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