File:  [Research Unix] / researchv9 / sys / conf / src / config / config.y
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:59 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv9-SUN3_old, researchv9-SUN3, HEAD
researchv9-SUN3(old)

%union {
	int i;
	char *cp;
	struct idlst *idlst;
}
%token CPU IDENT CONFIG ANY DEVICE UBA MBA NEXUS CSR DRIVE VECTOR OPTIONS
%token CONTROLLER PSEUDO_DEVICE FLAGS ID SEMICOLON NUMBER FPNUMBER TRACE
%token DISK SLAVE AT HZ TIMEZONE DST MAXUSERS MASTER MAKEFILE COMMA MINUS
%token MACHINE PRIORITY
%token VME16D16 VME24D16 VME32D16 VME16D32 VME24D32 VME32D32
%type <cp> Save_id ID Dev
%type <i> NUMBER FPNUMBER
%type <idlst> Id_list
%{
/*	config.y	1.11	81/05/22	*/
#include "config.h"
#include <stdio.h>
	struct device cur;
	struct device *curp = NULL;
	char *temp_id;
%}
%%
Configuration:
	Many_specs
	;

Many_specs:
	Many_specs Spec
	|
	;

Spec:
	Device_spec SEMICOLON  = { newdev(&cur); } |
	Config_spec SEMICOLON |
	TRACE SEMICOLON = { do_trace = ! do_trace; } |
	SEMICOLON |
	error SEMICOLON
	;

Config_spec:
	MACHINE Save_id
	    = {
		if (eq($2, "vax")) {
			machine = MACHINE_VAX;
			machinename = "vax";
		} else if (eq($2, "sun2")) {
			machine = MACHINE_SUN2;
			machinename = "sun2";
		} else if (eq($2, "sun3")) {
			machine = MACHINE_SUN3;
			machinename = "sun3";
		} else
			yyerror("Unknown machine type");
	      } |
	CPU Save_id = {
		    struct cputype *cp = (struct cputype *)malloc(sizeof (struct cputype));
		    cp->cpu_name = ns($2);
		    cp->cpu_next = cputype;
		    cputype = cp;
		    free(temp_id);
		    } |
	OPTIONS Opt_list |
	IDENT ID { ident = ns($2); } |
	CONFIG Save_id ID = { mkconf(temp_id, $3); free(temp_id); } |
	HZ NUMBER = {
		yyerror("HZ specification obsolete; delete");
		hz = 60;
		} |
	TIMEZONE NUMBER = { timezone = 60 * $2; check_tz(); } |
	TIMEZONE NUMBER DST = { timezone = 60 * $2; dst = 1; check_tz(); } |
	TIMEZONE FPNUMBER = { timezone = $2; check_tz(); } |
	TIMEZONE FPNUMBER DST = { timezone = $2; dst = 1; check_tz(); } |
	MINUS TIMEZONE NUMBER =
	    { timezone = -60 * $3; check_tz(); } |
	MINUS TIMEZONE NUMBER DST =
	    { timezone = -60 * $3; dst = 1; check_tz(); } |
	MINUS TIMEZONE FPNUMBER =
	    { timezone = -$3; check_tz(); } |
	MINUS TIMEZONE FPNUMBER DST =
	    { timezone = -$3; dst = 1; check_tz(); } |
	MAKEFILE ID =
	    { mkfile = ns($2); } |
	MAXUSERS NUMBER = { maxusers = $2; }
	;

Opt_list:
	Opt_list COMMA Option |
	Option
	;

Option:
	Save_id = {
		    struct opt *op = (struct opt *)malloc(sizeof (struct opt));
		    op->op_name = ns($1);
		    op->op_next = opt;
		    opt = op;
		    free(temp_id);
	}
	;

Save_id:
	ID = { $$ = temp_id = ns($1); }
	;

