static char rcsid[] = "$Header: swapgeneric.c,v 820.1 86/12/04 19:54:12 root Exp $";
static char sccsid[]="%W% %Y% %Q% %G%";

/************************************************************************
*									*
*			Copyright 1984 - 1986				*
*			VALID LOGIC SYSTEMS INCORPORATED		*
*									*
*	This listing contains confidential proprietary information	*
*	which is not to be disclosed to unauthorized persons without	*
*	written consent of an officer of Valid Logic Systems 		*
*	Incorporated.							*
*									*
*	The copyright notice appearing above is included to provide	*
*	statutory protection in the event of unauthorized or 		*
*	unintentional public disclosure.				*
*									*
************************************************************************/

#include "../machine/pte.h"

#include "../h/param.h"
#include "../h/conf.h"
#include "../h/buf.h"
#include "../h/vm.h"
#include "../h/systm.h"
#include "../h/reboot.h"

#include "../s32dev/mbvar.h"
#include "is.h"

/*
 * Generic configuration;  all in one
 */
dev_t	rootdev, argdev, dumpdev;
int	nswap;
struct	swdevt swdevt[] = {
     /*
      *  dev,  freed,  nblks
      */
	{ -1,	1,	0 },
	{ 0,	0,	0 },
};

int	boothowto = 0;			/* Defined in h/systm.h */

#if NIS > 0
extern	struct mb_driver isdriver;
#endif NIS > 0
extern	struct mb_driver rfdriver;

struct	genericconf {
	struct mb_driver *gc_driver;
	char	*gc_name;
	dev_t	gc_root;
	dev_t	gc_swap;
} genericconf[] = {
	{ &rfdriver,	"rd",	makedev(5, 6), makedev(5, 9), },
#if NIS > 0
	{ &isdriver,	"id",	makedev(0, 6), makedev(0, 2), },
#endif NIS > 0
	{ 0 },
};

#ifdef	s32	/* ROOT_ANYWHERE */
/*
 * From s32/locore.s: tells us from whence we didst boot.
 */
extern char *bootline;
#endif	s32	/* ROOT_ANYWHERE */

setconf()
{
	register struct mb_device *md;
	register struct genericconf *gc;
	int unit, swaponroot = 0;
#ifdef	s32	/* ROOT_ANYWHERE */
	label_t jb, *saved_jb;
	extern label_t *nofault;
#endif	s32	/* ROOT_ANYWHERE */

	if (boothowto & RB_ASKNAME) {
		char name[128];
retry:
		printf("root device? ");
		gets(name);
		/*
		 * Format of this string is:
		 * dd[0-7]
		 *
		 * dd is two character device type, E.G. "id", "rd".
		 * the number dictates unit number.
		 */
		for (gc = genericconf; gc->gc_driver; gc++)
			if (gc->gc_name[0] == name[0] &&
			    gc->gc_name[1] == name[1])
				goto gotit;
		goto bad;
gotit:
#ifdef notdef
		/*
		 * The following code is a no-op because, if name[3] == '*',
		 * then (in the following if statement) name[3] != 0, and
		 * we make the silly user try again.
		 * (bog 051986)
		 */
		if (name[3] == '*') {
			name[3] = name[4];
			swaponroot++;
		}
#endif notdef
		if (name[2] >= '0' && name[2] <= '7' && name[3] == 0) {
			unit = name[2] - '0';
			goto found;
		}
		printf("bad/missing unit number\n");
bad:
		printf("use one of:");
		for (gc = genericconf; gc->gc_driver; gc++)
			printf(" %s%%d", gc->gc_name);
		printf("\n");
		goto retry;
	}
	unit = 0;
#ifdef	s32	/* ROOT_ANYWHERE */
	/*
	 * Consult the bootline to find out where we booted from: 
	 * that should beour root device. For now, we only examine the
	 * first two characters of the bootline, which give us the device
	 * type (id, rd)
	 *
	 * Yicch. We have strings -- "id", "rd" -- in three or more
	 * spots, independently. Here, in conf/COMPILE, and in the boot code.
	 * Not to mention numerous other corners of the kernel.  This crap
	 * should ALL be centralized.
	 *
	 * ``But how, Batman -- HOW?''
	 */
	/*
	 * Prepare for bus errors in dealing with stuff from the boot code.
	 */
	saved_jb = nofault;
	if (! setjmp(&jb))
	{
		/* No bus error */
		nofault = &jb;
#ifdef notdef
		printf("setconf: bootline = 0x%x, = \"%s\"\n",bootline,bootline);
#endif notdef
		bootline[2] = '\0'; /* XXX */
		for (gc = genericconf; gc->gc_driver; gc++)
		{
#ifdef notdef
			printf("setconf: compare bootline to \"%s\"\n",
				gc->gc_name);
#endif notdef
			if (!strcmp(bootline,gc->gc_name,2))
			{
				/*
				 * Found a genericconf struct with same device
				 * as the boot code booted from.
				 */
				break;
			}
		}
		if (gc->gc_driver)
		{
			/*
			 * Success in getting the right device
			 * from the boot code.
			 */
			printf("Root on %s%d\n",
				gc->gc_name, 0);
			goto found;
		}
#ifdef DEBUG
		printf("setconf: I see no root of any kind here.\n");
#endif DEBUG
	}
	else
	{
	    /* bogus boot code */
	    printf("setconf: bus error reading bootline.\n");
#endif	s32	/* ROOT_ANYWHERE */

	    /*
	     * Find the first possible thing we can swap on by the following:
	     *
	     *	for each generic conf device, do:
	     *		if there's a device on mbdinit that matches,
	     *		driver-for-driver, then swap on it.
	     */
	    for (gc = genericconf; gc->gc_driver; gc++) {
		    for (md = mbdinit; md->md_driver; md++) {
			    if (md->md_alive == 0)
				    continue;
			    if (md->md_unit == 0 && md->md_dk != -1 &&
			        md->md_driver == gc->gc_driver) {
				    printf("root on %s0\n",
				        md->md_driver->mdr_dname);
				    goto found;
			    }
		    }
	    }
	    /*
	     * Bootstrap becomes a necktie to pull ourselves up by...
	     */
	    printf("no suitable root\n");
	    for (;;)
		    ;
#ifdef	s32	/* ROOT_ANYWHERE */
	}
found:
	nofault = saved_jb;
#else	s32	/* ROOT_ANYWHERE */
found:
#endif	s32	/* ROOT_ANYWHERE */
	/*
	 * Gross, but what can we do?
	 * (16 partitions) * unit number gives minor device number of
	 * 0 partition of disk; +6 for the root partition
	 * (partition 6 by convention).
	 */
	gc->gc_root = makedev(major(gc->gc_root), unit*16 + 6);
	rootdev = gc->gc_root;
	swdevt[0].sw_dev = argdev = dumpdev = gc->gc_swap;
	/* swap size and dumplo set during autoconfigure */
	if (swaponroot)
		rootdev = dumpdev;
}
