xref: /netbsd-src/sys/arch/amigappc/amigappc/autoconf.c (revision adffd44b18fc9111b9196d383b86cc70ba367efb)
1 /*	$NetBSD: autoconf.c,v 1.11 2023/10/14 08:05:25 andvar 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 
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.11 2023/10/14 08:05:25 andvar Exp $");
35 
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/reboot.h>
39 #include <sys/conf.h>
40 #include <sys/buf.h>
41 #include <sys/device.h>
42 #include <sys/device_impl.h>	/* XXX autoconf abuse */
43 #include <sys/disklabel.h>
44 #include <sys/disk.h>
45 #include <sys/proc.h>
46 #include <sys/kernel.h>
47 #include <sys/cpu.h>
48 
49 #include <amiga/amiga/cfdev.h>
50 #include <amiga/amiga/device.h>
51 #include <amiga/amiga/custom.h>
52 
53 static void findroot(void);
54 
55 u_long boot_partition;
56 
57 int amiga_realconfig;
58 
59 /*
60  * called at boot time, configure all devices on system
61  */
62 void
cpu_configure(void)63 cpu_configure(void)
64 {
65 
66 	/*
67 	 * this is the real thing baby (i.e. not console init)
68 	 */
69 	amiga_realconfig = 1;
70 	custom.intena = INTF_INTEN;
71 
72 	if (config_rootfound("mainbus", NULL) == NULL)
73 		panic("configure: mainbus not configured");
74 
75 #ifdef DEBUG_KERNEL_START
76 	printf("survived autoconf, going to enable interrupts\n");
77 #endif
78 
79 	genppc_cpu_configure();
80 	custom.intena = INTF_SETCLR | INTF_INTEN;
81 
82 #ifdef DEBUG_KERNEL_START
83 	printf("survived configure...\n");
84 #endif
85 }
86 
87 void
cpu_rootconf(void)88 cpu_rootconf(void)
89 {
90 
91 	findroot();
92 #ifdef DEBUG_KERNEL_START
93 	printf("survived findroot()\n");
94 #endif
95 	rootconf();
96 }
97 
98 /*ARGSUSED*/
99 int
simple_devprint(void * aux,const char * pnp)100 simple_devprint(void *aux, const char *pnp)
101 {
102 
103 	return QUIET;
104 }
105 
106 int
matchname(const char * fp,const char * sp)107 matchname(const char *fp, const char *sp)
108 {
109 	int len;
110 
111 	len = strlen(fp);
112 	if (strlen(sp) != len)
113 		return 0;
114 	if (bcmp(fp, sp, len) == 0)
115 		return 1;
116 	return 0;
117 }
118 
119 /*
120  * use config_search_ia to find appropriate device, then call that device
121  * directly with NULL device variable storage.  A device can then
122  * always tell the difference between the real and console init
123  * by checking for NULL.
124  */
125 int
amiga_config_found(cfdata_t pcfp,device_t parent,void * aux,cfprint_t pfn,const struct cfargs * cfargs)126 amiga_config_found(cfdata_t pcfp, device_t parent, void *aux, cfprint_t pfn,
127     const struct cfargs *cfargs)
128 {
129 	struct device temp;
130 	cfdata_t cf;
131 	const struct cfattach *ca;
132 	int rv = 0;
133 
134 	if (amiga_realconfig) {
135 		rv = config_found(parent, aux, pfn, cfargs) != NULL;
136 		goto out;
137 	}
138 
139 	if (parent == NULL) {
140 		memset(&temp, 0, sizeof temp);
141 		parent = &temp;
142 	}
143 
144 	parent->dv_cfdata = pcfp;
145 	parent->dv_cfdriver = config_cfdriver_lookup(pcfp->cf_name);
146 	parent->dv_unit = pcfp->cf_unit;
147 
148 	if ((cf = config_search(parent, aux,  cfargs)) != NULL) {
149 		ca = config_cfattach_lookup(cf->cf_name, cf->cf_atname);
150 		if (ca != NULL) {
151 			(*ca->ca_attach)(parent, NULL, aux);
152 			rv = 1;
153 		}
154 	}
155 	parent->dv_cfdata = NULL;
156  out:
157 	return rv;
158 }
159 
160 /*
161  * this function needs to get enough configured to do a console
162  * basically this means start attaching the grfxx's that support
163  * the console. Kinda hacky but it works.
164  */
165 void
config_console(void)166 config_console(void)
167 {
168 	cfdata_t cf;
169 
170 	config_init();
171 
172 	/*
173 	 * we need mainbus' cfdata.
174 	 */
175 	cf = config_rootsearch(NULL, "mainbus", NULL);
176 	if (cf == NULL)
177 		panic("no mainbus");
178 
179 	/*
180 	 * internal grf.
181 	 */
182 	amiga_config_found(cf, NULL, __UNCONST("grfcc"), NULL, CFARGS_NONE);
183 
184 	/*
185 	 * zbus knows when its not for real and will
186 	 * only configure the appropriate hardware
187 	 */
188 	amiga_config_found(cf, NULL, __UNCONST("zbus"), NULL, CFARGS_NONE);
189 }
190 
191 /*
192  * The system will assign the "booted device" indicator (and thus
193  * rootdev if rootspec is wildcarded) to the first partition 'a'
194  * in preference of boot.  However, it does walk unit backwards
195  * to remain compatible with the old Amiga method of picking the
196  * last root found.
197  */
198 #include <sys/fcntl.h>		/* XXXX and all that uses it */
199 #include <sys/proc.h>		/* XXXX and all that uses it */
200 
201 #include "fd.h"
202 #include "sd.h"
203 #include "cd.h"
204 #include "wd.h"
205 
206 #if NFD > 0
207 extern  struct cfdriver fd_cd;
208 extern	const struct bdevsw fd_bdevsw;
209 #endif
210 #if NSD > 0
211 extern  struct cfdriver sd_cd;
212 extern	const struct bdevsw sd_bdevsw;
213 #endif
214 #if NCD > 0
215 extern  struct cfdriver cd_cd;
216 extern	const struct bdevsw cd_bdevsw;
217 #endif
218 #if NWD > 0
219 extern  struct cfdriver wd_cd;
220 extern	const struct bdevsw wd_bdevsw;
221 #endif
222 
223 struct cfdriver *genericconf[] = {
224 #if NFD > 0
225 	&fd_cd,
226 #endif
227 #if NSD > 0
228 	&sd_cd,
229 #endif
230 #if NWD > 0
231 	&wd_cd,
232 #endif
233 #if NCD > 0
234 	&cd_cd,
235 #endif
236 	NULL,
237 };
238 
239 void
findroot(void)240 findroot(void)
241 {
242 	struct disk *dkp;
243 	struct partition *pp;
244 	device_t*devs;
245 	int i, maj, unit;
246 	const struct bdevsw *bdp;
247 
248 #if NSD > 0
249 	/*
250 	 * If we have the boot partition offset (boot_partition), try
251 	 * to locate the device corresponding to that partition.
252 	 */
253 #ifdef DEBUG_KERNEL_START
254 	printf("Boot partition offset is %ld\n", boot_partition);
255 #endif
256 	if (boot_partition != 0) {
257 
258 		for (unit = 0; unit < sd_cd.cd_ndevs; ++unit) {
259 #ifdef DEBUG_KERNEL_START
260 			printf("probing for sd%d\n", unit);
261 #endif
262 			if (sd_cd.cd_devs[unit] == NULL)
263 				continue;
264 
265 			/*
266 			 * Find the disk corresponding to the current
267 			 * device.
268 			 */
269 			devs = sd_cd.cd_devs;
270 			if ((dkp = disk_find(device_xname(devs[unit]))) == NULL)
271 				continue;
272 
273 			if (dkp->dk_driver == NULL ||
274 			    dkp->dk_driver->d_strategy == NULL)
275 				continue;
276 			bdp = &sd_bdevsw;
277 			maj = bdevsw_lookup_major(bdp);
278 			if ((*bdp->d_open)(MAKEDISKDEV(maj, unit, RAW_PART),
279 			    FREAD | FNONBLOCK, 0, curlwp))
280 				continue;
281 			(*bdp->d_close)(MAKEDISKDEV(maj, unit, RAW_PART),
282 			    FREAD | FNONBLOCK, 0, curlwp);
283 			pp = &dkp->dk_label->d_partitions[0];
284 			for (i = 0; i < dkp->dk_label->d_npartitions;
285 			    i++, pp++) {
286 #ifdef DEBUG_KERNEL_START
287 				printf("sd%d%c type %d offset %d size %d\n",
288 					unit, i+'a', pp->p_fstype,
289 					pp->p_offset, pp->p_size);
290 #endif
291 				if (pp->p_size == 0 ||
292 				    (pp->p_fstype != FS_BSDFFS &&
293 				    pp->p_fstype != FS_SWAP))
294 					continue;
295 				if (pp->p_offset == boot_partition) {
296 					if (booted_device == NULL) {
297 						booted_device = devs[unit];
298 						booted_partition = i;
299 					} else
300 						printf("Ambiguous boot device\n");
301 				}
302 			}
303 		}
304 	}
305 	if (booted_device != NULL)
306 		return;		/* we found the boot device */
307 #endif
308 
309 	for (i = 0; genericconf[i] != NULL; i++) {
310 		for (unit = genericconf[i]->cd_ndevs - 1; unit >= 0; unit--) {
311 			if (genericconf[i]->cd_devs[unit] == NULL)
312 				continue;
313 
314 			/*
315 			 * Find the disk structure corresponding to the
316 			 * current device.
317 			 */
318 			devs = genericconf[i]->cd_devs;
319 			if ((dkp = disk_find(device_xname(devs[unit]))) == NULL)
320 				continue;
321 
322 			if (dkp->dk_driver == NULL ||
323 			    dkp->dk_driver->d_strategy == NULL)
324 				continue;
325 
326 			bdp = NULL;
327 #if NFD > 0
328 			if (fd_bdevsw.d_strategy == dkp->dk_driver->d_strategy)
329 				bdp = &fd_bdevsw;
330 #endif
331 #if NSD > 0
332 			if (sd_bdevsw.d_strategy == dkp->dk_driver->d_strategy)
333 				bdp = &sd_bdevsw;
334 #endif
335 #if NWD > 0
336 			if (wd_bdevsw.d_strategy == dkp->dk_driver->d_strategy)
337 				bdp = &wd_bdevsw;
338 #endif
339 #if NCD > 0
340 			if (cd_bdevsw.d_strategy == dkp->dk_driver->d_strategy)
341 				bdp = &cd_bdevsw;
342 #endif
343 #ifdef DIAGNOSTIC
344 			if (bdp == NULL)
345 				panic("findroot: impossible");
346 #endif
347 			maj = bdevsw_lookup_major(bdp);
348 
349 			/* Open disk; forces read of disklabel. */
350 			if ((*bdp->d_open)(MAKEDISKDEV(maj,
351 			    unit, 0), FREAD|FNONBLOCK, 0, &lwp0))
352 				continue;
353 			(void)(*bdp->d_close)(MAKEDISKDEV(maj,
354 			    unit, 0), FREAD|FNONBLOCK, 0, &lwp0);
355 
356 			pp = &dkp->dk_label->d_partitions[0];
357 			if (pp->p_size != 0 && pp->p_fstype == FS_BSDFFS) {
358 				booted_device = devs[unit];
359 				booted_partition = 0;
360 				return;
361 			}
362 		}
363 	}
364 }
365 
366 /*
367  * Try to determine, if this machine is an A3000, which has a builtin
368  * realtime clock and scsi controller, so that this hardware is only
369  * included as "configured" if this IS an A3000
370  */
371 int a3000_flag = 1;		/* patchable */
372 #ifdef A4000
373 int a4000_flag = 1;		/* patchable - default to A4000 */
374 #else
375 int a4000_flag = 0;		/* patchable */
376 #endif
377 
378 int
is_a3000(void)379 is_a3000(void)
380 {
381 	/* this is a dirty kludge.. but how do you do this RIGHT ? :-) */
382 	extern long boot_fphystart;
383 	short sc;
384 
385 	if ((machineid >> 16) == 3000)
386 		return 1;			/* It's an A3000 */
387 	if (machineid >> 16)
388 		return 0;			/* It's not an A3000 */
389 	/* Machine type is unknown, so try to guess it */
390 	/* where is fastram on the A4000 ?? */
391 	/* if fastram is below 0x07000000, assume it's not an A3000 */
392 	if (boot_fphystart < 0x07000000)
393 		return 0;
394 	/*
395 	 * OK, fastram starts at or above 0x07000000, check specific
396 	 * machines
397 	 */
398 	for (sc = 0; sc < ncfdev; sc++) {
399 		switch (cfdev[sc].rom.manid) {
400 		case 2026:		/* Progressive Peripherals, Inc */
401 			switch (cfdev[sc].rom.prodid) {
402 			case 0:		/* PPI Mercury - A3000 */
403 			case 1:		/* PP&S A3000 '040 */
404 				return 1;
405 			case 150:	/* PPI Zeus - it's an A2000 */
406 			case 105:	/* PP&S A2000 '040 */
407 			case 187:	/* PP&S A500 '040 */
408 				return 0;
409 			}
410 			break;
411 
412 		case 2112:			/* IVS */
413 			switch (cfdev[sc].rom.prodid) {
414 			case 242:
415 				return 0;	/* A2000 accelerator? */
416 			}
417 			break;
418 		}
419 	}
420 	return a3000_flag;		/* XXX let flag tell now */
421 }
422 
423 int
is_a4000(void)424 is_a4000(void)
425 {
426 
427 	if ((machineid >> 16) == 4000)
428 		return 1;		/* It's an A4000 */
429 	if ((machineid >> 16) == 1200)
430 		return 0;		/* It's an A1200, so not A4000 */
431 	/* Do I need this any more? */
432 	if ((custom.deniseid & 0xff) == 0xf8)
433 		return 1;
434 #ifdef DEBUG
435 	if (a4000_flag)
436 		printf("Denise ID = %04x\n", (unsigned short)custom.deniseid);
437 #endif
438 	if (machineid >> 16)
439 		return 0;		/* It's not an A4000 */
440 	return a4000_flag;		/* Machine type not set */
441 }
442 
443 int
is_a1200(void)444 is_a1200(void)
445 {
446 
447 	if ((machineid >> 16) == 1200)
448 		return 1;		/* It's an A1200 */
449 	return 0;			/* Machine type not set */
450 }
451