Dev:
	UBA
	      = {
		if (machine != MACHINE_VAX)
			yyerror("wrong machine type for uba");
		$$ = ns("uba");
		} |
	MBA
	      = {
		if (machine != MACHINE_VAX)
			yyerror("wrong machine type for mba");
		$$ = ns("mba");
		} |
	VME16D16
	      = {
		if (machine != MACHINE_SUN2 && machine != MACHINE_SUN3)
			yyerror("wrong machine type for vme16d16");
		$$ = ns("vme16d16");
		} |
	VME24D16
	      = {
		if (machine != MACHINE_SUN2 && machine != MACHINE_SUN3)
			yyerror("wrong machine type for vme24d16");
		$$ = ns("vme24d16");
		} |
	VME32D16
	      = {
		if (machine != MACHINE_SUN3)
			yyerror("wrong machine type for vme32d16");
		$$ = ns("vme32d16");
		} |
	VME16D32
	      = {
		if (machine != MACHINE_SUN3)
			yyerror("wrong machine type for vme16d32");
		$$ = ns("vme16d32");
		} |
	VME24D32
	      = {
		if (machine != MACHINE_SUN3)
			yyerror("wrong machine type for vme24d32");
		$$ = ns("vme24d32");
		} |
	VME32D32
	      = {
		if (machine != MACHINE_SUN3)
			yyerror("wrong machine type for vme32d32");
		$$ = ns("vme32d32");
		} |
	ID = { $$ = ns($1); }
	;

Device_spec:
	DEVICE Dev_name Dev_info Int_spec = {  cur.d_type = DEVICE; } |
	MASTER Dev_name Dev_info Int_spec = {  cur.d_type = MASTER; } |
	DISK Dev_name Dev_info Int_spec =
				{  cur.d_dk = 1; cur.d_type = DEVICE; } |
	CONTROLLER Dev_name Dev_info Int_spec = {  cur.d_type = CONTROLLER; } |
	PSEUDO_DEVICE Init_dev Dev =
			{ cur.d_name = $3; cur.d_type = PSEUDO_DEVICE; } |
	PSEUDO_DEVICE Init_dev Dev NUMBER =
			{ cur.d_name = $3; cur.d_type = PSEUDO_DEVICE;
			  cur.d_count = $4; }
	;

Dev_name:
	Init_dev Dev NUMBER =	{
			cur.d_name = $2;
			if (eq($2, "mba"))
			    seen_mba = TRUE;
			else if (eq($2, "uba"))
			    seen_uba = TRUE;
			cur.d_unit = $3;
		}
	;

Init_dev:
	= { init_dev(&cur); }
	;

Dev_info:
	Con_info Info_list
	|
	;

Con_info:
	AT Dev NUMBER = {
		if (eq(cur.d_name, "mba") || eq(cur.d_name, "uba")) {
			sprintf(errbuf,
				"%s must be connected to a nexus", cur.d_name);
			yyerror(errbuf);
		}
		cur.d_conn = connect($2, $3);
	} |
	AT NEXUS NUMBER = { check_nexus(&cur, $3); cur.d_conn = TO_NEXUS; }
	;
    
Info_list:
	Info_list Info
	|
	;

Info:
	CSR NUMBER
		{
		cur.d_addr = $2;
		if (machine == MACHINE_SUN2 || machine == MACHINE_SUN3)
			bus_encode($2, &cur);
		} |
	DRIVE NUMBER = { cur.d_drive = $2; } |
	SLAVE NUMBER =
	{
		if (cur.d_conn != NULL && cur.d_conn != TO_NEXUS
		    && cur.d_conn->d_type == MASTER)
			cur.d_slave = $2;
		else
			yyerror("can't specify slave--not to master");
	} |
	FLAGS NUMBER = { cur.d_flags = $2; }
	;

Int_spec:
	Vec_spec
	      = { cur.d_pri = 0; } |
	PRIORITY NUMBER
	      = { cur.d_pri = $2; } |
	Vec_spec PRIORITY NUMBER
	      = { cur.d_pri = $3; } |
	PRIORITY NUMBER Vec_spec
	      = { cur.d_pri = $2; } |
	/* lambda */
		;

Vec_spec:
	VECTOR Id_list = { cur.d_vec = $2; };

Id_list:
	Save_id =
	    { struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst));
	      a->id = $1; a->id_next = 0; a->vec = 0; $$ = a; } |
	Save_id NUMBER =
	    { struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst));
	      a->id = $1; a->id_next = 0; a->vec = $2; $$ = a; } |
	Save_id Id_list =
	    { struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst));
	      a->id = $1; a->id_next = $2; a->vec = 0; $$ = a; } |
	Save_id NUMBER Id_list
	    { struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst));
	      a->id = $1; a->id_next = $3; a->vec = $2; $$ = a; };

%%

yyerror(s)
char *s;
{
	fprintf(stderr, "config: %s at line %d\n", s, yyline);
}

/*
 * ns:
 *	Return the passed string in a new space
 */

char *
ns(str)
register char *str;
{
	register char *cp;

	cp = malloc(strlen(str)+1);
	strcpy(cp, str);
	return cp;
}

