PWB1/sys/source/s8/config.c
#include "stdio.h"
#define TSIZE 50 /* maximum configuration table size */
#define DSIZE 30 /* maximum device table size */
#define ASIZE 20 /* maximum alias table size */
#define PSIZE 15 /* maximum parameter table size */
#define BSIZE 16 /* maximum block device table size */
#define CSIZE 32 /* maximum character device table size */
#define IMMED 16 /* immediate allocation of device */
#define BLOCK 8 /* block type device */
#define CHAR 4 /* character type device */
#define FIX 1 /* interrupt vector in range 0 - 0274 */
#define FLT 2 /* interrupt vector in range 0300 - 0774 */
#define OPEN 16 /* open routine exists */
#define CLOSE 8 /* close routine exists */
#define READ 4 /* read routine exists */
#define WRITE 2 /* write routine exists */
#define SGTTY 1 /* sgtty routine exists */
struct t {
char *devname; /* pointer to device name */
int vector; /* interrupt vector location */
int address; /* device address */
int buslevel; /* bus request level */
int addrsize; /* number of bytes at device address */
int vectsize; /* number of bytes needed for interrupt vector */
int type; /* IMMED,BLOCK,CHAR,FIX,FLT specification */
char *handler; /* pointer to interrupt handler */
int count; /* sequence number for this device */
int blk; /* major device number if block type device */
int chr; /* major device number if char. type device */
int mlt; /* number of devices on controller */
} table [TSIZE]
{
"dl11", 060, 0777560, 4, 8, 8, 5, "kl", 0, 0, 0, 1 /* console */
};
struct t2 {
char dev[9]; /* device name */
int vsize; /* interrupt vector size */
int asize; /* device address size */
int type2; /* IMMED,BLOCK,CHAR,FIX,FLT specification */
int block; /* major device number if block type device */
int charr; /* major device number if char. type device */
int mult; /* maximum number of devices per controller */
int busmax; /* maximum allowable bus request level */
int mask; /* device mask indicating existing handlers */
char hndlr[5]; /* handler name */
int dcount; /* number of controllers present */
char entries[3][9]; /* conf. structure definitions */
} devinfo [DSIZE];
struct t3 {
char new[9]; /* alias of device */
char old[9]; /* reference name of device */
} alias [ASIZE];
struct t4 {
char *indef; /* input parameter keyword */
char *oudef; /* output definition symbol */
int value;
} parms [PSIZE]
{
"buffers", "NBUF", -1,
"inodes", "NINODE", -1,
"files", "NFILE", -1,
"mounts", "NMOUNT", -1,
"coremap", "CMAPSIZ", -1,
"swapmap", "SMAPSIZ", -1,
"calls", "NCALL", -1,
"procs", "NPROC", -1,
"texts", "NTEXT", -1,
"clists", "NCLIST", -1
};
struct t *lowptr[128] /* low core double-word pointers */
{
1,2,3,4,5,6,7,8,9,10,11,12, /* trap vectors/fillers */
&table[0],20, /* console entry */
0,0, /* free entries */
17,18, /* trap vectors/fillers */
0, /* free entry */
13, /* trap vector/filler */
0,0,0,0,0,0,0,0,0,0, /* free entries */
0,0,0,0,0,0,0,0,0,0, /* free entries */
14,15,16 /* trap vectors/fillers */
};
struct t2 *bdevices[BSIZE]; /* pointers to block devices */
struct t2 *cdevices[CSIZE]; /* pointers to char. devices */
struct t *p; /* configuration table pointer */
struct t2 *q; /* master device table pointer */
struct t3 *r; /* alias table pointer */
struct t4 *kwdptr; /* keyword table pointer */
int eflag 0; /* error in configuration */
int bmax -1; /* dynamic max. major device number for block device */
int cmax -1; /* dynamic max. major device number for char. device */
int blockex 0; /* dynamic end of block device table */
int charex 0; /* dynamic end of character device table */
int subv 0; /* low core double-word subscript */
int abound -1; /* current alias table size */
int dbound -1; /* current device table size */
int tbound 0; /* current configuration table size */
int pbound 9; /* current keyword table size */
int rtmaj -1; /* major device number for root device */
int swpmaj -1; /* major device number for swap device */
int dmpmaj -1; /* major device number for dump device */
int rtmin -1; /* minor device number for root device */
int swpmin -1; /* minor device number for swap device */
int dmpmin -1; /* minor device number for dump device */
int swplo -1; /* low disc address for swap area */
int nswap -1; /* number of disc blocks in swap area */
int fdconf; /* configuration file descriptor */
int fdlow; /* low core file descriptor */
char *dmphndlr; /* pointer to dump handler routine */
char *mfile; /* master device file */
char *cfile; /* output configuration table file */
char *lfile; /* output low core file */
char *infile; /* input configuration file */
char line[101]; /* input line buffer area */
char dump[81]; /* trap filler for dump routine */
char xbuff[101]; /* buffer for external symbol definitions */
char *cputrap[] /* trap/filler text */
{
"",
"\tjmp\tstart\t\t/ Initial startup",
"\ttrap4;\tbr7+0.\t\t/ Bus error",
"\ttrap;\tbr7+1.\t\t/ Illegal instruction",
"\ttrap14;\tbr7+2.\t\t/ Bpt-trace trap",
"\ttrap;\tbr7+3.\t\t/ Iot trap",
"\ttrap24;\tbr7+4.\t\t/ Power failure",
"\ttrap;\tbr7+5.\t\t/ Emulator trap",
"\ttrap;\tbr7+6.\t\t/ System entry",
"\t_pwbname;\t\t/ Name of system\n\tbr .",
&dump[0],
"\t.+2;\tbr .\t\t/ Trap catcher",
"\t.+2;\tbr .",
"\ttrap;\tbr7+10.\t\t/ Memory system error",
"\ttrap;\tbr7+7.\t\t/ Programmed interrupt",
"\ttrap;\tbr7+8.\t\t/ Floating point",
"\ttrap250;\t\t/ Segmentation violation\n\tbr7+9.",
"\tclio;\tbr6+0.",
"\tclio;\tbr6+1."
};
char *out[2] /* low core text */
{
".globl\t_%srint, _%sxint\n%sin:\n\tjsr\tr0,call; _%srint\n",
"%sou:\n\tjsr\tr0,call; _%sxint\n\n"
};
char *opterror /* option error message */
{
"Option re-specification\n"
};
char *dmpform /* format for dump routine */
{
"dump:\t\t\t\t/ Memory dump\n.globl\tdump_%s\n\tjmp\t*$dump_%s"
};
main(argc,argv)
int argc;
char *argv[];
{
int l,a,v,bl,fd,i,ml,number;
char d[9], input[11], buff[9], c, capitals[9];
char *argv2;
struct t *pt;
argc--;
argv++;
argv2 = argv[0];
argv++;
/*
* Scan off the 'c', 'l', and 'm' options.
*/
while ((argc > 1) && (argv2[0] == '-')) {
for (i=1;(c=argv2[i]) != NULL;i++) {
switch (c) {
/*
* Output configuration file specification
*/
case 'c': if (cfile) {
printf (opterror);
exit(1);
}
cfile = argv[0];
argv++;
argc--;
break;
/*
* Output low core file specification
*/
case 'l': if (lfile) {
printf (opterror);
exit(1);
}
lfile = argv[0];
argv++;
argc--;
break;
/*
* Input master table specification
*/
case 'm': if (mfile) {
printf (opterror);
exit(1);
}
mfile = argv[0];
argv++;
argc--;
break;
default: printf ("Unknown option\n");
exit(1);
}
}
argc--;
argv2 = argv[0];
argv++;
}
if (argc != 1) {
printf ("Usage: config [-l file] [-c file] [-m file] file\n");
exit(1);
}
/*
* Set up defaults for unspecified files.
*/
if (cfile == 0)
cfile = "conf.c";
if (lfile == 0)
lfile = "low.s";
if (mfile == 0)
mfile = "/etc/master";
infile = argv2;
fd = fopen (infile,"r");
if (fd == NULL) {
printf ("Open error for file -- %s\n",infile);
exit(1);
}
/*
* Open configuration file and set modes.
*/
fdconf = fopen (cfile,"w");
if (fdconf == NULL) {
printf ("Open error for file -- %s\n",cfile);
exit(1);
}
chmod (cfile,0644);
/*
* Print configuration file heading.
*/
fprintf (fdconf,"/*\n * Configuration information\n */\n\n\n");
p = &table[1];
/*
* Read in the master device table and the alias table.
*/
file();
/*
* Set up the console, which must be present.
*/
q = find("dl11");
subv = (q->charr);
cdevices[subv] = q;
cmax = max (cmax,subv);
q->dcount++;
/*
* Start scanning the input.
*/
while (fgets(line,100,fd) != NULL) {
if (line[0] == '*')
continue;
l = sscanf(line,"%8s",&input[0]);
if (l == 0) {
error ("Incorrect line format");
continue;
}
if (equal(&input[0],"root")) {
/*
* Root device specification
*/
l = sscanf(line,"%*8s%8s%o",&buff[0],&number);
if (l != 2) {
error ("Incorrect line format");
continue;
}
if ((pt=locate(&buff[0])) == 0) {
error ("No such device");
continue;
}
if ((pt->type & BLOCK) == 0) {
error ("Not a block device");
continue;
}
if (number > 255) {
error ("Invalid minor device number");
continue;
}
if (rtmin >= 0) {
error ("Multiple root specification");
continue;
}
rtmin = number;
rtmaj = pt->blk;
}
else
if (equal(&input[0],"swap")) {
/*
* Swap device specification
*/
l = sscanf(line,"%*8s%8s%o%d%d",
&buff[0],&number,
&swplo,&nswap);
if (l != 4) {
error ("Incorrect line format");
continue;
}
if ((pt=locate(&buff[0])) == 0) {
error ("No such device");
continue;
}
if ((pt->type & BLOCK) == 0) {
error ("Not a block device");
continue;
}
if (number > 255) {
error ("Invalid minor device number");
continue;
}
if (swpmin >= 0) {
error ("Multiple swap specification");
continue;
}
if (nswap < 1) {
error ("Invalid nswap");
continue;
}
if (swplo < 1) {
error ("Invalid swplo");
continue;
}
swpmin = number;
swpmaj = pt->blk;
}
else
if (equal(&input[0],"dump")) {
/*
* Dump device specification
*/
l = sscanf(line,"%*8s%8s%o",&buff[0],&number);
if (l != 2) {
error ("Incorrect line format");
continue;
}
if ((pt=locate(&buff[0])) == 0) {
error ("No such device");
continue;
}
if (number > 255) {
error ("Invalid minor device number");
continue;
}
if (dmpmin >= 0) {
error ("Multiple dump specification");
continue;
}
dmpmin = number;
dmpmaj = 0;
dmphndlr = pt->handler;
}
else {
/*
* Device or parameter specification other than root, swap, or dump
*/
kwdptr = lookup(&input[0]);
if (kwdptr) {
l = sscanf(line,"%10s%d",&input[0],&number);
if (l != 2) {
error ("Incorrect line format");
continue;
}
kwdptr->value = number;
continue;
}
tbound++;
if (tbound == TSIZE) {
printf ("Configuration table overflow\n");
exit(1);
}
l = sscanf(line,"%8s%o%o%d%d",&d[0],&v,&a,&bl,&ml);
if (l < 4) {
error ("Incorrect line format");
continue;
}
/*
* Does such a device exist, and if so, do we allow its specification?
*/
if (((q=find(&d[0]))==0)||((q->type2&(FIX+FLT))==0)) {
error ("No such device");
continue;
}
/*
* Is the bus request level a valid one for this device?
*/
if (bl<4 || bl>q->busmax) {
error ("Invalid bus level");
continue;
}
/*
* Is the address valid?
*/
if (a < 0160000) {
error ("Invalid address");
continue;
}
/*
* Is the interrupt vector on an appropriate boundary?
*/
if (v%q->vsize) {
error ("Vector alignment");
continue;
}
/*
* Is the interrupt vector in low core?
*/
if (v<0 || v>0774) {
error ("Vector not in low core range");
continue;
}
switch (q->type2 & (FIX+FLT)) {
/*
* This interrupt vector should be in the 0 - 0274 range.
*/
case 1: if (v > 0274) {
error ("Vector not in 0-0274 range");
continue;
}
break;
/*
* This interrupt vector should be in the 0300 - 0774 range.
*/
case 2: if (v < 0300) {
error ("Vector not in 0300-0774 range");
continue;
}
break;
}
/*
* Get the double-word offset for the interrupt vector.
*/
subv = v/4;
/*
* If vector is not already allocated, mark it as now allocated.
*/
if (lowptr[subv]) {
error ("Vector allocated");
continue;
}
if (q->vsize == 8) {
if (lowptr[subv+1]) {
error ("Vector collision");
continue;
}
lowptr[subv+1] = 20;
}
/*
* See if the optional device multiplier was specified, and if so, see
* if it is a valid one.
*/
if (l == 5) {
if ((ml > q->mult) || (ml < 1)) {
error ("Invalid device multiplier");
continue;
}
p->mlt = ml;
}
/*
* Multiplier not specified, so take a default value from master device table.
*/
else
p->mlt = q->mult;
/*
* Set low core configuration table pointer to the device.
*/
lowptr[subv] = p;
/*
* Fill in the contents of the configuration table node for this device.
*/
setq();
p->devname = q->dev;
p->vector = subv;
p->address = a;
p->buslevel = bl;
p->addrsize = q->asize;
p->vectsize = q->vsize;
p->type = q->type2;
p->handler = q->hndlr;
p->count = q->dcount;
p->blk = q->block;
p->chr = q->charr;
q->dcount;
p++;
/*
* Write upper case define statement and sequence number for device.
*/
fprintf (fdconf,"#define\t%s_%d\n",
uppermap (&d[0],&capitals[0]),
q->dcount++);
}
}
/*
* Make sure that the root, swap and dump devices were specified.
*/
if (rtmaj < 0) {
printf ("root device not specified\n");
eflag++;
}
if (swpmaj < 0) {
printf ("swap device not specified\n");
eflag++;
}
if (dmpmaj < 0) {
printf ("dump device not specified\n");
eflag++;
}
for (kwdptr= &parms[0]; kwdptr<=&parms[pbound]; kwdptr++) {
if (kwdptr->value < 0) {
printf ("%s not specified\n",kwdptr->indef);
eflag++;
}
}
/*
* See if configuration is to be terminated.
*/
if (eflag) {
printf ("\nConfiguration aborted.\n");
exit (1);
}
/*
* Configuration is okay, so write the two files and quit.
*/
sprintf (&dump[0],dmpform,dmphndlr,dmphndlr);
prtconf();
prtlow();
printf ("Configuration completed successfully.\n");
exit (0);
}
/*
* This routine writes out the low core assembler program.
*/
prtlow()
{
register int i;
register char *ptr;
register struct t *tptr;
int ktemp;
/*
* Open low core file and set modes.
*/
fdlow = fopen (lfile,"w");
if (fdlow == NULL) {
printf ("Open error for file -- %s\n",lfile);
exit(1);
}
chmod (lfile,0644);
/*
* Print some headings.
*/
fprintf (fdlow,"\t\t/ PWB UNIX - Bell Laboratories /\n\n");
fprintf (fdlow,"/ Low core\n.data\n\nbr4 = 200\nbr5 = 240\n");
fprintf (fdlow,"br6 = 300\nbr7 = 340\n\n");
fprintf (fdlow,".globl\tstart, dump, call, _pwbname\n");
fprintf (fdlow,".globl\ttrap, trap4, trap14, trap24, trap250\n\n");
/*
* Go through low core in double-word increments.
*/
for(i=0;i<128;i++) {
ktemp = lowptr[i];
/*
* If the pointer is 0, set vector up for stray interrupt catcher.
*/
if (ktemp == 0)
fprintf (fdlow,"\t.+2;\tbr .\n");
else {
fprintf (fdlow,". = %o^.\n",i*4);
/*
* See if pointer refers to a filler message.
*/
if (ktemp < 20)
fprintf (fdlow,"%s\n",cputrap[ktemp]);
/*
* Pointer refers to a device, so set up the handler routine address with
* the bus level and device sequence number.
*/
else {
ptr = ktemp;
if (ptr->vectsize == 8) {
fprintf (fdlow,"\t%sin;\tbr%d+%d.\n",
ptr->handler,
ptr->buslevel,
ptr->count);
fprintf (fdlow,"\t%sou;\tbr%d+%d.\n",
ptr->handler,
ptr->buslevel,
ptr->count);
i++;
}
else {
fprintf (fdlow,"\t%sio;\tbr%d+%d.\n",
ptr->handler,
ptr->buslevel,
ptr->count);
}
}
}
}
/*
* Print headings for C interface code.
*/
fprintf (fdlow,"\n. = 1000^.\n\n/ Interface code to C\n\n");
fprintf (fdlow,".globl\t_clock\nclio:\n\tjsr\tr0,call; _clock\n\n");
/*
* Go through configuration table and print out all required handler references.
*/
for (tptr= &table[0];tptr->devname!=0;tptr++) {
if (tptr->count == 0) {
if (tptr->vectsize == 4) {
fprintf (fdlow,".globl\t_%sintr\n%sio:\n\tjsr\tr0,call; _%sintr\n\n",
tptr->handler,
tptr->handler,
tptr->handler);
}
else {
fprintf (fdlow,out[0],
tptr->handler,
tptr->handler,
tptr->handler,
tptr->handler);
fprintf (fdlow,out[1],
tptr->handler,
tptr->handler);
}
}
}
}
/*
* This routine is used to read in the master device table and the
* alias table. In the master device file, these two tables are separated
* by a line which contains an asterisk in column 1. Certain special type
* devices such as memory, require immediate allocation in the character
* and/or block tables. They are specially marked as requiring this.
*/
file()
{
int l,fd;
fd = fopen(mfile,"r");
if (fd == NULL) {
printf ("Open error for file -- %s\n",mfile);
exit(1);
}
q = &devinfo[0];
while (fgets(line,100,fd) != NULL) {
/*
* Check for the delimiter that indicates the beginning of the
* alias table entries.
*/
if (line[0] == '$')
break;
/*
* Check for comment.
*/
if (line[0] == '*')
continue;
dbound++;
if (dbound == DSIZE) {
printf ("Device table overflow\n");
exit(1);
}
l = sscanf(line,"%8s%d%d%d%4s%d%d%d%d%d%8s%8s%8s",
q->dev,&(q->vsize),&(q->mask),&(q->type2),
q->hndlr,&(q->asize),&(q->block),
&(q->charr),&(q->mult),&(q->busmax),
q->entries[0],q->entries[1],q->entries[2]);
if (l < 10) {
printf ("device table error -- %d\n",l);
exit(1);
}
/*
* Update the ends of the block and character device tables.
*/
if (q->type2 & BLOCK)
blockex = max (blockex,q->block);
if (q->type2 & CHAR)
charex = max (charex,q->charr);
/*
* See if the device requires immediate allocation.
*/
if (q->type2 & IMMED)
setq();
q++;
}
r = &alias[0];
while (fgets(line,100,fd) != NULL) {
/*
* Check for comment.
*/
if (line[0] == '*')
continue;
abound++;
if (abound == ASIZE) {
printf ("Alias table overflow\n");
exit(1);
}
l = sscanf(line,"%8s%8s",r->new,r->old);
if (l < 2) {
printf ("alias table error -- %d\n",l);
exit(1);
}
r++;
}
return(0);
}
/*
* This routine compares two null terminated strings for equality.
*/
equal(s1,s2)
char *s1,*s2;
{
while (*s1++ == *s2) {
if (*s2++ == 0)
return(1);
}
return(0);
}
/*
* This routine is used to print a configuration time error message
* and then set a flag indicating a contaminated configuration.
*/
error(message)
char *message;
{
printf ("%s%s\n\n",&line[0],message);
eflag++;
return;
}
/*
* This routine is used to search through the master device table for
* some specified device. If the device is found, we return a pointer to
* the device. If the device is not found, we search the alias table for
* this device. If the device is not found in the alias table, we return a
* zero. If the device is found, we change its name to the reference name of
* the device and re-initiate the search for this new name in the master
* device table.
*/
int find(device)
char *device;
{
register struct t2 *q;
register struct t3 *r;
for (; ;) {
/*
* Search the master device table for the specified device.
*/
for (q= &devinfo[0];q<=&devinfo[dbound];q++) {
if (equal(device,q->dev))
return(q);
}
/*
* Since the device was not found in the master device table,
* we now search through the alias table.
*/
for (r= &alias[0];r<=&alias[abound];r++) {
if (equal(device,r->new)) {
device = r->old;
break;
}
}
/*
* See if the device was found in the alias table. If it wasn't, return a 0.
*/
if (r > &alias[abound])
return(0);
/*
* It was found in the alias table, so we change its name back to the
* reference name of the device and re-initiate the master device table search.
*/
}
}
/*
* This routine is used to set the character and/or block table pointers
* to point to an entry of the master device table.
*/
setq()
{
register char *ptr;
/*
* Do a switch on the type of device.
*/
switch (q->type2 & (BLOCK+CHAR)) {
/*
* Device is not a block or character device.
*/
case 0: break;
/*
* Device is a character type device.
*/
case 4: subv = q->charr;
ptr = cdevices[subv];
if (ptr) {
if (!equal(ptr->dev,q->dev)) {
charex++;
if (charex == CSIZE) {
printf("Character table overflow\n");
exit(1);
}
q->charr = subv = charex;
}
}
cdevices[subv] = q;
cmax = max (cmax,subv);
break;
/*
* Device is a block type device.
*/
case 8: subv = q->block;
ptr = bdevices[subv];
if (ptr) {
if (!equal(ptr->dev,q->dev)) {
blockex++;
if (blockex == BSIZE) {
printf ("Block table overflow\n");
exit(1);
}
q->block = subv = blockex;
}
}
bdevices[subv] = q;
bmax = max (bmax,subv);
break;
/*
* Device is both a character and block type device.
*/
case 12:subv = q->charr;
ptr = cdevices[subv];
if (ptr) {
if (!equal(ptr->dev,q->dev)) {
charex++;
if (charex == CSIZE) {
printf("Character table overflow\n");
exit(1);
}
q->charr = subv = charex;
}
}
cdevices[subv] = q;
cmax = max (cmax,subv);
subv = q->block;
ptr = bdevices[subv];
if (ptr) {
if (!equal(ptr->dev,q->dev)) {
blockex++;
if (blockex == BSIZE) {
printf ("Block table overflow\n");
exit(1);
}
q->block = subv = blockex;
}
}
bdevices[subv] = q;
bmax = max (bmax,subv);
break;
}
return;
}
/*
* This routine writes out the configuration file (C program.)
*/
prtconf()
{
int i,j,counter;
char *ptr;
/*
* Print some headings.
*/
fprintf (fdconf,"\n");
for (kwdptr= &parms[0]; kwdptr<=&parms[pbound]; kwdptr++) {
fprintf (fdconf,"#define\t%s\t%d\n",
kwdptr->oudef, kwdptr->value);
}
fprintf (fdconf,"\n#include\t\"../hd\/io.h\"\n");
fprintf (fdconf,"#include\t\"../hd/space.h\"\n\n");
/*
* Print the extern statement for the nodev and nulldev entries.
*/
fprintf (fdconf,"extern nodev(), nulldev();\n");
/*
* Search the configuration table and generate an extern statement for
* any routines which are needed.
*/
for (p= &table[0];p<=&table[tbound];p++) {
if (p->count)
continue;
switch (p->type & (BLOCK+CHAR)) {
case 4: q = find(p->devname);
sprintf (&xbuff[0],"extern");
if (q->mask & OPEN)
sprintf (&(xbuff[strlen(xbuff)]),
" %sopen(),",&(q->hndlr));
if (q->mask & CLOSE)
sprintf (&(xbuff[strlen(xbuff)]),
" %sclose(),",&(q->hndlr));
if (q->mask & READ)
sprintf (&(xbuff[strlen(xbuff)]),
" %sread(),",&(q->hndlr));
if (q->mask & WRITE)
sprintf (&(xbuff[strlen(xbuff)]),
" %swrite(),",&(q->hndlr));
if (q->mask & SGTTY)
sprintf (&(xbuff[strlen(xbuff)]),
" %ssgtty(),",&(q->hndlr));
xbuff[strlen(xbuff)-1] = ';';
fprintf (fdconf,"%s\n",&xbuff[0]);
break;
case 8: fprintf (fdconf,"extern %sopen(), %sclose(),",
p->handler,p->handler);
fprintf (fdconf," %sstrategy(), %stab();\n",
p->handler,p->handler);
break;
case 12:q = find(p->devname);
sprintf (&xbuff[0],"extern %sopen(), %sclose(),",
&(q->hndlr),&(q->hndlr));
if (q->mask & READ)
sprintf (&(xbuff[strlen(xbuff)]),
" %sread(),",&(q->hndlr));
if (q->mask & WRITE)
sprintf (&(xbuff[strlen(xbuff)]),
" %swrite(),",&(q->hndlr));
if (q->mask & SGTTY)
sprintf (&(xbuff[strlen(xbuff)]),
" %ssgtty(),",&(q->hndlr));
sprintf (&(xbuff[strlen(xbuff)]),
" %sstrategy(), %stab();",
&(q->hndlr),&(q->hndlr));
fprintf (fdconf,"%s\n",&xbuff[0]);
break;
}
}
/*
* Search the master device table and generate an extern statement for
* any routines which were not covered by the previous section of code.
* These routines are generally associated with those devices which require
* immediate allocation (thus, they are not in the configuration table).
*/
for (q= &devinfo[0];q<=&devinfo[dbound];q++) {
if (q->type2 & IMMED) {
switch (q->type2 & (BLOCK+CHAR)) {
case 4: sprintf (&xbuff[0],"extern");
if (q->mask & OPEN)
sprintf (&(xbuff[strlen(xbuff)]),
" %sopen(),",&(q->hndlr));
if (q->mask & CLOSE)
sprintf (&(xbuff[strlen(xbuff)]),
" %sclose(),",&(q->hndlr));
if (q->mask & READ)
sprintf (&(xbuff[strlen(xbuff)]),
" %sread(),",&(q->hndlr));
if (q->mask & WRITE)
sprintf (&(xbuff[strlen(xbuff)]),
" %swrite(),",&(q->hndlr));
if (q->mask & SGTTY)
sprintf (&(xbuff[strlen(xbuff)]),
" %ssgtty(),",&(q->hndlr));
xbuff[strlen(xbuff)-1] = ';';
fprintf (fdconf,"%s\n",&xbuff[0]);
break;
case 8: fprintf (fdconf,"extern %sopen(), %sclose(),",
&(q->hndlr),&(q->hndlr));
fprintf (fdconf," %sstrategy(), %stab();\n",
&(q->hndlr),&(q->hndlr));
break;
case 12:sprintf (&xbuff[0],"extern %sopen(), %sclose(),",
&(q->hndlr),&(q->hndlr));
if (q->mask & READ)
sprintf (&(xbuff[strlen(xbuff)]),
" %sread(),",&(q->hndlr));
if (q->mask & WRITE)
sprintf (&(xbuff[strlen(xbuff)]),
" %swrite(),",&(q->hndlr));
if (q->mask & SGTTY)
sprintf (&(xbuff[strlen(xbuff)]),
" %ssgtty(),",&(q->hndlr));
sprintf (&(xbuff[strlen(xbuff)]),
" %sstrategy(), %stab();",
&(q->hndlr),&(q->hndlr));
fprintf (fdconf,"%s\n",&xbuff[0]);
break;
}
}
}
fprintf (fdconf,"\nint\t(*bdevsw[])()\n{\n");
/*
* Go through block device table and indicate addresses of required routines.
* If a particular device is not present, fill in "nodev" entries.
*/
for (i=0;i<=bmax;i++) {
ptr = bdevices[i];
fprintf (fdconf,"/*%2d*/\t",i);
if (ptr) {
fprintf (fdconf,"&%sopen,\t&%sclose,\t&%sstrategy,\t&%stab,\n",
&(ptr->hndlr),
&(ptr->hndlr),
&(ptr->hndlr),
&(ptr->hndlr));
}
else {
fprintf (fdconf,"&nodev, \t&nodev, \t&nodev, \t0, \n");
}
}
fprintf (fdconf,"};\n\n");
fprintf (fdconf,"int\t(*cdevsw[])()\n{\n");
/*
* Go through character device table and indicate addresses of required
* routines, or indicate "nulldev" if routine is not present. If a
* particular device is not present, fill in "nodev" entries.
*/
for (j=0;j<=cmax;j++) {
ptr = cdevices[j];
fprintf (fdconf,"/*%2d*/",j);
if (ptr) {
if (ptr->mask & OPEN)
fprintf (fdconf,"\t&%sopen,",&(ptr->hndlr));
else
fprintf (fdconf,"\t&nulldev,");
if (ptr->mask & CLOSE)
fprintf (fdconf,"\t&%sclose,",&(ptr->hndlr));
else
fprintf (fdconf,"\t&nulldev,");
if (ptr->mask & READ)
fprintf (fdconf,"\t&%sread,",&(ptr->hndlr));
else
fprintf (fdconf,"\t&nodev, ");
if (ptr->mask & WRITE)
fprintf (fdconf,"\t&%swrite,",&(ptr->hndlr));
else
fprintf (fdconf,"\t&nodev, ");
if (ptr->mask & SGTTY)
fprintf (fdconf,"\t&%ssgtty,\n",&(ptr->hndlr));
else
fprintf (fdconf,"\t&nodev, \n");
}
else
fprintf (fdconf,"\t&nodev, \t&nodev, \t&nodev, \t&nodev, \t&nodev,\n");
}
/*
* Print out block and character device counts, root, swap, and dump device
* information, and the swplo, and nswap values.
*/
fprintf (fdconf,"};\n\n");
fprintf (fdconf,"int\tbdevcnt\t%d;\nint\tcdevcnt\t%d;\n\n",i,j);
fprintf (fdconf,"int\trootdev\t{(%d<<8)|0%o};\n",rtmaj,rtmin);
fprintf (fdconf,"int\tswapdev\t{(%d<<8)|0%o};\n",swpmaj,swpmin);
fprintf (fdconf,"int\tswplo\t%d;\nint\tnswap\t%d;\n",swplo,nswap);
fprintf (fdconf,"int\tdumpdev\t{(%d<<8)|0%o};\n\n",dmpmaj,dmpmin);
/*
* Go through the block device table, ignoring any zero entries,
* as well as those that do not have interrupt vectors.
*/
for (i=0;i<=bmax;i++) {
if ((q=bdevices[i]) == 0)
continue;
if ((q->type2 & (FIX+FLT)) == 0)
continue;
counter = 0;
fprintf (fdconf,"\nint\t%s_addr[]\n{\n",q->hndlr);
/*
* For each of these devices, go through the configuration table and
* look for matches. For each match, print the device address, and keep
* a count of the number of matches.
*/
for (p= &table[0];p<=&table[tbound];p++) {
if (equal(q->dev,p->devname)) {
fprintf (fdconf,"\t0%o,\n",p->address);
counter =+ p->mlt;
}
}
fprintf (fdconf,"};\n");
fprintf (fdconf,"int\t%s_cnt %d;\n",
q->hndlr,counter);
/*
* Print any required structure definitions.
*/
for (j=0;j<3;j++) {
if (*(q->entries[j]) != NULL)
fprintf (fdconf,"struct\t%s\t%s_%s[%d];\n",
q->entries[j],q->hndlr,
q->entries[j],counter);
}
}
/*
* Go through the character device table, ignoring any zero entries,
* as well as those that do not have interrupt vectors, and those that
* are not strictly character devices.
*/
for (i=0;i<=cmax;i++) {
if ((q=cdevices[i]) == 0)
continue;
if ((q->type2 & (FIX+FLT)) == 0)
continue;
if ((q->type2 & (BLOCK+CHAR)) != CHAR)
continue;
counter = 0;
fprintf (fdconf,"\nint\t%s_addr[]\n{\n",q->hndlr);
/*
* For each of these devices, go through the configuration table and
* look for matches. For each match, print the device address, and keep
* a count of the number of matches.
*/
for (p= &table[0];p<=&table[tbound];p++) {
if (equal(q->dev,p->devname)) {
fprintf (fdconf,"\t0%o,\n",p->address);
counter =+ p->mlt;
}
}
fprintf (fdconf,"};\n");
fprintf (fdconf,"int\t%s_cnt %d;\n",
q->hndlr,counter);
/*
* Print any required structure definitions.
*/
for (j=0;j<3;j++) {
if (*(q->entries[j]) != NULL)
fprintf (fdconf,"struct\t%s\t%s_%s[%d];\n",
q->entries[j],q->hndlr,
q->entries[j],counter);
}
}
/*
* Repeat the procedure for the dm11 - modem control which is a somewhat
* special device.
*/
if (locate("dm11")) {
fprintf (fdconf,"\nint\tdm_addr[]\n{\n");
for (p= &table[0];p<=&table[tbound];p++) {
if (equal (p->devname,"dm11"))
fprintf (fdconf,"\t0%o,\n",p->address);
}
fprintf (fdconf,"};\n");
}
return;
}
max(a,b)
int a,b;
{
return (a>b ? a:b);
}
/*
* This routine is used to search the configuration table for some
* specified device. If the device is found we return a pointer to
* that device. If the device is not found, we search the alias
* table for this device. If the device is not found in the alias table
* we return a zero. If the device is found, we change its name to
* the reference name of the device and re-initiate the search for this
* new name in the configuration table.
*/
int locate(device)
char *device;
{
register struct t *p;
register struct t3 *r;
for (; ;) {
/*
* Search the configuration table for the specified device.
*/
for (p= &table[0];p<=&table[tbound];p++) {
if (equal(device,p->devname))
return(p);
}
/*
* Since the device was not found in the configuration table, we now
* search through the alias table.
*/
for (r= &alias[0];r<=&alias[abound];r++) {
if (equal(device,r->new)) {
device = r->old;
break;
}
}
/*
* See if the device was found in the alias table. If it wasn't, return a 0.
*/
if (r > &alias[abound])
return(0);
/*
* It was found in alias table, so we change its name back to the
* reference name of the device and re-initiate the configuration
* table search.
*/
}
}
/*
* This routine is used to search the parameter table
* for the keyword that was specified in the configuration. If the
* keyword cannot be found in this table, a value of zero is returned.
* If the keyword is found, a pointer to that entry is returned.
*/
int lookup(keyword)
char *keyword;
{
register struct t4 *kwdptr;
for (kwdptr= &parms[0]; kwdptr<=&parms[pbound]; kwdptr++) {
if (equal(keyword,kwdptr->indef))
return (kwdptr);
}
return(0);
}
/*
* This routine is used to map lower case alphabetics into upper case.
*/
int uppermap(device,caps)
char *device;
char *caps;
{
register char *ptr;
register char *ptr2;
ptr2 = &caps[0];
for (ptr= &device[0];*ptr!=NULL;ptr++) {
if ('a' <= *ptr && *ptr <= 'z')
*ptr2++ = *ptr + 'A' - 'a';
else
*ptr2++ = *ptr;
}
*ptr2 = NULL;
return (&caps[0]);
}