autoconf.c revision 1.36
11.36Sis/*	$NetBSD: autoconf.c,v 1.36 1996/05/09 20:30:33 is Exp $	*/
21.25Scgd
31.1Smw/*
41.17Schopps * Copyright (c) 1994 Christian E. Hopps
51.1Smw * All rights reserved.
61.1Smw *
71.1Smw * Redistribution and use in source and binary forms, with or without
81.1Smw * modification, are permitted provided that the following conditions
91.1Smw * are met:
101.1Smw * 1. Redistributions of source code must retain the above copyright
111.1Smw *    notice, this list of conditions and the following disclaimer.
121.1Smw * 2. Redistributions in binary form must reproduce the above copyright
131.1Smw *    notice, this list of conditions and the following disclaimer in the
141.1Smw *    documentation and/or other materials provided with the distribution.
151.1Smw * 3. All advertising materials mentioning features or use of this software
161.1Smw *    must display the following acknowledgement:
171.17Schopps *      This product includes software developed by Christian E. Hopps.
181.17Schopps * 4. The name of the author may not be used to endorse or promote products
191.17Schopps *    derived from this software without specific prior written permission
201.4Smw *
211.17Schopps * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
221.17Schopps * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
231.17Schopps * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
241.17Schopps * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
251.17Schopps * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
261.17Schopps * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
271.17Schopps * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
281.17Schopps * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
291.17Schopps * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
301.17Schopps * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
311.1Smw */
321.9Schopps#include <sys/param.h>
331.9Schopps#include <sys/systm.h>
341.17Schopps#include <sys/reboot.h>
351.9Schopps#include <sys/conf.h>
361.17Schopps#include <sys/device.h>
371.17Schopps#include <sys/disklabel.h>
381.19Schopps#include <machine/cpu.h>
391.17Schopps#include <amiga/amiga/cfdev.h>
401.17Schopps#include <amiga/amiga/device.h>
411.9Schopps#include <amiga/amiga/custom.h>
421.1Smw
431.11Schoppsvoid setroot __P((void));
441.11Schoppsvoid swapconf __P((void));
451.17Schoppsvoid mbattach __P((struct device *, struct device *, void *));
461.17Schoppsint mbprint __P((void *, char *));
471.30Sthorpejint mbmatch __P((struct device *, void *, void *));
481.11Schopps
491.17Schoppsint cold;	/* 1 if still booting */
501.17Schopps#include <sys/kernel.h>
511.1Smw/*
521.17Schopps * called at boot time, configure all devices on system
531.1Smw */
541.11Schoppsvoid
551.1Smwconfigure()
561.1Smw{
571.17Schopps	/*
581.17Schopps	 * this is the real thing baby (i.e. not console init)
591.17Schopps	 */
601.17Schopps	amiga_realconfig = 1;
611.36Sis#ifdef DRACO
621.36Sis	if (is_draco()) {
631.36Sis		*draco_intena &= ~DRIRQ_GLOBAL;
641.36Sis	} else
651.36Sis#endif
661.3Smw	custom.intena = INTF_INTEN;
671.1Smw
681.31Scgd	if (config_rootfound("mainbus", "mainbus") == NULL)
691.17Schopps		panic("no mainbus found");
701.36Sis
711.36Sis	printf("survived autoconf, going to enable interrupts\n");
721.11Schopps
731.36Sis#ifdef DRACO
741.36Sis	if (is_draco()) {
751.36Sis		*draco_intena |= DRIRQ_GLOBAL;
761.36Sis		/* softints always enabled */
771.36Sis	} else
781.36Sis#endif
791.36Sis	{
801.36Sis		custom.intena = INTF_SETCLR | INTF_INTEN;
811.28Schopps
821.36Sis		/* also enable hardware aided software interrupts */
831.36Sis		custom.intena = INTF_SETCLR | INTF_SOFTINT;
841.36Sis	}
851.36Sis	printf("survived interrupt enable\n");
861.28Schopps
871.17Schopps#ifdef GENERIC
881.36Sis	if ((boothowto & RB_ASKNAME) == 0) {
891.1Smw		setroot();
901.36Sis		printf("survived setroot()\n");
911.36Sis	}
921.1Smw	setconf();
931.36Sis	printf("survived setconf()\n");
941.1Smw#else
951.1Smw	setroot();
961.36Sis	printf("survived setroot()\n");
971.1Smw#endif
981.36Sis	printf("survived root device search\n");
991.1Smw	swapconf();
1001.36Sis	printf("survived swap device search\n");
1011.1Smw	cold = 0;
1021.17Schopps}
1031.3Smw
1041.17Schopps/*ARGSUSED*/
1051.17Schoppsint
1061.17Schoppssimple_devprint(auxp, pnp)
1071.17Schopps	void *auxp;
1081.17Schopps	char *pnp;
1091.17Schopps{
1101.17Schopps	return(QUIET);
1111.1Smw}
1121.1Smw
1131.17Schoppsint
1141.17Schoppsmatchname(fp, sp)
1151.17Schopps	char *fp, *sp;
1161.17Schopps{
1171.17Schopps	int len;
1181.1Smw
1191.17Schopps	len = strlen(fp);
1201.17Schopps	if (strlen(sp) != len)
1211.17Schopps		return(0);
1221.17Schopps	if (bcmp(fp, sp, len) == 0)
1231.17Schopps		return(1);
1241.17Schopps	return(0);
1251.17Schopps}
1261.1Smw
1271.17Schopps/*
1281.17Schopps * use config_search to find appropriate device, then call that device
1291.17Schopps * directly with NULL device variable storage.  A device can then
1301.17Schopps * always tell the difference betwean the real and console init
1311.17Schopps * by checking for NULL.
1321.17Schopps */
1331.11Schoppsint
1341.17Schoppsamiga_config_found(pcfp, pdp, auxp, pfn)
1351.17Schopps	struct cfdata *pcfp;
1361.17Schopps	struct device *pdp;
1371.17Schopps	void *auxp;
1381.17Schopps	cfprint_t pfn;
1391.1Smw{
1401.17Schopps	struct device temp;
1411.17Schopps	struct cfdata *cf;
1421.17Schopps
1431.17Schopps	if (amiga_realconfig)
1441.31Scgd		return(config_found(pdp, auxp, pfn) != NULL);
1451.17Schopps
1461.17Schopps	if (pdp == NULL)
1471.17Schopps		pdp = &temp;
1481.17Schopps
1491.17Schopps	pdp->dv_cfdata = pcfp;
1501.17Schopps	if ((cf = config_search((cfmatch_t)NULL, pdp, auxp)) != NULL) {
1511.30Sthorpej		cf->cf_attach->ca_attach(pdp, NULL, auxp);
1521.17Schopps		pdp->dv_cfdata = NULL;
1531.17Schopps		return(1);
1541.1Smw	}
1551.17Schopps	pdp->dv_cfdata = NULL;
1561.17Schopps	return(0);
1571.17Schopps}
1581.17Schopps
1591.17Schopps/*
1601.17Schopps * this function needs to get enough configured to do a console
1611.17Schopps * basically this means start attaching the grfxx's that support
1621.17Schopps * the console. Kinda hacky but it works.
1631.17Schopps */
1641.32Sveegovoid
1651.17Schoppsconfig_console()
1661.17Schopps{
1671.17Schopps	struct cfdata *cf;
1681.17Schopps
1691.36Sis	int i;
1701.36Sis
1711.17Schopps	/*
1721.17Schopps	 * we need mainbus' cfdata.
1731.17Schopps	 */
1741.17Schopps	cf = config_rootsearch(NULL, "mainbus", "mainbus");
1751.36Sis	if (cf == NULL) {
1761.17Schopps		panic("no mainbus");
1771.36Sis	}
1781.1Smw	/*
1791.17Schopps	 * internal grf.
1801.1Smw	 */
1811.36Sis#ifdef DRACO
1821.36Sis	if (!(is_draco()))
1831.36Sis#endif
1841.36Sis		amiga_config_found(cf, NULL, "grfcc", NULL);
1851.1Smw	/*
1861.27Schopps	 * zbus knows when its not for real and will
1871.21Schopps	 * only configure the appropriate hardware
1881.1Smw	 */
1891.27Schopps	amiga_config_found(cf, NULL, "zbus", NULL);
1901.1Smw}
1911.1Smw
1921.17Schopps/*
1931.17Schopps * mainbus driver
1941.17Schopps */
1951.30Sthorpejstruct cfattach mainbus_ca = {
1961.30Sthorpej	sizeof(struct device), mbmatch, mbattach
1971.30Sthorpej};
1981.30Sthorpej
1991.30Sthorpejstruct cfdriver mainbus_cd = {
2001.30Sthorpej	NULL, "mainbus", DV_DULL, NULL, 0
2011.17Schopps};
2021.17Schopps
2031.11Schoppsint
2041.30Sthorpejmbmatch(pdp, match, auxp)
2051.17Schopps	struct device *pdp;
2061.30Sthorpej	void *match, *auxp;
2071.1Smw{
2081.30Sthorpej	struct cfdata *cfp = match;
2091.30Sthorpej
2101.17Schopps	if (cfp->cf_unit > 0)
2111.1Smw		return(0);
2121.1Smw	/*
2131.17Schopps	 * We are always here
2141.1Smw	 */
2151.1Smw	return(1);
2161.1Smw}
2171.1Smw
2181.1Smw/*
2191.17Schopps * "find" all the things that should be there.
2201.1Smw */
2211.11Schoppsvoid
2221.17Schoppsmbattach(pdp, dp, auxp)
2231.17Schopps	struct device *pdp, *dp;
2241.17Schopps	void *auxp;
2251.1Smw{
2261.19Schopps	printf ("\n");
2271.17Schopps	config_found(dp, "clock", simple_devprint);
2281.36Sis#ifdef DRACO
2291.36Sis	if (is_draco()) {
2301.36Sis		config_found(dp, "kbd", simple_devprint);
2311.36Sis		config_found(dp, "drsc", simple_devprint);
2321.36Sis		/*
2331.36Sis		 * XXX -- missing here:
2341.36Sis		 * SuperIO chip serial, parallel, floppy
2351.36Sis		 * or maybe just make that into a pseudo
2361.36Sis		 * ISA bus.
2371.36Sis		 */
2381.36Sis	} else
2391.36Sis#endif
2401.36Sis	{
2411.36Sis		config_found(dp, "ser", simple_devprint);
2421.36Sis		config_found(dp, "par", simple_devprint);
2431.36Sis		config_found(dp, "kbd", simple_devprint);
2441.36Sis		config_found(dp, "ms", simple_devprint);
2451.36Sis		config_found(dp, "ms", simple_devprint);
2461.36Sis		config_found(dp, "grfcc", simple_devprint);
2471.36Sis		config_found(dp, "fdc", simple_devprint);
2481.36Sis	}
2491.24Schopps	if (is_a4000() || is_a1200())
2501.23Schopps		config_found(dp, "idesc", simple_devprint);
2511.29Schopps	if (is_a4000())			/* Try to configure A4000T SCSI */
2521.29Schopps		config_found(dp, "afsc", simple_devprint);
2531.27Schopps	config_found(dp, "zbus", simple_devprint);
2541.17Schopps	if (is_a3000())
2551.17Schopps		config_found(dp, "ahsc", simple_devprint);
2561.1Smw}
2571.1Smw
2581.11Schoppsint
2591.17Schoppsmbprint(auxp, pnp)
2601.17Schopps	void *auxp;
2611.17Schopps	char *pnp;
2621.1Smw{
2631.17Schopps	if (pnp)
2641.17Schopps		printf("%s at %s", (char *)auxp, pnp);
2651.17Schopps	return(UNCONF);
2661.1Smw}
2671.1Smw
2681.11Schoppsvoid
2691.17Schoppsswapconf()
2701.1Smw{
2711.17Schopps	struct swdevt *swp;
2721.17Schopps	u_int maj;
2731.17Schopps	int nb;
2741.3Smw
2751.17Schopps	for (swp = swdevt; swp->sw_dev > 0; swp++) {
2761.17Schopps		maj = major(swp->sw_dev);
2771.5Smw
2781.17Schopps		if (maj > nblkdev)
2791.17Schopps			break;
2801.1Smw
2811.17Schopps		if (bdevsw[maj].d_psize) {
2821.17Schopps			nb = bdevsw[maj].d_psize(swp->sw_dev);
2831.17Schopps			if (nb > 0 &&
2841.17Schopps			    (swp->sw_nblks == 0 || swp->sw_nblks > nb))
2851.17Schopps				swp->sw_nblks = nb;
2861.17Schopps			else
2871.17Schopps				swp->sw_nblks = 0;
2881.1Smw		}
2891.17Schopps		swp->sw_nblks = ctod(dtoc(swp->sw_nblks));
2901.11Schopps	}
2911.17Schopps	if (dumplo == 0 && bdevsw[major(dumpdev)].d_psize)
2921.17Schopps	/*dumplo = (*bdevsw[major(dumpdev)].d_psize)(dumpdev) - physmem;*/
2931.17Schopps		dumplo = (*bdevsw[major(dumpdev)].d_psize)(dumpdev) -
2941.17Schopps			ctob(physmem)/DEV_BSIZE;
2951.17Schopps	if (dumplo < 0)
2961.17Schopps		dumplo = 0;
2971.17Schopps
2981.1Smw}
2991.1Smw
3001.17Schopps#define	DOSWAP			/* change swdevt and dumpdev */
3011.17Schoppsu_long	bootdev = 0;		/* should be dev_t, but not until 32 bits */
3021.1Smw
3031.1Smwstatic	char devname[][2] = {
3041.32Sveego	{ 0	,0	},
3051.32Sveego	{ 0	,0	},
3061.32Sveego	{ 'f'	,'d'	},	/* 2 = fd */
3071.32Sveego	{ 0	,0	},
3081.32Sveego	{ 's'	,'d'	}	/* 4 = sd -- new SCSI system */
3091.1Smw};
3101.1Smw
3111.11Schoppsvoid
3121.1Smwsetroot()
3131.1Smw{
3141.17Schopps	int majdev, mindev, unit, part, adaptor;
3151.32Sveego	dev_t temp = 0;
3161.32Sveego	dev_t orootdev;
3171.1Smw	struct swdevt *swp;
3181.1Smw
3191.1Smw	if (boothowto & RB_DFLTROOT ||
3201.17Schopps	    (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
3211.11Schopps		return;
3221.1Smw	majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
3231.17Schopps	if (majdev > sizeof(devname) / sizeof(devname[0]))
3241.11Schopps		return;
3251.1Smw	adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK;
3261.1Smw	part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
3271.1Smw	unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
3281.1Smw	orootdev = rootdev;
3291.17Schopps	rootdev = MAKEDISKDEV(majdev, unit, part);
3301.1Smw	/*
3311.1Smw	 * If the original rootdev is the same as the one
3321.1Smw	 * just calculated, don't need to adjust the swap configuration.
3331.1Smw	 */
3341.17Schopps	if (rootdev == orootdev)
3351.11Schopps		return;
3361.17Schopps	printf("changing root device to %c%c%d%c\n",
3371.1Smw		devname[majdev][0], devname[majdev][1],
3381.17Schopps		unit, part + 'a');
3391.1Smw#ifdef DOSWAP
3401.17Schopps	mindev = DISKUNIT(rootdev);
3411.1Smw	for (swp = swdevt; swp->sw_dev; swp++) {
3421.1Smw		if (majdev == major(swp->sw_dev) &&
3431.17Schopps		    mindev == DISKUNIT(swp->sw_dev)) {
3441.1Smw			temp = swdevt[0].sw_dev;
3451.1Smw			swdevt[0].sw_dev = swp->sw_dev;
3461.1Smw			swp->sw_dev = temp;
3471.1Smw			break;
3481.1Smw		}
3491.1Smw	}
3501.1Smw	if (swp->sw_dev == 0)
3511.1Smw		return;
3521.1Smw	/*
3531.1Smw	 * If dumpdev was the same as the old primary swap
3541.1Smw	 * device, move it to the new primary swap device.
3551.1Smw	 */
3561.1Smw	if (temp == dumpdev)
3571.1Smw		dumpdev = swdevt[0].sw_dev;
3581.1Smw#endif
3591.3Smw}
3601.3Smw
3611.17Schopps
3621.11Schopps/*
3631.11Schopps * Try to determine, of this machine is an A3000, which has a builtin
3641.11Schopps * realtime clock and scsi controller, so that this hardware is only
3651.11Schopps * included as "configured" if this IS an A3000
3661.11Schopps */
3671.5Smw
3681.5Smwint a3000_flag = 1;		/* patchable */
3691.5Smw#ifdef A4000
3701.5Smwint a4000_flag = 1;		/* patchable - default to A4000 */
3711.5Smw#else
3721.5Smwint a4000_flag = 0;		/* patchable */
3731.5Smw#endif
3741.5Smw
3751.3Smwint
3761.11Schoppsis_a3000()
3771.3Smw{
3781.11Schopps	/* this is a dirty kludge.. but how do you do this RIGHT ? :-) */
3791.22Schopps	extern long boot_fphystart;
3801.11Schopps	short sc;
3811.11Schopps
3821.19Schopps	if ((machineid >> 16) == 3000)
3831.19Schopps		return (1);			/* It's an A3000 */
3841.19Schopps	if (machineid >> 16)
3851.19Schopps		return (0);			/* It's not an A3000 */
3861.19Schopps	/* Machine type is unknown, so try to guess it */
3871.11Schopps	/* where is fastram on the A4000 ?? */
3881.11Schopps	/* if fastram is below 0x07000000, assume it's not an A3000 */
3891.22Schopps	if (boot_fphystart < 0x07000000)
3901.17Schopps		return(0);
3911.11Schopps	/*
3921.11Schopps	 * OK, fastram starts at or above 0x07000000, check specific
3931.11Schopps	 * machines
3941.11Schopps	 */
3951.17Schopps	for (sc = 0; sc < ncfdev; sc++) {
3961.17Schopps		switch (cfdev[sc].rom.manid) {
3971.17Schopps		case 2026:		/* Progressive Peripherals, Inc */
3981.17Schopps			switch (cfdev[sc].rom.prodid) {
3991.17Schopps			case 0:		/* PPI Mercury - A3000 */
4001.17Schopps			case 1:		/* PP&S A3000 '040 */
4011.17Schopps				return(1);
4021.17Schopps			case 150:	/* PPI Zeus - it's an A2000 */
4031.17Schopps			case 105:	/* PP&S A2000 '040 */
4041.17Schopps			case 187:	/* PP&S A500 '040 */
4051.17Schopps				return(0);
4061.11Schopps			}
4071.11Schopps			break;
4081.3Smw
4091.17Schopps		case 2112:			/* IVS */
4101.17Schopps			switch (cfdev[sc].rom.prodid) {
4111.17Schopps			case 242:
4121.17Schopps				return(0);	/* A2000 accelerator? */
4131.11Schopps			}
4141.11Schopps			break;
4151.11Schopps		}
4161.11Schopps	}
4171.17Schopps	return (a3000_flag);		/* XXX let flag tell now */
4181.5Smw}
4191.5Smw
4201.5Smwint
4211.11Schoppsis_a4000()
4221.5Smw{
4231.19Schopps	if ((machineid >> 16) == 4000)
4241.19Schopps		return (1);		/* It's an A4000 */
4251.24Schopps	if ((machineid >> 16) == 1200)
4261.24Schopps		return (0);		/* It's an A1200, so not A4000 */
4271.36Sis#ifdef DRACO
4281.36Sis	if (is_draco())
4291.36Sis		return (0);
4301.36Sis#endif
4311.24Schopps	/* Do I need this any more? */
4321.19Schopps	if ((custom.deniseid & 0xff) == 0xf8)
4331.19Schopps		return (1);
4341.19Schopps#ifdef DEBUG
4351.19Schopps	if (a4000_flag)
4361.19Schopps		printf ("Denise ID = %04x\n", (unsigned short)custom.deniseid);
4371.19Schopps#endif
4381.19Schopps	if (machineid >> 16)
4391.19Schopps		return (0);		/* It's not an A4000 */
4401.19Schopps	return (a4000_flag);		/* Machine type not set */
4411.24Schopps}
4421.24Schopps
4431.24Schoppsint
4441.24Schoppsis_a1200()
4451.24Schopps{
4461.24Schopps	if ((machineid >> 16) == 1200)
4471.24Schopps		return (1);		/* It's an A1200 */
4481.24Schopps	return (0);			/* Machine type not set */
4491.1Smw}
4501.36Sis
4511.36Sis#ifdef DRACO
4521.36Sisint
4531.36Sisis_draco()
4541.36Sis{
4551.36Sis	if ((machineid >> 24) == 0x7D)
4561.36Sis		return ((machineid >> 16) & 0xFF);
4571.36Sis	return (0);
4581.36Sis}
4591.36Sis#endif
460