/*
 * newdev
 *	Add a device to the list
 */

newdev(dp)
register struct device *dp;
{
	register struct device *np;

	np = (struct device *) malloc(sizeof *np);
	*np = *dp;
	if (curp == NULL)
		dtab = np;
	else
		curp->d_next = np;
	curp = np;
}

/*
 * mkconf
 *	Note that a configuration should be made
 */

mkconf(dev, sysname)
char *dev, *sysname;
{
	register struct file_list *fl;

	fl = (struct file_list *) malloc(sizeof *fl);
	fl->f_fn = ns(dev);
	fl->f_needs = ns(sysname);
	if (confp == NULL)
	    conf_list = fl;
	else
	    confp->f_next = fl;
	confp = fl;
}

/*
 * Connect:
 *	Find the pointer to connect to the given device and number.
 *	returns NULL if no such device and prints an error message
 */

struct device *connect(dev, num)
register char *dev;
register int num;
{
	register struct device *dp;
	struct device *huhcon();

	if (num == QUES)
	    return huhcon(dev);
	for (dp = dtab; dp != NULL; dp = dp->d_next)
		if ((num == dp->d_unit) && eq(dev, dp->d_name))
		    if (dp->d_type != CONTROLLER && dp->d_type != MASTER)
		    {
			sprintf(errbuf, "%s connected to non-controller", dev);
			yyerror(errbuf);
			return NULL;
		    }
		    else
			return dp;
	sprintf(errbuf, "%s %d not defined", dev, num);
	yyerror(errbuf);
	return NULL;
}

/*
 * huhcon
 *	Connect to an unspecific thing
 */

struct device *huhcon(dev)
register char *dev;
{
    register struct device *dp, *dcp;
    struct device rdev;
    int oldtype;

    /*
     * First make certain that there are some of these to wildcard on
     */
    for (dp = dtab; dp != NULL; dp = dp->d_next)
	if (eq(dp->d_name, dev))
	    break;
    if (dp == NULL)
    {
	sprintf(errbuf, "no %s's to wildcard", dev);
	yyerror(errbuf);
	return NULL;
    }
    oldtype = dp->d_type;
    dcp = dp->d_conn;
    /*
     * Now see if there is already a wildcard entry for this device
     * (e.g. Search for a "uba ?")
     */
    for (; dp != NULL; dp = dp->d_next)
	if (eq(dev, dp->d_name) && dp->d_unit == -1)
	    break;
    /*
     * If there isn't, make one becuase everything needs to be connected
     * to something.
     */
    if (dp == NULL)
    {
	dp = &rdev;
	init_dev(dp);
	dp->d_unit = QUES;
	dp->d_name = ns(dev);
	dp->d_type = oldtype;
	newdev(dp);
	dp = curp;
	/*
	 * Connect it to the same thing that other similar things are
	 * connected to, but make sure it is a wildcard unit
	 * (e.g. up connected to sc ?, here we make connect sc? to a uba?)
	 * If other things like this are on the NEXUS or if the aren't
	 * connected to anything, then make the same connection, else
	 * call ourself to connect to another unspecific device.
	 */
	if (dcp == TO_NEXUS || dcp == NULL)
	    dp->d_conn = dcp;
	else
	    dp->d_conn = connect(dcp->d_name, QUES);
    }
    return dp;
}

/*
 * init_dev:
 *	Set up the fields in the current device to their
 *	default values.
 */

init_dev(dp)
register struct device *dp;
{
    dp->d_name = "OHNO!!!";
    dp->d_type = DEVICE;
    dp->d_conn = NULL;
    dp->d_vec = NULL;
    dp->d_addr = UNKNOWN;
    dp->d_flags = dp->d_dk = 0;
    dp->d_slave = dp->d_drive = dp->d_unit = UNKNOWN;
    dp->d_count = 0;
    dp->d_mach = dp->d_bus = 0;
    dp->d_pri = 0;
}

/*
 * Check_nexus:
 *	Make certain that this is a reasonable type of thing to put
 *	on the nexus.
 */

