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: }