|
|
1.1 ! root 1: /* autoconf.c 4.32 81/11/11 */ ! 2: ! 3: /* ! 4: * Setup the system to run on the current machine. ! 5: * ! 6: * Configure() is called at boot time and initializes the uba and mba ! 7: * device tables and the memory controller monitoring. Available ! 8: * devices are determined (from possibilities mentioned in ioconf.c), ! 9: * and the drivers are initialized. ! 10: * ! 11: * N.B.: A lot of the conditionals based on processor type say ! 12: * #if VAX780 ! 13: * and ! 14: * #if VAX750 ! 15: * which may be incorrect after more processors are introduced if they ! 16: * are like either of these machines. ! 17: * ! 18: * TODO: ! 19: * use pcpu info about whether a ubasr exists ! 20: */ ! 21: ! 22: #include "mba.h" ! 23: ! 24: #include "../h/param.h" ! 25: #include "../h/systm.h" ! 26: #include "../h/map.h" ! 27: #include "../h/nexus.h" ! 28: #include "../h/pte.h" ! 29: #include "../h/buf.h" ! 30: #include "../h/mbareg.h" ! 31: #include "../h/mbavar.h" ! 32: #include "../h/dk.h" ! 33: #include "../h/vm.h" ! 34: #include "../h/ubareg.h" ! 35: #include "../h/ubavar.h" ! 36: #include "../h/mtpr.h" ! 37: #include "../h/cpu.h" ! 38: #include "../h/scb.h" ! 39: #include "../h/mem.h" ! 40: ! 41: /* ! 42: * The following several variables are related to ! 43: * the configuration process, and are used in initializing ! 44: * the machine. ! 45: */ ! 46: int cold; /* if 1, still working on cold-start */ ! 47: int nexnum; /* current nexus number */ ! 48: int dkn; /* number of iostat dk numbers assigned so far */ ! 49: ! 50: /* ! 51: * Addresses of the (locore) routines which bootstrap us from ! 52: * hardware traps to C code. Filled into the system control block ! 53: * as necessary. ! 54: */ ! 55: #if NMBA > 0 ! 56: int (*mbaintv[4])() = { Xmba0int, Xmba1int, Xmba2int, Xmba3int }; ! 57: #endif ! 58: #if VAX780 ! 59: int (*ubaintv[4])() = { Xua0int, Xua1int, Xua2int, Xua3int }; ! 60: #endif ! 61: ! 62: /* ! 63: * This allocates the space for the per-uba information, ! 64: * such as buffered data path usage. ! 65: */ ! 66: struct uba_hd uba_hd[MAXNUBA]; ! 67: ! 68: /* ! 69: * Determine mass storage and memory configuration for a machine. ! 70: * Get cpu type, and then switch out to machine specific procedures ! 71: * which will probe adaptors to see what is out there. ! 72: */ ! 73: configure() ! 74: { ! 75: union cpusid cpusid; ! 76: register struct percpu *ocp; ! 77: register int *ip; ! 78: extern char Sysbase[]; ! 79: ! 80: cpusid.cpusid = mfpr(SID); ! 81: for (ocp = percpu; ocp->pc_cputype; ocp++) ! 82: if (ocp->pc_cputype == cpusid.cpuany.cp_type) { ! 83: probenexus(ocp); ! 84: /* ! 85: * Write protect the scb. It is strange ! 86: * that this code is here, but this is as soon ! 87: * as we are done mucking with it, and the ! 88: * write-enable was done in assembly language ! 89: * to which we will never return. ! 90: */ ! 91: ip = (int *)Sysmap; *ip &= ~PG_PROT; *ip |= PG_KR; ! 92: mtpr(TBIS, Sysbase); ! 93: #if GENERIC ! 94: setconf(); ! 95: #endif ! 96: cold = 0; ! 97: memenable(); ! 98: return; ! 99: } ! 100: printf("cpu type %d not configured\n", cpusid.cpuany.cp_type); ! 101: asm("halt"); ! 102: } ! 103: ! 104: /* ! 105: * Probe nexus space, finding the interconnects ! 106: * and setting up and probing mba's and uba's for devices. ! 107: */ ! 108: /*ARGSUSED*/ ! 109: probenexus(pcpu) ! 110: register struct percpu *pcpu; ! 111: { ! 112: register struct nexus *nxv; ! 113: struct nexus *nxp = pcpu->pc_nexbase; ! 114: union nexcsr nexcsr; ! 115: int i; ! 116: ! 117: nexnum = 0, nxv = nexus; ! 118: for (; nexnum < pcpu->pc_nnexus; nexnum++, nxp++, nxv++) { ! 119: nxaccess(nxp, Nexmap[nexnum]); ! 120: if (badaddr((caddr_t)nxv, 4)) ! 121: continue; ! 122: if (pcpu->pc_nextype && pcpu->pc_nextype[nexnum] != NEX_ANY) ! 123: nexcsr.nex_csr = pcpu->pc_nextype[nexnum]; ! 124: else ! 125: nexcsr = nxv->nexcsr; ! 126: if (nexcsr.nex_csr&NEX_APD) ! 127: continue; ! 128: switch (nexcsr.nex_type) { ! 129: ! 130: case NEX_MBA: ! 131: printf("mba%d at tr%d\n", nummba, nexnum); ! 132: if (nummba >= NMBA) { ! 133: printf("%d mba's", nummba); ! 134: goto unconfig; ! 135: } ! 136: #if NMBA > 0 ! 137: mbafind(nxv, nxp); ! 138: nummba++; ! 139: #endif ! 140: break; ! 141: ! 142: case NEX_UBA0: ! 143: case NEX_UBA1: ! 144: case NEX_UBA2: ! 145: case NEX_UBA3: ! 146: printf("uba%d at tr%d\n", numuba, nexnum); ! 147: if (numuba >= 4) { ! 148: printf("5 uba's"); ! 149: goto unsupp; ! 150: } ! 151: #if VAX780 ! 152: if (cpu == VAX_780) ! 153: setscbnex(ubaintv[numuba]); ! 154: #endif ! 155: i = nexcsr.nex_type - NEX_UBA0; ! 156: unifind((struct uba_regs *)nxv, (struct uba_regs *)nxp, ! 157: umem[i], pcpu->pc_umaddr[i], UMEMmap[i]); ! 158: #if VAX780 ! 159: if (cpu == VAX_780) ! 160: ((struct uba_regs *)nxv)->uba_cr = ! 161: UBACR_IFS|UBACR_BRIE| ! 162: UBACR_USEFIE|UBACR_SUEFIE; ! 163: #endif ! 164: numuba++; ! 165: break; ! 166: ! 167: case NEX_DR32: ! 168: /* there can be more than one... are there other codes??? */ ! 169: printf("dr32"); ! 170: goto unsupp; ! 171: ! 172: case NEX_MEM4: ! 173: case NEX_MEM4I: ! 174: case NEX_MEM16: ! 175: case NEX_MEM16I: ! 176: printf("mcr%d at tr%d\n", nmcr, nexnum); ! 177: if (nmcr >= 4) { ! 178: printf("5 mcr's"); ! 179: goto unsupp; ! 180: } ! 181: mcraddr[nmcr++] = (struct mcr *)nxv; ! 182: break; ! 183: ! 184: case NEX_MPM0: ! 185: case NEX_MPM1: ! 186: case NEX_MPM2: ! 187: case NEX_MPM3: ! 188: printf("mpm"); ! 189: goto unsupp; ! 190: ! 191: default: ! 192: printf("nexus type %x", nexcsr.nex_type); ! 193: unsupp: ! 194: printf(" unsupported (at tr %d)\n", nexnum); ! 195: continue; ! 196: unconfig: ! 197: printf(" not configured\n"); ! 198: continue; ! 199: } ! 200: } ! 201: #if VAX780 ! 202: if (cpu == VAX_780) ! 203: { int ubawatch(); timeout(ubawatch, (caddr_t)0, hz); } ! 204: #endif ! 205: } ! 206: ! 207: #if NMBA > 0 ! 208: struct mba_device *mbaconfig(); ! 209: /* ! 210: * Find devices attached to a particular mba ! 211: * and look for each device found in the massbus ! 212: * initialization tables. ! 213: */ ! 214: mbafind(nxv, nxp) ! 215: struct nexus *nxv, *nxp; ! 216: { ! 217: register struct mba_regs *mdp; ! 218: register struct mba_drv *mbd; ! 219: register struct mba_device *mi; ! 220: register struct mba_slave *ms; ! 221: int dn, dt; ! 222: struct mba_device fnd; ! 223: ! 224: mdp = (struct mba_regs *)nxv; ! 225: mba_hd[nummba].mh_mba = mdp; ! 226: mba_hd[nummba].mh_physmba = (struct mba_regs *)nxp; ! 227: setscbnex(mbaintv[nummba]); ! 228: fnd.mi_mba = mdp; ! 229: fnd.mi_mbanum = nummba; ! 230: for (mbd = mdp->mba_drv, dn = 0; mbd < &mdp->mba_drv[8]; mbd++, dn++) { ! 231: dt = mbd->mbd_dt & 0xffff; ! 232: if (dt == 0) ! 233: continue; ! 234: if (dt == MBDT_MOH) ! 235: continue; ! 236: fnd.mi_drive = dn; ! 237: if ((mi = mbaconfig(&fnd, dt)) && (dt & MBDT_TAP)) { ! 238: for (ms = mbsinit; ms->ms_driver; ms++) ! 239: if (ms->ms_driver == mi->mi_driver && ms->ms_alive == 0 && ! 240: (ms->ms_ctlr == mi->mi_unit || ms->ms_ctlr=='?')) { ! 241: if ((*ms->ms_driver->md_slave)(mi, ms)) { ! 242: printf("%s%d at %s%d slave %d\n", ! 243: ms->ms_driver->md_sname, ! 244: ms->ms_unit, ! 245: mi->mi_driver->md_dname, ! 246: mi->mi_unit, ! 247: ms->ms_slave); ! 248: ms->ms_alive = 1; ! 249: ms->ms_ctlr = mi->mi_unit; ! 250: } ! 251: } ! 252: } ! 253: } ! 254: mdp->mba_cr = MBCR_INIT; ! 255: mdp->mba_cr = MBCR_IE; ! 256: } ! 257: ! 258: /* ! 259: * Have found a massbus device; ! 260: * see if it is in the configuration table. ! 261: * If so, fill in its data. ! 262: */ ! 263: struct mba_device * ! 264: mbaconfig(ni, type) ! 265: register struct mba_device *ni; ! 266: register int type; ! 267: { ! 268: register struct mba_device *mi; ! 269: register short *tp; ! 270: register struct mba_hd *mh; ! 271: ! 272: for (mi = mbdinit; mi->mi_driver; mi++) { ! 273: if (mi->mi_alive) ! 274: continue; ! 275: tp = mi->mi_driver->md_type; ! 276: for (mi->mi_type = 0; *tp; tp++, mi->mi_type++) ! 277: if (*tp == (type&MBDT_TYPE)) ! 278: goto found; ! 279: continue; ! 280: found: ! 281: #define match(fld) (ni->fld == mi->fld || mi->fld == '?') ! 282: if (!match(mi_drive) || !match(mi_mbanum)) ! 283: continue; ! 284: printf("%s%d at mba%d drive %d", ! 285: mi->mi_driver->md_dname, mi->mi_unit, ! 286: ni->mi_mbanum, ni->mi_drive); ! 287: printf("\n"); ! 288: mi->mi_alive = 1; ! 289: mh = &mba_hd[ni->mi_mbanum]; ! 290: mi->mi_hd = mh; ! 291: mh->mh_mbip[ni->mi_drive] = mi; ! 292: mh->mh_ndrive++; ! 293: mi->mi_mba = ni->mi_mba; ! 294: mi->mi_drv = &mi->mi_mba->mba_drv[ni->mi_drive]; ! 295: mi->mi_driver->md_info[mi->mi_unit] = mi; ! 296: mi->mi_mbanum = ni->mi_mbanum; ! 297: mi->mi_drive = ni->mi_drive; ! 298: if (mi->mi_dk && dkn < DK_NDRIVE) ! 299: mi->mi_dk = dkn++; ! 300: else ! 301: mi->mi_dk = -1; ! 302: (*mi->mi_driver->md_attach)(mi); ! 303: return (mi); ! 304: } ! 305: return (0); ! 306: } ! 307: #endif ! 308: ! 309: /* ! 310: * Fixctlrmask fixes the masks of the driver ctlr routines ! 311: * which otherwise save r10 and r11 where the interrupt and br ! 312: * level are passed through. ! 313: */ ! 314: fixctlrmask() ! 315: { ! 316: register struct uba_ctlr *um; ! 317: register struct uba_device *ui; ! 318: register struct uba_driver *ud; ! 319: #define phys(a,b) ((b)(((int)(a))&0x7fffffff)) ! 320: ! 321: for (um = ubminit; ud = phys(um->um_driver, struct uba_driver *); um++) ! 322: *phys(ud->ud_probe, short *) &= ~0xc00; ! 323: for (ui = ubdinit; ud = phys(ui->ui_driver, struct uba_driver *); ui++) ! 324: *phys(ud->ud_probe, short *) &= ~0xc00; ! 325: } ! 326: ! 327: /* ! 328: * Find devices on a UNIBUS. ! 329: * Uses per-driver routine to set <br,cvec> into <r11,r10>, ! 330: * and then fills in the tables, with help from a per-driver ! 331: * slave initialization routine. ! 332: */ ! 333: unifind(vubp, pubp, vumem, pumem, memmap) ! 334: struct uba_regs *vubp, *pubp; ! 335: caddr_t vumem, pumem; ! 336: struct pte *memmap; ! 337: { ! 338: #ifndef lint ! 339: register int br, cvec; /* MUST BE r11, r10 */ ! 340: #else ! 341: /* ! 342: * Lint doesn't realize that these ! 343: * can be initialized asynchronously ! 344: * when devices interrupt. ! 345: */ ! 346: register int br = 0, cvec = 0; ! 347: #endif ! 348: register struct uba_device *ui; ! 349: register struct uba_ctlr *um; ! 350: u_short *reg, addr; ! 351: struct uba_hd *uhp; ! 352: struct uba_driver *udp; ! 353: int i, (**ivec)(), haveubasr = 0; ! 354: ! 355: /* ! 356: * Initialize the UNIBUS, by freeing the map ! 357: * registers and the buffered data path registers ! 358: */ ! 359: uhp = &uba_hd[numuba]; ! 360: uhp->uh_map = (struct map *)calloc(UAMSIZ * sizeof (struct map)); ! 361: rminit(uhp->uh_map, NUBMREG, 1, "uba", UAMSIZ); ! 362: switch (cpu) { ! 363: #if VAX780 ! 364: case VAX_780: ! 365: uhp->uh_bdpfree = (1<<NBDP780) - 1; ! 366: haveubasr = 1; ! 367: break; ! 368: #endif ! 369: #if VAX750 ! 370: case VAX_750: ! 371: uhp->uh_bdpfree = (1<<NBDP750) - 1; ! 372: break; ! 373: #endif ! 374: #if VAX7ZZ ! 375: case VAX_7ZZ: ! 376: break; ! 377: #endif ! 378: } ! 379: ! 380: /* ! 381: * Save virtual and physical addresses ! 382: * of adaptor, and allocate and initialize ! 383: * the UNIBUS interrupt vector. ! 384: */ ! 385: uhp->uh_uba = vubp; ! 386: uhp->uh_physuba = pubp; ! 387: /* HAVE TO DO SOMETHING SPECIAL FOR SECOND UNIBUS ON COMETS HERE */ ! 388: if (numuba == 0) ! 389: uhp->uh_vec = UNIvec; ! 390: else ! 391: uhp->uh_vec = (int(**)())calloc(512); ! 392: for (i = 0; i < 128; i++) ! 393: uhp->uh_vec[i] = ! 394: scbentry(&catcher[i*2], SCB_ISTACK); ! 395: /* ! 396: * Set last free interrupt vector for devices with ! 397: * programmable interrupt vectors. Use is to decrement ! 398: * this number and use result as interrupt vector. ! 399: */ ! 400: uhp->uh_lastiv = 0x200; ! 401: ! 402: /* THIS IS A CHEAT: USING THE FACT THAT UMEM and NEXI ARE SAME SIZE */ ! 403: nxaccess((struct nexus *)pumem, memmap); ! 404: #if VAX780 ! 405: if (haveubasr) { ! 406: vubp->uba_sr = vubp->uba_sr; ! 407: vubp->uba_cr = UBACR_IFS|UBACR_BRIE; ! 408: } ! 409: #endif ! 410: /* ! 411: * Map the first page of UNIBUS i/o ! 412: * space to the first page of memory ! 413: * for devices which will need to dma ! 414: * output to produce an interrupt. ! 415: */ ! 416: *(int *)(&vubp->uba_map[0]) = UBAMR_MRV; ! 417: ! 418: #define ubaddr(off) (u_short *)((int)vumem + ((off)&0x1fff)) ! 419: /* ! 420: * Check each unibus mass storage controller. ! 421: * For each one which is potentially on this uba, ! 422: * see if it is really there, and if it is record it and ! 423: * then go looking for slaves. ! 424: */ ! 425: for (um = ubminit; udp = um->um_driver; um++) { ! 426: if (um->um_ubanum != numuba && um->um_ubanum != '?') ! 427: continue; ! 428: addr = (u_short)um->um_addr; ! 429: reg = ubaddr(addr); ! 430: if (badaddr((caddr_t)reg, 2)) ! 431: continue; ! 432: #if VAX780 ! 433: if (haveubasr && vubp->uba_sr) { ! 434: vubp->uba_sr = vubp->uba_sr; ! 435: continue; ! 436: } ! 437: #endif ! 438: cvec = 0x200; ! 439: i = (*udp->ud_probe)(reg); ! 440: #if VAX780 ! 441: if (haveubasr && vubp->uba_sr) { ! 442: vubp->uba_sr = vubp->uba_sr; ! 443: continue; ! 444: } ! 445: #endif ! 446: if (i == 0) ! 447: continue; ! 448: printf("%s%d at uba%d csr %o ", ! 449: udp->ud_mname, um->um_ctlr, numuba, addr); ! 450: if (cvec == 0) { ! 451: printf("zero vector\n"); ! 452: continue; ! 453: } ! 454: if (cvec == 0x200) { ! 455: printf("didn't interrupt\n"); ! 456: continue; ! 457: } ! 458: printf("vec %o, ipl %x\n", cvec, br); ! 459: um->um_alive = 1; ! 460: um->um_ubanum = numuba; ! 461: um->um_hd = &uba_hd[numuba]; ! 462: um->um_addr = (caddr_t)reg; ! 463: udp->ud_minfo[um->um_ctlr] = um; ! 464: for (ivec = um->um_intr; *ivec; ivec++) { ! 465: um->um_hd->uh_vec[cvec/4] = ! 466: scbentry(*ivec, SCB_ISTACK); ! 467: cvec += 4; ! 468: } ! 469: for (ui = ubdinit; ui->ui_driver; ui++) { ! 470: if (ui->ui_driver != udp || ui->ui_alive || ! 471: ui->ui_ctlr != um->um_ctlr && ui->ui_ctlr != '?' || ! 472: ui->ui_ubanum != numuba && ui->ui_ubanum != '?') ! 473: continue; ! 474: if ((*udp->ud_slave)(ui, reg)) { ! 475: ui->ui_alive = 1; ! 476: ui->ui_ctlr = um->um_ctlr; ! 477: ui->ui_ubanum = numuba; ! 478: ui->ui_hd = &uba_hd[numuba]; ! 479: ui->ui_addr = (caddr_t)reg; ! 480: ui->ui_physaddr = pumem + (addr&0x1fff); ! 481: if (ui->ui_dk && dkn < DK_NDRIVE) ! 482: ui->ui_dk = dkn++; ! 483: else ! 484: ui->ui_dk = -1; ! 485: ui->ui_mi = um; ! 486: /* ui_type comes from driver */ ! 487: udp->ud_dinfo[ui->ui_unit] = ui; ! 488: printf("%s%d at %s%d slave %d\n", ! 489: udp->ud_dname, ui->ui_unit, ! 490: udp->ud_mname, um->um_ctlr, ui->ui_slave); ! 491: (*udp->ud_attach)(ui); ! 492: } ! 493: } ! 494: } ! 495: /* ! 496: * Now look for non-mass storage peripherals. ! 497: */ ! 498: for (ui = ubdinit; udp = ui->ui_driver; ui++) { ! 499: if (ui->ui_ubanum != numuba && ui->ui_ubanum != '?' || ! 500: ui->ui_alive || ui->ui_slave != -1) ! 501: continue; ! 502: addr = (u_short)ui->ui_addr; ! 503: reg = ubaddr(addr); ! 504: if (badaddr((caddr_t)reg, 2)) ! 505: continue; ! 506: #if VAX780 ! 507: if (haveubasr && vubp->uba_sr) { ! 508: vubp->uba_sr = vubp->uba_sr; ! 509: continue; ! 510: } ! 511: #endif ! 512: cvec = 0x200; ! 513: i = (*udp->ud_probe)(reg, um->um_ctlr); ! 514: #if VAX780 ! 515: if (haveubasr && vubp->uba_sr) { ! 516: vubp->uba_sr = vubp->uba_sr; ! 517: continue; ! 518: } ! 519: #endif ! 520: if (i == 0) ! 521: continue; ! 522: printf("%s%d at uba%d csr %o ", ! 523: ui->ui_driver->ud_dname, ui->ui_unit, numuba, addr); ! 524: if (cvec == 0) { ! 525: printf("zero vector\n"); ! 526: continue; ! 527: } ! 528: if (cvec == 0x200) { ! 529: printf("didn't interrupt\n"); ! 530: continue; ! 531: } ! 532: printf("vec %o, ipl %x\n", cvec, br); ! 533: ui->ui_hd = &uba_hd[numuba]; ! 534: for (ivec = ui->ui_intr; *ivec; ivec++) { ! 535: ui->ui_hd->uh_vec[cvec/4] = ! 536: scbentry(*ivec, SCB_ISTACK); ! 537: cvec += 4; ! 538: } ! 539: ui->ui_alive = 1; ! 540: ui->ui_ubanum = numuba; ! 541: ui->ui_addr = (caddr_t)reg; ! 542: ui->ui_physaddr = pumem + (addr&0x1fff); ! 543: ui->ui_dk = -1; ! 544: /* ui_type comes from driver */ ! 545: udp->ud_dinfo[ui->ui_unit] = ui; ! 546: (*udp->ud_attach)(ui); ! 547: } ! 548: } ! 549: ! 550: setscbnex(fn) ! 551: int (*fn)(); ! 552: { ! 553: register struct scb *scbp = &scb; ! 554: ! 555: scbp->scb_ipl14[nexnum] = scbp->scb_ipl15[nexnum] = ! 556: scbp->scb_ipl16[nexnum] = scbp->scb_ipl17[nexnum] = ! 557: scbentry(fn, SCB_ISTACK); ! 558: } ! 559: ! 560: /* ! 561: * Make a nexus accessible at physical address phys ! 562: * by mapping kernel ptes starting at pte. ! 563: * ! 564: * WE LEAVE ALL NEXI MAPPED; THIS IS PERHAPS UNWISE ! 565: * SINCE MISSING NEXI DONT RESPOND. BUT THEN AGAIN ! 566: * PRESENT NEXI DONT RESPOND TO ALL OF THEIR ADDRESS SPACE. ! 567: */ ! 568: nxaccess(physa, pte) ! 569: struct nexus *physa; ! 570: register struct pte *pte; ! 571: { ! 572: register int i = btop(sizeof (struct nexus)); ! 573: register unsigned v = btop(physa); ! 574: ! 575: do ! 576: *(int *)pte++ = PG_V|PG_KW|v++; ! 577: while (--i > 0); ! 578: mtpr(TBIA, 0); ! 579: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.