SysIII/usr/src/cmd/config/config.vax.c
#include "stdio.h"
#define TSIZE 50 /* maximum configuration table size */
#define DSIZE 50 /* maximum device table size */
#define ASIZE 20 /* maximum alias table size */
#define MSIZE 100 /* maximum address map table size */
#define PSIZE 32 /* maximum keyword table size */
#define BSIZE 16 /* maximum block device table size */
#define CSIZE 50 /* maximum character device table size */
#define ONCE 128 /* allow only one specification of device */
#define NOCNT 64 /* suppress device count field */
#define SUPP 32 /* suppress interrupt vector (on print) */
#define REQ 16 /* required device */
#define BLOCK 8 /* block type device */
#define CHAR 4 /* character type device */
#define FLT 2 /* interrupt vector in range 0300 - 0774 */
#define FIX 1 /* interrupt vector in range 0 - 0274 */
#define INIT 64 /* initialization routine exists */
#define PWR 32 /* power fail routine exists */
#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 IOCTL 1 /* ioctl routine exists */
struct t {
char *devname; /* pointer to device name */
short vector; /* interrupt vector location */
unsigned short address; /* device address */
short buslevel; /* bus request level */
short addrsize; /* number of bytes at device address */
short vectsize; /* number of bytes for interrupt vector */
short type; /* ONCE,NOCNT,SUPP,REQ,BLOCK,CHAR,FLT,FIX */
char *handler; /* pointer to interrupt handler */
short count; /* sequence number for this device */
short blk; /* major device number if block type device */
short chr; /* major device number if char. type device */
short mlt; /* number of devices on controller */
} table [TSIZE];
struct t2 {
char dev[9]; /* device name */
short vsize; /* interrupt vector size */
short asize; /* device address size */
short type2; /* ONCE,NOCNT,SUPP,REQ,BLOCK,CHAR,FLT,FIX */
short block; /* major device number if block type device */
short charr; /* major device number if char. type device */
short mult; /* maximum number of devices per controller */
short busmax; /* maximum allowable bus request level */
short mask; /* device mask indicating existing handlers */
char hndlr[5]; /* handler name */
short dcount; /* number of controllers present */
char entries[3][9]; /* conf. structure definitions */
short acount; /* number of devices */
} devinfo [DSIZE];
struct t3 {
char new[9]; /* alias of device */
char old[9]; /* reference name of device */
} alias [ASIZE];
struct map {
unsigned short start; /* starting unibus address */
short length; /* gap length */
} map[MSIZE] =
{
0160000, 017570
};
struct t4 {
char indef[21]; /* input parameter keyword */
char oudef[21]; /* output definition symbol */
char value[21]; /* actual parameter value */
char defval[21]; /* default parameter value */
} parms [PSIZE];
struct t *lowptr[128]; /* low core double-word pointers */
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 */
struct t *locate();
struct t2 *find();
struct t4 *lookup();
char *uppermap();
short power = 0; /* power fail restart flag */
short eflag = 0; /* error in configuration */
short tflag = 0; /* table flag */
short bmax = -1; /* dynamic max. major device number for block device */
short cmax = -1; /* dynamic max. major device number for char. device */
short blockex = 0; /* dynamic end of block device table */
short charex = 0; /* dynamic end of character device table */
short subv = 0; /* low core double-word subscript */
short subtmp = 0; /* temporary; for subscripting */
short abound = -1; /* current alias table size */
short dbound = -1; /* current device table size */
short tbound = -1; /* current configuration table size */
short pbound = -1; /* current keyword table size */
short mbound = 0; /* current address map table size */
short rtmaj = -1; /* major device number for root device */
short swpmaj = -1; /* major device number for swap device */
short pipmaj = -1; /* major device number for pipe device */
short dmpmaj = -1; /* major device number for dump device */
short rtmin = -1; /* minor device number for root device */
short swpmin = -1; /* minor device number for swap device */
short pipmin = -1; /* minor device number for pipe device */
short dmpmin = -1; /* minor device number for dump device */
long swplo = -1; /* low disc address for swap area */
short nswap = -1; /* number of disc blocks in swap area */
FILE *fdconf; /* configuration file descriptor */
FILE *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 pwrbuff[513]; /* power fail routine buffer */
char initbuff[513]; /* initialization routine buffer */
char xbuff[101]; /* buffer for external symbol definitions */
char d[9]; /* buffer area */
char capitals[9]; /* buffer area */
short vec; /* specified interrupt vector */
unsigned short add; /* specified device address */
short bl; /* specified bus level */
short ml; /* specified device multiplicity */
char *opterror = /* option error message */
{
"Option re-specification\n"
};
char *sdev[] = {
"dm11",
"hisdm",
NULL
};
main(argc,argv)
int argc;
char *argv[];
{
register i, l;
register FILE *fd;
int number;
char input[21], buff[9], c, symbol[21];
char *argv2;
struct t *pt;
argc--;
argv++;
argv2 = argv[0];
argv++;
/*
* Scan off the 'c', 'l', 'm', and 't' 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 univec 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;
/*
* Table flag
*/
case 't': tflag++;
break;
default: printf ("Unknown option\n");
exit(1);
}
}
argc--;
argv2 = argv[0];
argv++;
}
if (argc != 1) {
printf ("Usage: config [-t][-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 = "univec.c";
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;
/*
* Read in the master device table and the alias table.
*/
file();
/*
* Start scanning the input.
*/
while (fgets(line,100,fd) != NULL) {
if (line[0] == '*')
continue;
l = sscanf(line,"%20s",input);
if (l == 0) {
error ("Incorrect line format");
continue;
}
if (equal(input,"root")) {
/*
* Root device specification
*/
l = sscanf(line,"%*8s%8s%o",buff,&number);
if (l != 2) {
error ("Incorrect line format");
continue;
}
if ((pt=locate(buff)) == 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 ("Root re-specification");
continue;
}
rtmin = number;
rtmaj = pt->blk;
}
else
if (equal(input,"swap")) {
/*
* Swap device specification
*/
l = sscanf(line,"%*8s%8s%o%ld%hd",
buff,&number,
&swplo,&nswap);
if (l != 4) {
error ("Incorrect line format");
continue;
}
if ((pt=locate(buff)) == 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 ("Swap re-specification");
continue;
}
if (nswap < 1) {
error ("Invalid nswap");
continue;
}
if (swplo < 0) {
error ("Invalid swplo");
continue;
}
swpmin = number;
swpmaj = pt->blk;
}
else
if (equal(input,"pipe")) {
/*
* Pipe device specification
*/
l = sscanf(line,"%*8s%8s%o",buff,&number);
if (l != 2) {
error ("Incorrect line format");
continue;
}
if ((pt=locate(buff)) == 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 (pipmin >= 0) {
error ("Pipe re-specification");
continue;
}
pipmin = number;
pipmaj = pt->blk;
}
else
if (equal(input,"dump")) {
/*
* Dump device specification
*/
l = sscanf(line,"%*8s%8s%o",buff,&number);
if (l != 2) {
error ("Incorrect line format");
continue;
}
if ((pt=locate(buff)) == 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 (dmpmin >= 0) {
error ("Dump re-specification");
continue;
}
dmpmin = number;
dmpmaj = pt->blk;
dmphndlr = pt->handler;
}
else {
/*
* Device or parameter specification other than root, swap, pipe, or dump.
* If power fail recovery is specified, remember it.
*/
kwdptr = lookup(input);
if (kwdptr) {
l = sscanf(line,"%20s%20s",input,symbol);
if (l != 2) {
error ("Incorrect line format");
continue;
}
if (strlen(kwdptr->value)) {
error ("Parameter re-specification");
continue;
}
if (equal(input,"power") && equal(symbol,"1"))
power++;
strcpy(kwdptr->value,symbol);
continue;
}
l = sscanf(line,"%8s%ho%ho%hd%hd",d,&vec,&add,&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) {
error ("No such device");
continue;
}
if ((q->type2 & ONCE) && (locate(d))) {
error ("Only one specification allowed");
continue;
}
/*
* Is the address valid?
*/
if (q->asize) {
if (add % 2) {
error ("Address alignment");
continue;
}
if (add < 0160000) {
error ("Invalid address");
continue;
}
if (addrcheck(add,q->asize)) {
error ("Address collision");
continue;
}
}
else {
if (add) {
error ("Address not null");
continue;
}
}
/*
* If the vector size field is non-zero, process as a regular device.
*/
if (q->vsize) {
/*
* Is the interrupt vector on an appropriate boundary?
*/
if (vec%q->vsize) {
error ("Vector alignment");
continue;
}
/*
* Is the interrupt vector in low core?
*/
if (vec<0 || vec>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 FIX:
if (vec > 0274) {
error ("Vector not in 0-0274 range");
continue;
}
break;
/*
* This interrupt vector should be in the 0300 - 0774 range.
*/
case FLT:
if (vec < 0300) {
error ("Vector not in 0300-0774 range");
continue;
}
break;
}
/*
* Is the bus request level a valid one for this device?
*/
if (bl<4 || bl>q->busmax) {
error ("Invalid bus level");
continue;
}
/*
* Get the double-word offset for the interrupt vector.
*/
subv = vec/4;
/*
* Make sure the interrupt vector is free.
*/
if (lowptr[subv]) {
error ("Vector allocated");
continue;
}
if (q->vsize == 8) {
if (lowptr[subv+1]) {
error ("Vector collision");
continue;
}
}
}
/*
* Device is not interrupt driven, so interrupt vector and
bus request levels should be zero.
*/
else {
if (vec) {
error ("Interrupt vector not null");
continue;
}
if (bl) {
error ("Bus level not null");
continue;
}
subv = 0;
}
/*
* 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;
}
}
/*
* Multiplier not specified, so take a default value from master device table.
*/
else
ml = q->mult;
/*
* Fill in the contents of the configuration table node for this device.
*/
enterdev(vec,add,bl,ml,d);
}
}
/*
* Make sure that the root, swap, pipe and dump devices were specified.
* Set up default values for tunable things where applicable.
*/
if (rtmaj < 0) {
printf ("root device not specified\n");
eflag++;
}
if (swpmaj < 0) {
printf ("swap device not specified\n");
eflag++;
}
if (pipmaj < 0) {
printf ("pipe device not specified\n");
eflag++;
}
if (dmpmaj < 0) {
printf ("dump device not specified\n");
eflag++;
}
for (kwdptr=parms; kwdptr<= &parms[pbound]; kwdptr++) {
if (strlen(kwdptr->value) == 0) {
if (strlen(kwdptr->defval) == 0) {
printf ("%s not specified\n",kwdptr->indef);
eflag++;
}
strcpy(kwdptr->value,kwdptr->defval);
}
}
/*
* 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.
*/
for (q=devinfo; q<= &devinfo[dbound]; q++) {
if (q->type2 & REQ) {
if (!(locate(q->dev))) {
enterdev(0,0,0,q->mult,q->dev);
}
}
}
prtconf();
prtlow();
exit(0);
}
/*
* This routine writes out the univec program.
*/
prtlow()
{
register int i;
register struct t *ptr;
register struct t *ktemp;
/*
* Open univec 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,"/* Unibus vector table */\n\n");
fprintf (fdlow,"#define NULL (int *)0\n");
fprintf (fdlow,"#define D0 0x00000000\n");
fprintf (fdlow,"#define D1 0x08000000\n");
fprintf (fdlow,"#define D2 0x10000000\n");
fprintf (fdlow,"#define D3 0x18000000\n");
fprintf (fdlow,"#define D4 0x20000000\n");
fprintf (fdlow,"#define D5 0x28000000\n");
fprintf (fdlow,"#define D6 0x30000000\n");
fprintf (fdlow,"#define D7 0x38000000\n");
fprintf (fdlow,"\n/* Interrupt Service Routine addresses */\n");
/*
* Go through configuration table and print out all required handler references.
* For devices that are not interrupt driven, and those that have the
* SUPP bit on, the printing of the handler name is suppressed.
*/
for (ptr= table; ptr->devname!=0; ptr++) {
if (ptr->count == 0) {
if ((ptr->type & SUPP) || (ptr->vectsize == 0))
continue;
if (ptr->vectsize == 4) {
fprintf (fdlow,"extern %sintr();\n",
ptr->handler);
}
else {
fprintf (fdlow,"extern %srint(), %sxint();\n",
ptr->handler,
ptr->handler);
}
}
}
/*
* Go through low core in double-word increments.
*/
fprintf (fdlow,"int *UNIvec[128] = {\n");
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,"\tNULL,\n");
else {
fprintf (fdlow,"/* %o */\n",i*4);
/*
* Pointer refers to a device, so set up the handler routine address with
* the bus level and device sequence number, unless SUPP bit is on.
*/
ptr = ktemp;
if (ptr->vectsize == 8) {
if (ptr->type & SUPP) {
fprintf (fdlow,"\tNULL,\n");
fprintf (fdlow,"\tNULL,\n");
}
else {
fprintf (fdlow,"\t(int *)((int)%srint+D%d),\n",
ptr->handler,
ptr->count);
fprintf (fdlow,"\t(int *)((int)%sxint+D%d),\n",
ptr->handler,
ptr->count);
}
i++;
}
else {
if (ptr->type & SUPP) {
fprintf (fdlow,"\tNULL,\n");
}
else {
fprintf (fdlow,"\t(int *)((int)%sintr+D%d),\n",
ptr->handler,
ptr->count);
}
}
}
}
fprintf (fdlow,"};\n");
}
/*
* 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 that contains an asterisk in column 1.
*/
file()
{
register l;
register FILE *fd;
fd = fopen(mfile,"r");
if (fd == NULL) {
printf ("Open error for file -- %s\n",mfile);
exit(1);
}
q = devinfo;
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%hd%ho%ho%4s%hd%hd%hd%hd%hd%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 ("%s\nDevice parameter count\n",line);
exit(1);
}
if (q->type2 & REQ) {
if (q->vsize || q->asize || q->busmax) {
printf ("%s\nParameter inconsistency\n",line);
exit(1);
}
}
/*
* Update the ends of the block and character device tables.
*/
if (q->type2 & BLOCK)
if ((blockex = max(blockex,q->block)) >= BSIZE) {
printf ("%s\nBad major device number\n",line);
exit(1);
}
if (q->type2 & CHAR)
if ((charex = max(charex,q->charr)) >= CSIZE) {
printf ("%s\nBad major device number\n",line);
exit(1);
}
q++;
}
r = alias;
while (fgets(line,100,fd) != NULL) {
/*
* Check for the delimiter that indicates the beginning of the
* keyword table entries.
*/
if (line[0] == '$')
break;
/*
* 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 ("%s\nAlias parameter count\n",line);
exit(1);
}
r++;
}
kwdptr = parms;
while (fgets(line,100,fd) != NULL) {
/*
* Check for comment.
*/
if (line[0] == '*')
continue;
pbound++;
if (pbound == PSIZE) {
printf ("Keyword table overflow\n");
exit(1);
}
l = sscanf(line,"%20s%20s%20s",kwdptr->indef,
kwdptr->oudef,kwdptr->defval);
if (l < 2) {
printf ("%s\nTunable parameter count\n",line);
exit(1);
}
if (l == 2)
*(kwdptr->defval) = NULL;
kwdptr++;
}
return;
}
/*
* This routine compares two null terminated strings for equality.
*/
equal(s1,s2)
register 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,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.
*/
struct t2 *
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; 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; 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 struct t2 *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 CHAR:
subtmp = q->charr;
ptr = cdevices[subtmp];
if (ptr) {
if (!equal(ptr->dev,q->dev)) {
charex++;
if (charex == CSIZE) {
printf("Character table overflow\n");
exit(1);
}
q->charr = subtmp = charex;
}
}
cdevices[subtmp] = q;
cmax = max (cmax,subtmp);
break;
/*
* Device is a block type device.
*/
case BLOCK:
subtmp = q->block;
ptr = bdevices[subtmp];
if (ptr) {
if (!equal(ptr->dev,q->dev)) {
blockex++;
if (blockex == BSIZE) {
printf ("Block table overflow\n");
exit(1);
}
q->block = subtmp = blockex;
}
}
bdevices[subtmp] = q;
bmax = max (bmax,subtmp);
break;
/*
* Device is both a character and block type device.
*/
case BLOCK|CHAR:
subtmp = q->charr;
ptr = cdevices[subtmp];
if (ptr) {
if (!equal(ptr->dev,q->dev)) {
charex++;
if (charex == CSIZE) {
printf("Character table overflow\n");
exit(1);
}
q->charr = subtmp = charex;
}
}
cdevices[subtmp] = q;
cmax = max (cmax,subtmp);
subtmp = q->block;
ptr = bdevices[subtmp];
if (ptr) {
if (!equal(ptr->dev,q->dev)) {
blockex++;
if (blockex == BSIZE) {
printf ("Block table overflow\n");
exit(1);
}
q->block = subtmp = blockex;
}
}
bdevices[subtmp] = q;
bmax = max (bmax,subtmp);
break;
}
return;
}
/*
* This routine writes out the configuration file (C program.)
*/
prtconf()
{
register i, j, counter;
short k;
char *sname;
struct t2 *ptr;
/*
* Print some headings.
*/
fprintf (fdconf,"\n");
for (kwdptr=parms; kwdptr<= &parms[pbound]; kwdptr++) {
fprintf (fdconf,"#define\t%s\t%s\n",
kwdptr->oudef, kwdptr->value);
}
fprintf (fdconf,"\n#include\t\"sys/param.h\"\n");
fprintf (fdconf,"#include\t\"sys/io.h\"\n");
fprintf (fdconf,"#include\t\"sys/space.h\"\n");
fprintf (fdconf,"#include\t\"sys/conf.h\"\n");
fprintf (fdconf,"#include\t\"sys/uba.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 that are needed.
*/
for (p=table; p<= &table[tbound]; p++) {
if (p->count)
continue;
switch (p->type & (BLOCK|CHAR)) {
case CHAR:
q = find(p->devname);
sprintf (xbuff,"extern ");
if (q->mask & OPEN) {
strcat (xbuff,q->hndlr);
strcat (xbuff,"open(), ");
}
if (q->mask & CLOSE) {
strcat (xbuff,q->hndlr);
strcat (xbuff,"close(), ");
}
if (q->mask & READ) {
strcat (xbuff,q->hndlr);
strcat (xbuff,"read(), ");
}
if (q->mask & WRITE) {
strcat (xbuff,q->hndlr);
strcat (xbuff,"write(), ");
}
if (q->mask & IOCTL) {
strcat (xbuff,q->hndlr);
strcat (xbuff,"ioctl(), ");
}
if (q->mask & PWR)
if (power) {
strcat (xbuff,q->hndlr);
strcat (xbuff,"clr(), ");
}
if (q->mask & INIT) {
strcat (xbuff,q->hndlr);
strcat (xbuff,"init(), ");
}
xbuff[strlen(xbuff)-2] = ';';
xbuff[strlen(xbuff)-1] = NULL;
fprintf (fdconf,"%s\n",xbuff);
break;
case BLOCK:
fprintf (fdconf,"extern %sopen(), %sclose(), %sstrategy();\n",
p->handler,p->handler,p->handler);
fprintf (fdconf,"extern struct iobuf %stab;\n", p->handler);
break;
case BLOCK|CHAR:
q = find(p->devname);
sprintf (xbuff,"extern %sopen(), %sclose(), ",
q->hndlr,q->hndlr);
if (q->mask & READ) {
strcat (xbuff,q->hndlr);
strcat (xbuff,"read(), ");
}
if (q->mask & WRITE) {
strcat (xbuff,q->hndlr);
strcat (xbuff,"write(), ");
}
if (q->mask & IOCTL) {
strcat (xbuff,q->hndlr);
strcat (xbuff,"ioctl(), ");
}
if (q->mask & PWR)
if (power) {
strcat (xbuff,q->hndlr);
strcat (xbuff,"clr(), ");
}
if (q->mask & INIT) {
strcat (xbuff,q->hndlr);
strcat (xbuff,"init(), ");
}
strcat (xbuff,q->hndlr);
strcat (xbuff,"strategy();");
fprintf (fdconf,"%s\n",xbuff);
fprintf (fdconf,"extern struct iobuf %stab;\n", q->hndlr);
break;
}
}
fprintf (fdconf,"\nstruct bdevsw bdevsw[] = {\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, \tnodev, \tnodev, \t0, \n");
}
}
fprintf (fdconf,"};\n\n");
fprintf (fdconf,"struct cdevsw cdevsw[] = {\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,"\tnulldev,");
if (ptr->mask & CLOSE)
fprintf (fdconf,"\t%sclose,",ptr->hndlr);
else
fprintf (fdconf,"\tnulldev,");
if (ptr->mask & READ)
fprintf (fdconf,"\t%sread,",ptr->hndlr);
else
fprintf (fdconf,"\tnodev, ");
if (ptr->mask & WRITE)
fprintf (fdconf,"\t%swrite,",ptr->hndlr);
else
fprintf (fdconf,"\tnodev, ");
if (ptr->mask & IOCTL)
fprintf (fdconf,"\t%sioctl,\n",ptr->hndlr);
else
fprintf (fdconf,"\tnodev, \n");
}
else
fprintf (fdconf,"\tnodev, \tnodev, \tnodev, \tnodev, \tnodev,\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 = %d;\nint\tcdevcnt = %d;\n\n",i,j);
fprintf (fdconf,"dev_t\trootdev = makedev(%d, %d);\n",rtmaj,rtmin);
fprintf (fdconf,"dev_t\tpipedev = makedev(%d, %d);\n",pipmaj,pipmin);
fprintf (fdconf,"dev_t\tdumpdev = makedev(%d, %d);\n",dmpmaj,dmpmin);
fprintf (fdconf,"dev_t\tswapdev = makedev(%d, %d);\n",swpmaj,swpmin);
fprintf (fdconf,"daddr_t\tswplo = %lu;\nint\tnswap = %d;\n\n",swplo,nswap);
/*
* Initialize the power fail and init handler buffers.
*/
sprintf (pwrbuff,"\nint\t(*pwr_clr[])() = \n{\n");
sprintf (initbuff,"\nint\t(*dev_init[])() = \n{\n");
/*
* Go through the block device table, ignoring any zero entries.
* Add power fail and init handler entries to the buffers as appropriate.
*/
if (tflag)
printf ("Block Devices\nmajor\tdevice\thandler\tcount\n");
for (i=0; i<=bmax; i++) {
if ((q=bdevices[i]) == 0)
continue;
if (power)
if (q->mask & PWR)
sprintf (&pwrbuff[strlen(pwrbuff)],"\t%sclr,\n",q->hndlr);
if (q->mask & INIT)
sprintf (&initbuff[strlen(initbuff)],"\t&%sinit,\n",q->hndlr);
counter = 0;
/*
* 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.
*/
fprintf (fdconf,"\n");
if (q->asize)
fprintf (fdconf,"int\t%s_addr[] = {\n",q->hndlr);
for (p=table; p<= &table[tbound]; p++) {
if (equal(q->dev,p->devname)) {
if (q->asize)
fprintf(fdconf,"\tUBA_DEV+%.7o,\n",p->address);
counter += p->mlt;
}
}
if (q->asize)
fprintf (fdconf,"};\n");
if (!(q->type2 & NOCNT))
fprintf (fdconf,"int\t%s_cnt = %d;\n",
q->hndlr,counter);
if (tflag)
printf ("%2d\t%s\t%s\t%2d\n",i,q->dev,q->hndlr,counter);
q->acount = 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 are not strictly character devices.
* Add power fail and init handler entries to the buffers as appropriate.
*/
if (tflag)
printf ("Character Devices\nmajor\tdevice\thandler\tcount\n");
for (i=0; i<=cmax; i++) {
if ((q=cdevices[i]) == 0)
continue;
if ((q->type2 & (BLOCK|CHAR)) != CHAR) {
if (tflag)
printf ("%2d\t%s\t%s\t%2d\n",i,q->dev,q->hndlr,q->acount);
continue;
}
if (power)
if (q->mask & PWR)
sprintf (&pwrbuff[strlen(pwrbuff)],"\t%sclr,\n",q->hndlr);
if (q->mask & INIT)
sprintf (&initbuff[strlen(initbuff)],"\t&%sinit(),\n",q->hndlr);
counter = 0;
/*
* 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.
*/
fprintf (fdconf,"\n");
if (q->asize)
fprintf (fdconf,"int\t%s_addr[] = {\n",q->hndlr);
for (p=table; p<= &table[tbound]; p++) {
if (equal(q->dev,p->devname)) {
if (q->asize)
fprintf(fdconf,"\tUBA_DEV+%.7o,\n",p->address);
counter += p->mlt;
}
}
if (q->asize)
fprintf (fdconf,"};\n");
if (!(q->type2 & NOCNT))
fprintf (fdconf,"int\t%s_cnt = %d;\n",
q->hndlr,counter);
if (tflag)
printf ("%2d\t%s\t%s\t%2d\n",i,q->dev,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 this swill for the weirdo devices.
*/
for (k=0; (sname=sdev[k]) != NULL; k++)
if (locate(sname)) {
q = find(sname);
counter = 0;
fprintf (fdconf,"\nint\t%s_addr[] = {\n",q->hndlr);
for (p=table; p<= &table[tbound]; p++) {
if (equal (p->devname,sname)) {
fprintf (fdconf,"\tUBA_DEV+%.7o,\n",p->address);
counter += p->mlt;
}
}
fprintf (fdconf,"};\n");
if (!(q->type2 & NOCNT))
fprintf (fdconf,"int\t%s_cnt = %d;\n",
q->hndlr,counter);
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);
}
}
/*
* Write out NULL entry into power fail and init buffers.
* Then write the buffers out into the configuration file.
*/
sprintf (&pwrbuff[strlen(pwrbuff)],"\t(int (*)())0\n};\n");
sprintf (&initbuff[strlen(initbuff)],"\t(int (*)())0\n};\n");
fprintf (fdconf,"%s",pwrbuff);
fprintf (fdconf,"%s",initbuff);
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.
*/
struct t *
locate(device)
char *device;
{
register struct t *p;
register struct t3 *r;
for (;;) {
/*
* Search the configuration table for the specified device.
*/
for (p=table; 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; 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.
*/
struct t4 *
lookup(keyword)
char *keyword;
{
register struct t4 *kwdptr;
for (kwdptr=parms; 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.
*/
char *
uppermap(device,caps)
char *device;
char *caps;
{
register char *ptr;
register char *ptr2;
ptr2 = caps;
for (ptr=device; *ptr!=NULL; ptr++) {
if ('a' <= *ptr && *ptr <= 'z')
*ptr2++ = *ptr + 'A' - 'a';
else
*ptr2++ = *ptr;
}
*ptr2 = NULL;
return (caps);
}
/*
* This routine enters the device in the configuration table.
*/
enterdev(vec,add,bl,ml,name)
int vec, bl, ml;
unsigned add;
char *name;
{
tbound++;
if (tbound == TSIZE) {
printf ("Configuration table overflow\n");
exit(1);
}
/*
* Write upper case define statement and sequence number for device.
*/
fprintf (fdconf,"#define\t%s_%d 1\n",
uppermap (name,capitals),
q->dcount);
if (q->vsize)
setlow(vec);
setq();
p->devname = q->dev;
p->vector = vec;
p->address = add;
p->buslevel = bl;
p->addrsize = q->asize;
p->vectsize = q->vsize;
p->type = q->type2;
p->handler = q->hndlr;
p->count = q->dcount;
p->mlt = ml;
p->blk = q->block;
p->chr = q->charr;
p++;
q->dcount++;
return;
}
/*
* This routine enters the appropriate pointer for the device
* into low core.
*/
setlow(vec)
int vec;
{
subv = vec/4;
if (q->vsize == 8)
lowptr[subv+1] = p;
lowptr[subv] = p;
return;
}
addrcheck(add,size)
unsigned short add;
short size;
{
register struct map *mp;
register struct map *hold;
for (mp= &map[mbound]; mp >= map; mp--) {
if (add >= mp->start) {
if ((add+size) > (mp->start+mp->length))
return(1);
if ((add == mp->start) &&
((size+add)==(mp->start+mp->length))) {
mbound--;
while (mp <= &map[mbound]) {
mp->start = (mp+1)->start;
mp->length = (mp+1)->length;
mp++;
}
return(0);
}
if (add == mp->start) {
mp->start += size;
mp->length -= size;
return(0);
}
if ((size + add) == (mp->start + mp->length)) {
mp->length -= size;
return(0);
}
hold = mp;
if ((mbound + 1) == MSIZE) {
printf ("Address map table overflow\n");
exit(1);
}
for (mp= &map[mbound]; mp >= hold; mp--) {
(mp+1)->start = mp->start;
(mp+1)->length = mp->length;
}
mp++;
mp->length = add - mp->start;
(mp+1)->start = size + add;
(mp+1)->length = (mp+1)->length-(size+add)+mp->start;
mbound++;
return(0);
}
}
return(1);
}