1: /*
   2:  * Copyright (c) 1986 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  *
   6:  *	@(#)do_config.c	2.1 (2.11BSD GTE) 12/30/92
   7:  */
   8: 
   9: /*
  10:  * Now with all our information, make a configuration
  11:  * Devices without both attach and probe routines will
  12:  * not be configured into the system
  13:  */
  14: 
  15: #include <machine/psl.h>
  16: #include <machine/trap.h>
  17: #include <machine/autoconfig.h>
  18: #include <sys/types.h>
  19: #include <a.out.h>
  20: #include <errno.h>
  21: #include <stdio.h>
  22: #include "dtab.h"
  23: #include "ivec.h"
  24: 
  25: extern  int kmem, verbose, debug, errno, complain;
  26: extern  NLIST   *bad_nl, *good_nl, *int_nl, *end_vector, *trap_nl, *sep_nl;
  27: extern  NLIST   *next_nl;
  28: 
  29: grab(where)
  30: u_int   where;
  31: {
  32:     int var;
  33: 
  34:     lseek(kmem,((long) where) & 0xffffL,0);
  35:     read(kmem,&var,sizeof(var));
  36:     if (debug)
  37:         printf("Grab %o = %o",where, var);
  38:     return(var);
  39: }
  40: 
  41: stuff(var, where)
  42: unsigned int where;
  43: {
  44:     char s[20];
  45: 
  46:     if (debug) {
  47:         printf("Stuff %o @ %o\n", var, where);
  48:         return;
  49:     }
  50:     lseek(kmem, ((long) where) & 0xffffL, 0);
  51:     if (write(kmem, &var, sizeof var) < sizeof var) {
  52:         sprintf(s, "stuff 0%o", where);
  53:         perror(s);
  54:     }
  55: }
  56: 
  57: prdev(dp)
  58: DTAB    *dp;
  59: {
  60:     printf("%s ", dp->dt_name);
  61:     if (dp->dt_unit == -1)
  62:         putchar('?');
  63:     else
  64:         printf("%d", dp->dt_unit);
  65:     printf(" csr %o vector %o", dp->dt_addr, dp->dt_vector);
  66: }
  67: 
  68: /*
  69:  * Go through the configuration table and probe all the devices.  Call
  70:  * attach for ones which exist.  Probe routines should return
  71:  *	ACP_NXDEV	No such device
  72:  *	ACP_IFINTR	Device exists if interrupts ok
  73:  *	ACP_EXISTS	Device exists
  74:  * All interrupt vectors are poked to either point to conf_goodvec or
  75:  * conf_badvec which change the value of conf_int.  Values of this
  76:  * variable are:
  77:  *	ACI_BADINTR	Device interrupted through wrong vector
  78:  *	ACI_NOINTR	Device didn't interrupt
  79:  *	ACI_GOODINTR	Interrupt ok
  80:  */
  81: 
  82: auto_config()
  83: {
  84:     register DTAB   *dp;
  85:     int ret;
  86: 
  87:     if (intval() != CONF_MAGIC) {
  88:         fputs(myname,stderr);
  89:         fputs(": namelist doesn't match running kernel.\n",stderr);
  90:         exit(AC_SETUP);
  91:     }
  92: 
  93:     init_lowcore(bad_nl->n_value);
  94: 
  95:     for (dp = devs; dp != NULL; dp = dp->dt_next) {
  96:         /*
  97: 		 * Make sure we have both a probe and attach routine
  98: 		 */
  99:         if (!((dp->dt_uprobe || (dp->dt_probe && dp->dt_probe->n_value))
 100:             && (dp->dt_attach && dp->dt_attach->n_value))) {
 101:             if (debug || verbose) {
 102:                 prdev(dp);
 103:                 puts(" skipped:  No autoconfig routines.");
 104:             }
 105:             continue;
 106:         }           /* Make sure the CSR is there */
 107:         errno = 0;
 108:         grab(dp->dt_addr);
 109:         if (errno) {
 110:             if (errno != EFAULT && errno != ENXIO)
 111:                 perror("Reading CSR");
 112:             if (debug || verbose) {
 113:                 prdev(dp);
 114:                 puts(" skipped:  No CSR.");
 115:             }
 116:             continue;
 117:         }           /* Ok, try a probe now */
 118:         if (expect_intr(dp)) {
 119:             if (complain) {
 120:                 prdev(dp);
 121:                 puts(" interrupt vector already in use.");
 122:             }
 123:             continue;
 124:         }
 125:         ret = do_probe(dp);
 126:         clear_vec(dp);
 127:         switch (ret) {
 128:             case ACP_NXDEV:
 129:                 if (debug || verbose) {
 130:                     prdev(dp);
 131:                     puts(" does not exist.");
 132:                 }
 133:                 break;
 134:             case ACP_IFINTR:
 135:                 switch (intval()) {
 136:                     case ACI_BADINTR:
 137:                         if (debug || verbose || complain) {
 138:                             prdev(dp);
 139:                             puts(" interrupt vector wrong.");
 140:                         }
 141:                         break;
 142:                     case ACI_NOINTR:
 143:                         if (complain) {
 144:                             prdev(dp);
 145:                             puts(" didn't interrupt.");
 146:                         }
 147:                         break;
 148:                     case ACI_GOODINTR:
 149:                         attach(dp);
 150:                         break;
 151:                     default:
 152:                         prdev(dp);
 153:                         printf(" bad interrupt value %d.\n", intval());
 154:                         break;
 155:                 }
 156:                 break;
 157:             case ACP_EXISTS:
 158:                 attach(dp);
 159:                 break;
 160:             default:
 161:                 prdev(dp);
 162:                 printf(" bad probe value %d.\n", ret);
 163:                 break;
 164:         }
 165:     }
 166:     set_unused();
 167: }
 168: 
 169: /*
 170:  * Return the current value of the interrupt return flag.
 171:  * Initial value is the magic number
 172:  */
 173: 
 174: static int conf_int = CONF_MAGIC;
 175: 
 176: intval()
 177: {
 178:     if (debug)
 179:         return conf_int;
 180:     else
 181:         return grab(int_nl->n_value);
 182: }
 183: 
 184: static int save_vec[9][2], save_p;
 185: 
 186: /*
 187:  * Fill all interrupt vectors of this device with pointers to
 188:  * the good interrupt vector routine.  Also save values to
 189:  * later restore them.  Since we init_lowcore() everything to
 190:  * conf_badint, anything not equalling that indicates a vector
 191:  * which is already in use; unless the vector was initialized in l.s,
 192:  * this device should be skipped.
 193:  */
 194: 
 195: expect_intr(dp)
 196: DTAB    *dp;
 197: {
 198:     HAND    *hp;
 199:     register int    addr = dp->dt_vector;
 200: 
 201: /*
 202:  * A vector of 0 has special meaning for devices which support programmable
 203:  * (settable) vectors.  If a xxVec() entry point is present in the driver and
 204:  * /etc/dtab has a value of 0 for the vector then 'autoconfig' will allocate
 205:  * one by calling the kernel routine 'nextiv'.
 206:  *
 207:  * If multiple handlers are declared for a device (at present there are no
 208:  * progammable vector devices with more than 1 handler) the vector passed
 209:  * to the driver will be the lowest one (the first handle corresponds to
 210:  * the lowest vector).
 211: */
 212:     if (!addr) {
 213:         if (dp->dt_setvec == 0) {
 214:             prdev(dp);
 215:             printf(" vector = 0, %sVec undefined\n", dp->dt_name);
 216:             return(1);
 217:         }
 218: /*
 219:  * Now count the number of vectors needed.  This has the side effect of
 220:  * allocating the vectors even if an error occurs later.  At the end of
 221:  * the scan the last vector assigned will be the lowest one.  In order to
 222:  * assure adjacency of multiple vectors BR7 is used in the call to the
 223:  * kernel and it is assumed that at this point in the system's life
 224:  * nothing else is allocating vectors (the networking has already grabbed the
 225:  * ones it needs by the time autoconfig is run).
 226: */
 227:         for (hp = dp->dt_handlers; hp; hp = hp->s_next) {
 228:             addr = ucall(PSL_BR7, next_nl->n_value, 0, 0);
 229:             if (addr <= 0) {
 230:                 printf("'nextiv' error for %s\n",
 231:                     dp->dt_name);
 232:                 return(1);
 233:             }
 234:         }
 235: /*
 236:  * Now set the lowest vector allocated into the device entry for further
 237:  * processing.  From this point on the vector will behave just as if it
 238:  * had been read from /etc/dtab.
 239: */
 240:         dp->dt_vector = addr;
 241:     }
 242: 
 243:     for (save_p = 0, hp = (HAND *)dp->dt_handlers;hp;hp = hp->s_next) {
 244:         save_vec[save_p][1] = grab(addr + sizeof(int));
 245:         if (((save_vec[save_p][0] = grab(addr)) != bad_nl->n_value)
 246:             && ((save_vec[save_p][0] != hp->s_nl->n_value)
 247:             || have_set(addr))) {
 248:             clear_vec(dp);
 249:             return 1;
 250:         }
 251:         save_p++;
 252:         write_vector(addr, good_nl->n_value, PSL_BR7);
 253:         addr += IVSIZE;
 254:     }
 255:     return 0;
 256: }
 257: 
 258: clear_vec(dp)
 259: register DTAB   *dp;
 260: {
 261:     register int addr = dp->dt_vector, n;
 262: 
 263:     for (n = 0; n < save_p; n++) {
 264:         write_vector(addr, save_vec[n][0], save_vec[n][1]);
 265:         addr += IVSIZE;
 266:     }
 267: }
 268: 
 269: init_lowcore(val)
 270: {
 271:     int addr;
 272: 
 273:     if (debug)
 274:         return;
 275:     for (addr = 0; addr < end_vector->n_value; addr += IVSIZE) {
 276:         if (grab(addr) || grab(addr + 2))
 277:             continue;
 278:         write_vector(addr, val, PSL_BR7);
 279:     }
 280: }
 281: 
 282: do_probe(dp)
 283: register DTAB   *dp;
 284: {
 285:     int func;
 286:     int ret;
 287: 
 288:     func = dp->dt_probe->n_value;
 289:     if (debug) {
 290:         char line[80];
 291: 
 292:         if (func)
 293:             printf("ucall %o(PSL_BR0, %o, 0):", func, dp->dt_addr);
 294:         else
 295:             printf("probe %s:", dp->dt_name);
 296:         fputs(" return conf_int:",stdout);
 297:         gets(line);
 298:         sscanf(line, "%o%o", &ret, &conf_int);
 299:         return ret;
 300:     }
 301:     stuff(0, int_nl->n_value);  /* Clear conf_int */
 302:     /*
 303: 	 * use the kernel's probe routine if it exists,
 304: 	 * otherwise use our internal probe.  Pass it the first (lowest)
 305: 	 * vector assigned to the device.
 306: 	 */
 307:     if (func) {
 308:         errno = 0;
 309:         ret = ucall(PSL_BR0, func, dp->dt_addr, dp->dt_vector);
 310:         if (errno)
 311:             perror("ucall");
 312:         return(ret);
 313:     }
 314:     return((*(dp->dt_uprobe))(dp->dt_addr,  dp->dt_vector));
 315: }
 316: 
 317: set_unused()
 318: {
 319:     int addr;
 320: 
 321:     if (debug)
 322:         return;
 323:     if (sep_nl->n_value) {
 324:         /*
 325: 		 * On non-separate I/D kernel, attempt to set up catcher
 326: 		 * at 0 for both jumps and traps to 0.
 327: 		 * On traps, set PS for randomtrap, with the catcher at 0444.
 328: 		 * On jumps, branch to 0112, then to 050 (where there's space).
 329: 		 * The handler at 50 is already in place.
 330: 		 * The funny numbers are due to attempts to find vectors
 331: 		 * that are unlikely to be used, and the need for the value
 332: 		 * at 0 to serve as both a vector and an instruction
 333: 		 * (br 112 is octal 444).
 334: 		 */
 335:         if ((grab(0110) == bad_nl->n_value) && (grab(0112) == PSL_BR7)
 336:             && (grab(0444) == bad_nl->n_value) && (grab(0446) == PSL_BR7)) {
 337:             stuff(0444, 0);         /* br 0112 */
 338:             stuff(PSL_BR7 + T_ZEROTRAP, 2);
 339:             stuff(trap_nl->n_value, 0110);  /* trap; 756 (br7+14.)*/
 340:             stuff(0756, 0112);      /* br 050 */
 341:             stuff(0137, 0444);      /* jmp $*trap */
 342:             stuff(trap_nl->n_value, 0446);
 343:         }
 344:     }
 345:     for (addr = 0; addr < end_vector->n_value; addr += IVSIZE) {
 346:         if (grab(addr) != bad_nl->n_value)
 347:             continue;
 348:         write_vector(addr, trap_nl->n_value, PSL_BR7+T_RANDOMTRAP);
 349:     }
 350: }

Defined functions

auto_config defined in line 82; used 1 times
clear_vec defined in line 258; used 2 times
do_probe defined in line 282; used 1 times
expect_intr defined in line 195; used 1 times
init_lowcore defined in line 269; used 1 times
  • in line 93
intval defined in line 176; used 3 times
prdev defined in line 57; used 14 times
set_unused defined in line 317; used 1 times

Defined variables

conf_int defined in line 174; used 2 times
save_p defined in line 184; used 6 times
save_vec defined in line 184; used 5 times
Last modified: 1994-01-15
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3625
Valid CSS Valid XHTML 1.0 Strict