|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)autoconf.c 1.1 86/02/03 Copyr 1985 Sun Micro"; ! 3: #endif ! 4: ! 5: /* ! 6: * Copyright (c) 1985 by Sun Microsystems, Inc. ! 7: */ ! 8: ! 9: /* ! 10: * Setup the system to run on the current machine. ! 11: * ! 12: * Configure() is called at boot time and initializes the Mainbus ! 13: * device tables and the memory controller monitoring. Available ! 14: * devices are determined (from possibilities mentioned in ioconf.c), ! 15: * and the drivers are initialized. ! 16: */ ! 17: ! 18: #include "../h/param.h" ! 19: #include "../h/systm.h" ! 20: #include "../h/map.h" ! 21: #include "../h/buf.h" ! 22: #include "../h/dk.h" ! 23: #include "../h/vm.h" ! 24: #include "../h/conf.h" ! 25: #include "../h/file.h" ! 26: #include "../h/dir.h" ! 27: #include "../h/user.h" ! 28: #include "../h/proc.h" ! 29: ! 30: #include "../machine/pte.h" ! 31: #include "../machine/mmu.h" ! 32: #include "../machine/cpu.h" ! 33: #include "../machine/scb.h" ! 34: #include "../machine/mbvar.h" ! 35: #include "../machine/zsvar.h" ! 36: #include "../machine/sunromvec.h" ! 37: #include "../machine/idprom.h" ! 38: ! 39: /* ! 40: * The following several variables are related to ! 41: * the configuration process, and are used in initializing ! 42: * the machine. ! 43: */ ! 44: int dkn; /* number of iostat dk numbers assigned so far */ ! 45: ! 46: /* ! 47: * This allocates the space for the per-Mainbus information. ! 48: */ ! 49: struct mb_hd mb_hd; ! 50: ! 51: /* ! 52: * Determine mass storage and memory configuration for a machine. ! 53: * Get cpu type, and then switch out to machine specific procedures ! 54: * which will probe adaptors to see what is out there. ! 55: */ ! 56: configure() ! 57: { ! 58: ! 59: idprom(); ! 60: /* ! 61: * Configure the Mainbus. ! 62: */ ! 63: mbconfig(); ! 64: #ifdef GENERIC ! 65: setconf(); ! 66: #endif ! 67: } ! 68: ! 69: static int (*vec_save)(); /* used to save original vector value */ ! 70: ! 71: /* ! 72: * Find devices on the Mainbus. ! 73: * Uses per-driver routine to probe for existence of the device ! 74: * and then fills in the tables, with help from a per-driver ! 75: * slave initialization routine. ! 76: */ ! 77: mbconfig() ! 78: { ! 79: register struct mb_device *md; ! 80: register struct mb_ctlr *mc; ! 81: u_short *reg; ! 82: struct mb_driver *mdr; ! 83: u_short *doprobe(); ! 84: ! 85: vec_save = scb.scb_user[0]; /* save default trap routine */ ! 86: ! 87: /* ! 88: * Grab some memory to record the Mainbus address space in use, ! 89: * so we can be sure not to place two devices at the same address. ! 90: * If we run out of kernelmap space, we could reuse the mapped ! 91: * pages if we did all probes first to determine the target ! 92: * locations and sizes, and then remucked with the kernelmap to ! 93: * share spaces, then did all the attaches. ! 94: * ! 95: * We could use just 1/8 of this (we only want a 1 bit flag) but ! 96: * we are going to give it back anyway, and that would make the ! 97: * code here bigger (which we can't give back), so ... ! 98: */ ! 99: ! 100: /* ! 101: * Check each Mainbus mass storage controller. ! 102: * See if it is really there, and if it is record it and ! 103: * then go looking for slaves. ! 104: */ ! 105: for (mc = mbcinit; mdr = mc->mc_driver; mc++) { ! 106: if ((reg = doprobe((u_long)mc->mc_addr, (u_long)mc->mc_space, ! 107: mdr, mdr->mdr_cname, mc->mc_ctlr, mc->mc_intpri, ! 108: mc->mc_intr)) == 0) ! 109: continue; ! 110: mc->mc_alive = 1; ! 111: mc->mc_mh = &mb_hd; ! 112: mc->mc_addr = (caddr_t)reg; ! 113: if (mdr->mdr_cinfo) ! 114: mdr->mdr_cinfo[mc->mc_ctlr] = mc; ! 115: for (md = mbdinit; md->md_driver; md++) { ! 116: if (md->md_driver != mdr || md->md_alive || ! 117: md->md_ctlr != mc->mc_ctlr && md->md_ctlr != '?') ! 118: continue; ! 119: if ((*mdr->mdr_slave)(md, reg)) { ! 120: md->md_alive = 1; ! 121: md->md_ctlr = mc->mc_ctlr; ! 122: md->md_hd = &mb_hd; ! 123: md->md_addr = (caddr_t)reg; ! 124: if (md->md_dk && dkn < DK_NDRIVE) ! 125: md->md_dk = dkn++; ! 126: else ! 127: md->md_dk = -1; ! 128: md->md_mc = mc; ! 129: /* md_type comes from driver */ ! 130: if (mdr->mdr_dinfo) ! 131: mdr->mdr_dinfo[md->md_unit] = md; ! 132: printf("%s%d at %s%d slave %d\n", ! 133: mdr->mdr_dname, md->md_unit, ! 134: mdr->mdr_cname, mc->mc_ctlr, md->md_slave); ! 135: if (mdr->mdr_attach) ! 136: (*mdr->mdr_attach)(md); ! 137: } ! 138: } ! 139: } ! 140: ! 141: /* ! 142: * Now look for non-mass storage peripherals. ! 143: */ ! 144: for (md = mbdinit; mdr = md->md_driver; md++) { ! 145: if (md->md_alive || md->md_slave != -1) ! 146: continue; ! 147: if ((reg = doprobe((u_long)md->md_addr, (u_long)md->md_space, ! 148: mdr, mdr->mdr_dname, md->md_unit, md->md_intpri, ! 149: md->md_intr)) == 0) ! 150: continue; ! 151: md->md_hd = &mb_hd; ! 152: md->md_alive = 1; ! 153: md->md_addr = (caddr_t)reg; ! 154: md->md_dk = -1; ! 155: /* md_type comes from driver */ ! 156: if (mdr->mdr_dinfo) ! 157: mdr->mdr_dinfo[md->md_unit] = md; ! 158: if (mdr->mdr_attach) ! 159: (*mdr->mdr_attach)(md); ! 160: } ! 161: } ! 162: ! 163: /* ! 164: * Make non-zero if want to be set up to handle ! 165: * both vectored and auto-vectored interrupts ! 166: * for the same device at the same time. ! 167: */ ! 168: int paranoid = 0; ! 169: ! 170: /* ! 171: * Probe for a device or controller at the specified addr. ! 172: * The space argument give the page type and cpu type for the device. ! 173: */ ! 174: u_short * ! 175: doprobe(addr, space, mdr, dname, unit, br, vp) ! 176: register u_long addr, space; ! 177: register struct mb_driver *mdr; ! 178: char *dname; ! 179: int unit, br; ! 180: register struct vec *vp; ! 181: { ! 182: register u_short *reg = NULL; ! 183: char *name; ! 184: long a = 0; ! 185: int i, extent, machine; ! 186: u_int pageval; ! 187: ! 188: #define SP_MACHMASK 0xFFFF0000 /* space mask for machine type */ ! 189: #define MAKE_MACH(m) ((m)<<16) ! 190: #define SP_MACH_ALL MAKE_MACH(0) ! 191: ! 192: #define SP_BUSMASK 0x0000FFFF /* mask for bus type */ ! 193: #define SP_VIRTUAL 0x00000001 ! 194: #define SP_OBMEM 0x00000002 ! 195: #define SP_OBIO 0x00000004 ! 196: #define SP_VME16D16 0x00000100 ! 197: #define SP_VME24D16 0x00000200 ! 198: #define SP_VME32D16 0x00000400 ! 199: #define SP_VME16D32 0x00001000 ! 200: #define SP_VME24D32 0x00002000 ! 201: #define SP_VME32D32 0x00004000 ! 202: ! 203: machine = space & SP_MACHMASK; ! 204: ! 205: if (machine != SP_MACH_ALL && machine != MAKE_MACH(cpu & CPU_MACH)) ! 206: return(0); ! 207: ! 208: switch (space & SP_BUSMASK) { ! 209: ! 210: case SP_VIRTUAL: ! 211: name = "virtual"; ! 212: reg = (u_short *)addr; ! 213: break; ! 214: ! 215: case SP_OBMEM: ! 216: name = "obmem"; ! 217: pageval = PGT_OBMEM | btop(addr); ! 218: break; ! 219: ! 220: case SP_OBIO: ! 221: name = "obio"; ! 222: pageval = PGT_OBIO | btop(addr); ! 223: break; ! 224: ! 225: case SP_VME16D16: ! 226: name = "vme16d16"; ! 227: pageval = PGT_VME_D16 | btop(VME16_BASE | (addr & VME16_MASK)); ! 228: break; ! 229: ! 230: case SP_VME24D16: ! 231: name = "vme24d16"; ! 232: pageval = PGT_VME_D16 | btop(VME24_BASE | (addr & VME24_MASK)); ! 233: break; ! 234: ! 235: case SP_VME32D16: ! 236: name = "vme32d16"; ! 237: pageval = PGT_VME_D16 | btop(addr); ! 238: break; ! 239: ! 240: case SP_VME16D32: ! 241: name = "vme16d32"; ! 242: pageval = PGT_VME_D32 | btop(VME16_BASE | (addr & VME16_MASK)); ! 243: break; ! 244: ! 245: case SP_VME24D32: ! 246: name = "vme24d32"; ! 247: pageval = PGT_VME_D32 | btop(VME24_BASE | (addr & VME24_MASK)); ! 248: break; ! 249: ! 250: case SP_VME32D32: ! 251: name = "vme32d32"; ! 252: pageval = PGT_VME_D32 | btop(addr); ! 253: break; ! 254: ! 255: default: ! 256: return (0); ! 257: } ! 258: ! 259: if (reg == NULL) { ! 260: int offset = addr & PGOFSET; ! 261: ! 262: extent = btoc(mdr->mdr_size + offset); ! 263: if (extent == 0) ! 264: extent = 1; ! 265: if ((a = rmalloc(kernelmap, (long)extent)) == 0) ! 266: panic("out of kernelmap for devices"); ! 267: reg = (u_short *)((int)kmxtob(a) | offset); ! 268: mapin(&Usrptmap[a], btop(reg), pageval, extent, PG_V | PG_KW); ! 269: } ! 270: ! 271: i = (*mdr->mdr_probe)(reg, unit); ! 272: if (i == 0) { ! 273: if (a) ! 274: rmfree(kernelmap, (long)extent, a); ! 275: return (0); ! 276: } ! 277: printf("%s%d at %s %x ", dname, unit, name, addr); ! 278: if (br < 0 || br >= 7) { ! 279: printf("bad priority (%d)\n", br); ! 280: if (a) ! 281: rmfree(kernelmap, (long)extent, a); ! 282: return (0); ! 283: } ! 284: ! 285: /* ! 286: * If br is 0, then no priority was specified in the ! 287: * config file and the device cannot use interrupts. ! 288: */ ! 289: if (br != 0) { ! 290: /* ! 291: * If we are paranoid or vectored interrupts are not ! 292: * going to be used then set up for polling interrupts. ! 293: */ ! 294: if (paranoid || vp == (struct vec *)0) { ! 295: printf("pri %d ", br); ! 296: addintr(br, mdr); ! 297: } ! 298: ! 299: /* ! 300: * now set up vectored interrupts if conditions are right ! 301: */ ! 302: if (vp != (struct vec *)0) { ! 303: for (; vp->v_func; vp++) { ! 304: printf("vec 0x%x ", vp->v_vec); ! 305: if (vp->v_vec < VEC_MIN || vp->v_vec > VEC_MAX) ! 306: panic("bad vector"); ! 307: else if (scb.scb_user[vp->v_vec - VEC_MIN] != ! 308: vec_save) ! 309: panic("duplicate vector"); ! 310: else ! 311: scb.scb_user[vp->v_vec - VEC_MIN] = ! 312: vp->v_func; ! 313: } ! 314: } ! 315: } ! 316: printf("\n"); ! 317: return (reg); ! 318: } ! 319: ! 320: #define SPURIOUS 0x80000000 /* recognized in locore.s */ ! 321: ! 322: int level2_spurious, level3_spurious, level4_spurious, level6_spurious; ! 323: ! 324: not_serviced2() ! 325: { ! 326: ! 327: call_default_intr(); ! 328: if ((level2_spurious++ % 100) == 1) ! 329: printf("iobus level 2 interrupt not serviced\n"); ! 330: return (SPURIOUS); ! 331: } ! 332: ! 333: not_serviced3() ! 334: { ! 335: ! 336: call_default_intr(); ! 337: if ((level3_spurious++ % 100) == 1) ! 338: printf("iobus level 3 interrupt not serviced\n"); ! 339: return (SPURIOUS); ! 340: } ! 341: ! 342: not_serviced4() ! 343: { ! 344: ! 345: call_default_intr(); ! 346: if ((level4_spurious++ % 100) == 1) ! 347: printf("iobus level 4 interrupt not serviced\n"); ! 348: return (SPURIOUS); ! 349: } ! 350: ! 351: not_serviced6() ! 352: { ! 353: ! 354: call_default_intr(); ! 355: if ((level6_spurious++ % 100) == 1) ! 356: printf("iobus level 6 interrupt not serviced\n"); ! 357: return (SPURIOUS); ! 358: } ! 359: ! 360: typedef int (*func)(); ! 361: ! 362: #define NVECT 10 ! 363: ! 364: /* ! 365: * These vectors are used in locore.s to jump to device interrupt routines. ! 366: */ ! 367: func level2_vector[NVECT] = {not_serviced2}; ! 368: func level3_vector[NVECT] = {not_serviced3}; ! 369: func level4_vector[NVECT] = {not_serviced4}; ! 370: func level6_vector[NVECT] = {not_serviced6}; ! 371: ! 372: func *vector[7] = {NULL, NULL, level2_vector, level3_vector, ! 373: level4_vector, NULL, level6_vector}; ! 374: ! 375: /* ! 376: * Arrange for a driver to be called when a particular ! 377: * auto-vectored interrupt occurs. ! 378: * NOTE: every device sharing a driver must be on the ! 379: * same interrupt level for polling interrupts because ! 380: * there is only one entry made per driver. ! 381: */ ! 382: addintr(lvl, mdr) ! 383: struct mb_driver *mdr; ! 384: { ! 385: register func f; ! 386: register func *fp; ! 387: register int i; ! 388: ! 389: switch (lvl) { ! 390: case 1: ! 391: return; /* bogus - these devices don't interrupt */ ! 392: case 2: ! 393: fp = level2_vector; ! 394: break; ! 395: case 3: ! 396: fp = level3_vector; ! 397: break; ! 398: case 4: ! 399: fp = level4_vector; ! 400: break; ! 401: case 5: ! 402: panic("addintr called with level 5"); ! 403: /* NOTREACHED */ ! 404: case 6: ! 405: fp = level6_vector; ! 406: break; ! 407: default: ! 408: panic("addintr: unknown level"); ! 409: /* NOTREACHED */ ! 410: } ! 411: if ((f = mdr->mdr_intr) == NULL) ! 412: return; ! 413: for (i = 0; i < NVECT; i++) { ! 414: if (*fp == NULL) /* end of list found */ ! 415: break; ! 416: if (*fp == f) /* already in list */ ! 417: return; ! 418: fp++; ! 419: } ! 420: if (i >= NVECT) ! 421: panic("addintr: too many devices"); ! 422: fp[0] = fp[-1]; /* move not_serviced to end */ ! 423: fp[-1] = f; /* add f to list */ ! 424: } ! 425: ! 426: /* ! 427: * This is for crazy devices that don't know when they interrupt. ! 428: * We just call them at the end after all the sane devices have decided ! 429: * the interrupt is not their fault. ! 430: */ ! 431: func default_intrs[NVECT]; ! 432: ! 433: add_default_intr(f) ! 434: func f; ! 435: { ! 436: register int i; ! 437: register func *fp; ! 438: ! 439: fp = default_intrs; ! 440: for (i = 0; i < NVECT; i++) { ! 441: if (*fp == NULL) /* end of list found */ ! 442: break; ! 443: if (*fp == f) /* already in list */ ! 444: return; ! 445: fp++; ! 446: } ! 447: if (i >= NVECT) ! 448: panic("add_default_intr: too many devices"); ! 449: *fp = f; /* add f to list */ ! 450: } ! 451: ! 452: call_default_intr() ! 453: { ! 454: register func *fp; ! 455: ! 456: for (fp = default_intrs; *fp; fp++) ! 457: (*fp)(); ! 458: } ! 459: ! 460: /* ! 461: * Some things, like cputype, are contained in the idprom, but are ! 462: * needed and obtained earlier; hence they are not set (again) here. ! 463: */ ! 464: idprom() ! 465: { ! 466: register u_char *cp, val = 0; ! 467: register int i; ! 468: struct idprom id; ! 469: ! 470: getidprom((char *)&id); ! 471: cp = (u_char *)&id; ! 472: for (i = 0; i < 16; i++) ! 473: val ^= *cp++; ! 474: if (val != 0) ! 475: printf("WARNING: ID prom checksum error\n"); ! 476: if (id.id_format == 1) { ! 477: localetheraddr(id.id_ether, NULL); ! 478: } else ! 479: printf("INVALID FORMAT CODE IN ID PROM\n"); ! 480: } ! 481: ! 482: int cpudelay = 3; /* default to a medium range value here */ ! 483: ! 484: /* ! 485: * We set the cpu type and associated variables. Should there get to ! 486: * be too many variables, they should be collected together in a ! 487: * structure and indexed by cpu type. ! 488: */ ! 489: setcputype() ! 490: { ! 491: struct idprom id; ! 492: ! 493: cpu = -1; ! 494: getidprom((char *)&id); ! 495: if (id.id_format == 1) { ! 496: switch (id.id_machine) { ! 497: case CPU_SUN3_160: ! 498: case CPU_SUN3_50: ! 499: case CPU_SUN3_260: ! 500: cpu = id.id_machine; ! 501: break; ! 502: default: ! 503: printf("UNKNOWN MACHINE TYPE 0x%x IN ID PROM\n", ! 504: id.id_machine); ! 505: break; ! 506: } ! 507: } else ! 508: printf("INVALID FORMAT TYPE IN ID PROM\n"); ! 509: ! 510: if (cpu == -1) { ! 511: printf("DEFAULTING MACHINE TYPE TO SUN3_160\n"); ! 512: cpu = CPU_SUN3_160; ! 513: } ! 514: ! 515: /* ! 516: * Can't use the last segment for DVMA. ! 517: * The last is for on-board Ethernet scratch, ! 518: * u area, and miscellanous on-board devices. ! 519: * On the Sun-3, we can set dvmasize independent ! 520: * of the implementation. ! 521: */ ! 522: dvmasize = btoc(DVMASIZE) - NPAGSEG; ! 523: ! 524: switch (cpu) { ! 525: case CPU_SUN3_160: ! 526: #ifndef SUN3_160 ! 527: panic("not configured for SUN3_160"); ! 528: #endif !SUN3_160 ! 529: cpudelay = 3; ! 530: break; ! 531: case CPU_SUN3_50: ! 532: #ifndef SUN3_50 ! 533: panic("not configured for SUN3_50"); ! 534: #endif !SUN3_50 ! 535: cpudelay = 3; ! 536: break; ! 537: case CPU_SUN3_260: ! 538: #ifndef SUN3_260 ! 539: panic("not configured for SUN3_260"); ! 540: #endif !SUN3_260 ! 541: cpudelay = 2; ! 542: break; ! 543: } ! 544: } ! 545: ! 546: machineid() ! 547: { ! 548: struct idprom id; ! 549: register int x; ! 550: ! 551: getidprom((char *)&id); ! 552: x = id.id_machine << 24; ! 553: x += id.id_serial; ! 554: return (x); ! 555: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.