check_nexus(dev, num)
register struct device *dev;
int num;
{
	switch (machine) {

	case MACHINE_VAX:
		if (!eq(dev->d_name, "uba") && !eq(dev->d_name, "mba"))
			yyerror("only uba's and mba's should be connected to the nexus");
		if (num != QUES)
			yyerror("can't give specific nexus numbers");
		break;

	case MACHINE_SUN2:
		if (!eq(dev->d_name, "virtual") &&
		    !eq(dev->d_name, "obmem") &&
		    !eq(dev->d_name, "obio") &&
		    !eq(dev->d_name, "mbmem") &&
		    !eq(dev->d_name, "mbio") &&
		    !eq(dev->d_name, "vme16d16") &&
		    !eq(dev->d_name, "vme24d16")) {
			(void)sprintf(errbuf,
			    "unknown bus type `%s' for nexus connection on %s",
			    dev->d_name, machinename);
			yyerror(errbuf);
		}
		break;

	case MACHINE_SUN3:
		if (!eq(dev->d_name, "virtual") &&
		    !eq(dev->d_name, "obmem") &&
		    !eq(dev->d_name, "obio") &&
		    !eq(dev->d_name, "vme16d16") &&
		    !eq(dev->d_name, "vme24d16") &&
		    !eq(dev->d_name, "vme32d16") &&
		    !eq(dev->d_name, "vme16d32") &&
		    !eq(dev->d_name, "vme24d32") &&
		    !eq(dev->d_name, "vme32d32")) {
			(void)sprintf(errbuf,
			    "unknown bus type `%s' for nexus connection on %s",
			    dev->d_name, machinename);
			yyerror(errbuf);
		}
		break;
	}
}

/*
 * Check the timezone to make certain it is sensible
 */

check_tz()
{
	if (timezone > 24 * 60)
		yyerror("timezone is unreasonable");
	else
		hadtz = TRUE;
}

/*
 * bi_info gives the magic number used to construct the token for
 * the autoconf code.  bi_max is the maximum value (across all
 * machine types for a given architecture) that a given "bus
 * type" can legally have.
 */
struct bus_info {
	char	*bi_name;
	u_short	bi_info;
	u_int	bi_max;
};

struct bus_info sun2_info[] = {
	{ "virtual",	0x0001,	(1<<24)-1 },
	{ "obmem",	0x0002,	(1<<23)-1 },
	{ "obio",	0x0004,	(1<<23)-1 },
	{ "mbmem",	0x0010,	(1<<20)-1 },
	{ "mbio",	0x0020,	(1<<16)-1 },
	{ "vme16d16",	0x0100,	(1<<16)-1 },
	{ "vme24d16",	0x0200,	(1<<24)-(1<<16)-1 },
	{ (char *)0,	0,	0 }
};

struct bus_info sun3_info[] = {
	{ "virtual",	0x0001,	(1<<32)-1 },
	{ "obmem",	0x0002,	(1<<32)-1 },
	{ "obio",	0x0004,	(1<<21)-1 },
	{ "vme16d16",	0x0100,	(1<<16)-1 },
	{ "vme24d16",	0x0200,	(1<<24)-(1<<16)-1 },
	{ "vme32d16",	0x0400,	(1<<32)-(1<<24)-1 },
	{ "vme16d32",	0x1000,	(1<<16) },
	{ "vme24d32",	0x2000,	(1<<24)-(1<<16)-1 },
	{ "vme32d32",	0x4000,	(1<<32)-(1<<24)-1 },
	{ (char *)0,	0,	0 }
};

bus_encode(addr, dp)
	u_int addr;
	register struct device *dp;
{
	register char *busname;
	register struct bus_info *bip;
	register int num;

	if (machine == MACHINE_SUN2)
		bip = sun2_info;
	else if (machine == MACHINE_SUN3)
		bip = sun3_info;
	else {
		yyerror("bad machine type for bus_encode");
		exit(1);
	}

	if (dp->d_conn == TO_NEXUS || dp->d_conn == 0) {
		yyerror("bad connection");
		exit(1);
	}

	busname = dp->d_conn->d_name;
	num = dp->d_conn->d_unit;

	for (; bip->bi_name != 0; bip++)
		if (eq(busname, bip->bi_name))
			break;

	if (bip->bi_name == 0) {
		(void)sprintf(errbuf, "bad bus type '%s' for machine %s",
			busname, machinename);
		yyerror(errbuf);
	} else if (addr > bip->bi_max) {
		(void)sprintf(errbuf,
			"0x%x exceeds maximum address 0x%x allowed for %s",
			addr, bip->bi_max, busname);
		yyerror(errbuf);
	} else {
		dp->d_bus = bip->bi_info;	/* set up bus type info */
		if (num != QUES)
			/*
			 * Set up cpu type since the connecting
			 * bus type is not wildcarded.
			 */
			dp->d_mach = num;
	}
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.