Home | History | Annotate | Line # | Download | only in amigappc
      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
     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
     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
    100 simple_devprint(void *aux, const char *pnp)
    101 {
    102 
    103 	return QUIET;
    104 }
    105 
    106 int
    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
    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
    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
    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
    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
    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
    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