|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982,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: * @(#)autoconf.c 7.1 (Berkeley) 6/6/86 ! 7: */ ! 8: ! 9: /* ! 10: * Setup the system to run on the current machine. ! 11: * ! 12: * Configure() is called at boot time and initializes the uba and mba ! 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 "mba.h" ! 19: #include "uba.h" ! 20: ! 21: #include "pte.h" ! 22: ! 23: #include "param.h" ! 24: #include "systm.h" ! 25: #include "map.h" ! 26: #include "buf.h" ! 27: #include "dk.h" ! 28: #include "vm.h" ! 29: #include "conf.h" ! 30: #include "dmap.h" ! 31: #include "reboot.h" ! 32: ! 33: #include "cpu.h" ! 34: #include "mem.h" ! 35: #include "mtpr.h" ! 36: #include "nexus.h" ! 37: #include "scb.h" ! 38: #include "ioa.h" ! 39: #include "../vaxmba/mbareg.h" ! 40: #include "../vaxmba/mbavar.h" ! 41: #include "../vaxuba/ubareg.h" ! 42: #include "../vaxuba/ubavar.h" ! 43: ! 44: /* ! 45: * The following several variables are related to ! 46: * the configuration process, and are used in initializing ! 47: * the machine. ! 48: */ ! 49: int cold; /* if 1, still working on cold-start */ ! 50: int nexnum; /* current nexus number */ ! 51: int nsbi; /* current sbi number */ ! 52: int dkn; /* number of iostat dk numbers assigned so far */ ! 53: int cpuspeed = 1; /* relative cpu speed */ ! 54: ! 55: /* ! 56: * Addresses of the (locore) routines which bootstrap us from ! 57: * hardware traps to C code. Filled into the system control block ! 58: * as necessary. ! 59: */ ! 60: #if NMBA > 0 ! 61: int (*mbaintv[4])() = { Xmba0int, Xmba1int, Xmba2int, Xmba3int }; ! 62: #if NMBA > 4 ! 63: Need to expand the table for more than 4 massbus adaptors ! 64: #endif ! 65: #endif ! 66: #if defined(VAX780) || defined(VAX8600) ! 67: int (*ubaintv[])() = ! 68: { ! 69: Xua0int, Xua1int, Xua2int, Xua3int, ! 70: #if NUBA > 4 ! 71: Xua4int, Xua5int, Xua6int, Xua7int, ! 72: #endif ! 73: #if NUBA > 8 ! 74: Need to expand the table for more than 8 unibus adaptors ! 75: #endif ! 76: }; ! 77: #endif ! 78: ! 79: /* ! 80: * This allocates the space for the per-uba information, ! 81: * such as buffered data path usage. ! 82: */ ! 83: struct uba_hd uba_hd[NUBA]; ! 84: ! 85: /* ! 86: * Determine mass storage and memory configuration for a machine. ! 87: * Get cpu type, and then switch out to machine specific procedures ! 88: * which will probe adaptors to see what is out there. ! 89: */ ! 90: configure() ! 91: { ! 92: union cpusid cpusid; ! 93: register struct percpu *ocp; ! 94: register int *ip; ! 95: extern char Sysbase[]; ! 96: ! 97: cpusid.cpusid = mfpr(SID); ! 98: for (ocp = percpu; ocp->pc_cputype; ocp++) ! 99: if (ocp->pc_cputype == cpusid.cpuany.cp_type) { ! 100: cpuspeed = ocp->pc_cpuspeed; ! 101: probeio(ocp); ! 102: /* ! 103: * Write protect the scb and UNIBUS interrupt vectors. ! 104: * It is strange that this code is here, but this is ! 105: * as soon as we are done mucking with it, and the ! 106: * write-enable was done in assembly language ! 107: * to which we will never return. ! 108: */ ! 109: ip = (int *)Sysmap + 1; *ip &= ~PG_PROT; *ip |= PG_KR; ! 110: ip++; *ip &= ~PG_PROT; *ip |= PG_KR; ! 111: #if NUBA > 1 ! 112: ip++; *ip &= ~PG_PROT; *ip |= PG_KR; ! 113: #endif ! 114: mtpr(TBIS, Sysbase); ! 115: #if GENERIC ! 116: if ((boothowto & RB_ASKNAME) == 0) ! 117: setroot(); ! 118: setconf(); ! 119: #else ! 120: setroot(); ! 121: #endif ! 122: /* ! 123: * Configure swap area and related system ! 124: * parameter based on device(s) used. ! 125: */ ! 126: swapconf(); ! 127: cold = 0; ! 128: memenable(); ! 129: return; ! 130: } ! 131: printf("cpu type %d not configured\n", cpusid.cpuany.cp_type); ! 132: asm("halt"); ! 133: } ! 134: ! 135: /* ! 136: * Probe the main IO bus(es). ! 137: * The percpu structure gives us a handle on the addresses and/or types. ! 138: */ ! 139: probeio(pcpu) ! 140: register struct percpu *pcpu; ! 141: { ! 142: register struct iobus *iob; ! 143: int ioanum; ! 144: ! 145: ioanum = 0; ! 146: for (iob = pcpu->pc_io; ioanum < pcpu->pc_nioa; ioanum++, iob++) { ! 147: ! 148: switch (iob->io_type) { ! 149: ! 150: #if VAX780 || VAX750 || VAX730 || VAX630 ! 151: case IO_SBI780: ! 152: case IO_CMI750: ! 153: case IO_XXX730: ! 154: case IO_QBUS: ! 155: probenexi((struct nexusconnect *)iob->io_details); ! 156: break; ! 157: #endif ! 158: ! 159: #if VAX8600 ! 160: case IO_ABUS: ! 161: probe_Abus(ioanum, iob); ! 162: break; ! 163: #endif ! 164: default: ! 165: if (iob->io_addr) { ! 166: printf( ! 167: "IO adaptor %d, type %d, at address 0x%x is unsupported\n", ! 168: ioanum, iob->io_type, iob->io_addr); ! 169: } else ! 170: printf("IO adaptor %d, type %d, is unsupported\n", ! 171: ioanum, iob->io_type); ! 172: break; ! 173: } ! 174: } ! 175: } ! 176: ! 177: #if VAX8600 ! 178: probe_Abus(ioanum, iob) ! 179: register struct iobus *iob; ! 180: { ! 181: register struct ioa *ioap; ! 182: union ioacsr ioacsr; ! 183: int type; ! 184: struct sbia_regs *sbiaregs; ! 185: ! 186: ioap = &ioa[ioanum]; ! 187: ioaccess(iob->io_addr, Ioamap[ioanum], iob->io_size); ! 188: if (badaddr((caddr_t)ioap, 4)) ! 189: return; ! 190: ioacsr.ioa_csr = ioap->ioacsr.ioa_csr; ! 191: type = ioacsr.ioa_type & IOA_TYPMSK; ! 192: ! 193: switch (type) { ! 194: ! 195: case IOA_SBIA: ! 196: printf("SBIA%d at IO adaptor %d address 0x%x\n", ! 197: nsbi, ioanum, iob->io_addr); ! 198: probenexi((struct nexusconnect *)iob->io_details); ! 199: nsbi++; ! 200: sbiaregs = (struct sbia_regs *)ioap; ! 201: sbiaregs->sbi_errsum = -1; ! 202: sbiaregs->sbi_error = 0x1000; ! 203: sbiaregs->sbi_fltsts = 0xc0000; ! 204: break; ! 205: ! 206: default: ! 207: printf("IOA%d at address 0x%x is unsupported (type = 0x%x)\n", ! 208: ioanum, iob->io_addr, ioacsr.ioa_type); ! 209: break; ! 210: } ! 211: } ! 212: #endif ! 213: ! 214: /* ! 215: * Probe nexus space, finding the interconnects ! 216: * and setting up and probing mba's and uba's for devices. ! 217: */ ! 218: /*ARGSUSED*/ ! 219: probenexi(pnc) ! 220: register struct nexusconnect *pnc; ! 221: { ! 222: register struct nexus *nxv; ! 223: struct nexus *nxp = pnc->psb_nexbase; ! 224: union nexcsr nexcsr; ! 225: int i; ! 226: ! 227: nexnum = 0, nxv = &nexus[nsbi * NNEXSBI]; ! 228: for (; nexnum < pnc->psb_nnexus; nexnum++, nxp++, nxv++) { ! 229: ioaccess((caddr_t)nxp, Nexmap[nsbi * NNEXSBI + nexnum], ! 230: sizeof(struct nexus)); ! 231: if (badaddr((caddr_t)nxv, 4)) ! 232: continue; ! 233: if (pnc->psb_nextype && pnc->psb_nextype[nexnum] != NEX_ANY) ! 234: nexcsr.nex_csr = pnc->psb_nextype[nexnum]; ! 235: else ! 236: nexcsr = nxv->nexcsr; ! 237: if (nexcsr.nex_csr&NEX_APD) ! 238: continue; ! 239: switch (nexcsr.nex_type) { ! 240: ! 241: case NEX_MBA: ! 242: printf("mba%d at tr%d\n", nummba, nexnum); ! 243: if (nummba >= NMBA) { ! 244: printf("%d mba's", nummba++); ! 245: goto unconfig; ! 246: } ! 247: #if NMBA > 0 ! 248: mbafind(nxv, nxp); ! 249: nummba++; ! 250: #endif ! 251: break; ! 252: ! 253: case NEX_UBA0: ! 254: case NEX_UBA1: ! 255: case NEX_UBA2: ! 256: case NEX_UBA3: ! 257: printf("uba%d at tr%d\n", numuba, nexnum); ! 258: #if VAX750 ! 259: if (numuba >= 2 && cpu == VAX_750) { ! 260: printf("More than 2 UBA's"); ! 261: goto unsupp; ! 262: } ! 263: #endif ! 264: if (numuba >= NUBA) { ! 265: printf("%d uba's", ++numuba); ! 266: goto unconfig; ! 267: } ! 268: #if defined(VAX780) || defined(VAX8600) ! 269: if ((cpu == VAX_780) || (cpu == VAX_8600)) ! 270: setscbnex(ubaintv[numuba]); ! 271: #endif ! 272: i = nexcsr.nex_type - NEX_UBA0; ! 273: unifind((struct uba_regs *)nxv, (struct uba_regs *)nxp, ! 274: umem[numuba], pnc->psb_umaddr[i], UMEMmap[numuba], ! 275: pnc->psb_haveubasr); ! 276: #if defined(VAX780) || defined(VAX8600) ! 277: if ((cpu == VAX_780) || (cpu == VAX_8600)) ! 278: ((struct uba_regs *)nxv)->uba_cr = ! 279: UBACR_IFS|UBACR_BRIE| ! 280: UBACR_USEFIE|UBACR_SUEFIE| ! 281: (((struct uba_regs *)nxv)->uba_cr&0x7c000000); ! 282: #endif ! 283: numuba++; ! 284: break; ! 285: ! 286: case NEX_DR32: ! 287: /* there can be more than one... are there other codes??? */ ! 288: printf("dr32"); ! 289: goto unsupp; ! 290: ! 291: case NEX_MEM4: ! 292: case NEX_MEM4I: ! 293: case NEX_MEM16: ! 294: case NEX_MEM16I: ! 295: printf("mcr%d at tr%d\n", nmcr, nexnum); ! 296: if (nmcr >= 4) { ! 297: printf("5 mcr's"); ! 298: goto unsupp; ! 299: } ! 300: switch (cpu) { ! 301: case VAX_780: ! 302: mcrtype[nmcr] = M780C; ! 303: break; ! 304: case VAX_750: ! 305: mcrtype[nmcr] = M750; ! 306: break; ! 307: case VAX_730: ! 308: mcrtype[nmcr] = M730; ! 309: break; ! 310: } ! 311: mcraddr[nmcr++] = (struct mcr *)nxv; ! 312: break; ! 313: ! 314: case NEX_MEM64I: ! 315: case NEX_MEM64L: ! 316: case NEX_MEM64LI: ! 317: case NEX_MEM256I: ! 318: case NEX_MEM256L: ! 319: case NEX_MEM256LI: ! 320: printf("mcr%d (el) at tr%d\n", nmcr, nexnum); ! 321: if (nmcr >= 4) { ! 322: printf("5 mcr's"); ! 323: goto unsupp; ! 324: } ! 325: if (cpu == VAX_780) ! 326: mcrtype[nmcr] = M780EL; ! 327: mcraddr[nmcr++] = (struct mcr *)nxv; ! 328: if (nexcsr.nex_type != NEX_MEM64I && ! 329: nexcsr.nex_type != NEX_MEM256I) ! 330: break; ! 331: /* fall into ... */ ! 332: ! 333: case NEX_MEM64U: ! 334: case NEX_MEM64UI: ! 335: case NEX_MEM256U: ! 336: case NEX_MEM256UI: ! 337: printf("mcr%d (eu) at tr%d\n", nmcr, nexnum); ! 338: if (nmcr >= 4) { ! 339: printf("5 mcr's"); ! 340: goto unsupp; ! 341: } ! 342: if (cpu == VAX_780) ! 343: mcrtype[nmcr] = M780EU; ! 344: mcraddr[nmcr++] = (struct mcr *)nxv; ! 345: break; ! 346: ! 347: case NEX_MPM0: ! 348: case NEX_MPM1: ! 349: case NEX_MPM2: ! 350: case NEX_MPM3: ! 351: printf("mpm"); ! 352: goto unsupp; ! 353: ! 354: case NEX_CI: ! 355: printf("ci"); ! 356: goto unsupp; ! 357: ! 358: default: ! 359: printf("nexus type %x", nexcsr.nex_type); ! 360: unsupp: ! 361: printf(" unsupported (at tr %d)\n", nexnum); ! 362: continue; ! 363: unconfig: ! 364: printf(" not configured\n"); ! 365: continue; ! 366: } ! 367: } ! 368: if (nummba > NMBA) ! 369: nummba = NMBA; ! 370: if (numuba > NUBA) ! 371: numuba = NUBA; ! 372: } ! 373: ! 374: #if NMBA > 0 ! 375: struct mba_device *mbaconfig(); ! 376: /* ! 377: * Find devices attached to a particular mba ! 378: * and look for each device found in the massbus ! 379: * initialization tables. ! 380: */ ! 381: mbafind(nxv, nxp) ! 382: struct nexus *nxv, *nxp; ! 383: { ! 384: register struct mba_regs *mdp; ! 385: register struct mba_drv *mbd; ! 386: register struct mba_device *mi; ! 387: register struct mba_slave *ms; ! 388: int dn, dt, sn; ! 389: struct mba_device fnd; ! 390: ! 391: mdp = (struct mba_regs *)nxv; ! 392: mba_hd[nummba].mh_mba = mdp; ! 393: mba_hd[nummba].mh_physmba = (struct mba_regs *)nxp; ! 394: setscbnex(mbaintv[nummba]); ! 395: fnd.mi_mba = mdp; ! 396: fnd.mi_mbanum = nummba; ! 397: for (mbd = mdp->mba_drv, dn = 0; mbd < &mdp->mba_drv[8]; mbd++, dn++) { ! 398: if ((mbd->mbd_ds&MBDS_DPR) == 0) ! 399: continue; ! 400: mdp->mba_sr |= MBSR_NED; /* si kludge */ ! 401: dt = mbd->mbd_dt & 0xffff; ! 402: if (dt == 0) ! 403: continue; ! 404: if (mdp->mba_sr&MBSR_NED) ! 405: continue; /* si kludge */ ! 406: if (dt == MBDT_MOH) ! 407: continue; ! 408: fnd.mi_drive = dn; ! 409: #define qeq(a, b) ( a == b || a == '?' ) ! 410: if ((mi = mbaconfig(&fnd, dt)) && (dt & MBDT_TAP)) ! 411: for (sn = 0; sn < 8; sn++) { ! 412: mbd->mbd_tc = sn; ! 413: for (ms = mbsinit; ms->ms_driver; ms++) ! 414: if (ms->ms_driver == mi->mi_driver && ! 415: ms->ms_alive == 0 && ! 416: qeq(ms->ms_ctlr, mi->mi_unit) && ! 417: qeq(ms->ms_slave, sn) && ! 418: (*ms->ms_driver->md_slave)(mi, ms, sn)) { ! 419: printf("%s%d at %s%d slave %d\n" ! 420: , ms->ms_driver->md_sname ! 421: , ms->ms_unit ! 422: , mi->mi_driver->md_dname ! 423: , mi->mi_unit ! 424: , sn ! 425: ); ! 426: ms->ms_alive = 1; ! 427: ms->ms_ctlr = mi->mi_unit; ! 428: ms->ms_slave = sn; ! 429: } ! 430: } ! 431: } ! 432: mdp->mba_cr = MBCR_INIT; ! 433: mdp->mba_cr = MBCR_IE; ! 434: } ! 435: ! 436: /* ! 437: * Have found a massbus device; ! 438: * see if it is in the configuration table. ! 439: * If so, fill in its data. ! 440: */ ! 441: struct mba_device * ! 442: mbaconfig(ni, type) ! 443: register struct mba_device *ni; ! 444: register int type; ! 445: { ! 446: register struct mba_device *mi; ! 447: register short *tp; ! 448: register struct mba_hd *mh; ! 449: ! 450: for (mi = mbdinit; mi->mi_driver; mi++) { ! 451: if (mi->mi_alive) ! 452: continue; ! 453: tp = mi->mi_driver->md_type; ! 454: for (mi->mi_type = 0; *tp; tp++, mi->mi_type++) ! 455: if (*tp == (type&MBDT_TYPE)) ! 456: goto found; ! 457: continue; ! 458: found: ! 459: #define match(fld) (ni->fld == mi->fld || mi->fld == '?') ! 460: if (!match(mi_drive) || !match(mi_mbanum)) ! 461: continue; ! 462: printf("%s%d at mba%d drive %d\n", ! 463: mi->mi_driver->md_dname, mi->mi_unit, ! 464: ni->mi_mbanum, ni->mi_drive); ! 465: mi->mi_alive = 1; ! 466: mh = &mba_hd[ni->mi_mbanum]; ! 467: mi->mi_hd = mh; ! 468: mh->mh_mbip[ni->mi_drive] = mi; ! 469: mh->mh_ndrive++; ! 470: mi->mi_mba = ni->mi_mba; ! 471: mi->mi_drv = &mi->mi_mba->mba_drv[ni->mi_drive]; ! 472: mi->mi_mbanum = ni->mi_mbanum; ! 473: mi->mi_drive = ni->mi_drive; ! 474: /* ! 475: * If drive has never been seen before, ! 476: * give it a dkn for statistics. ! 477: */ ! 478: if (mi->mi_driver->md_info[mi->mi_unit] == 0) { ! 479: mi->mi_driver->md_info[mi->mi_unit] = mi; ! 480: if (mi->mi_dk && dkn < DK_NDRIVE) ! 481: mi->mi_dk = dkn++; ! 482: else ! 483: mi->mi_dk = -1; ! 484: } ! 485: (*mi->mi_driver->md_attach)(mi); ! 486: return (mi); ! 487: } ! 488: return (0); ! 489: } ! 490: #endif ! 491: ! 492: /* ! 493: * Fixctlrmask fixes the masks of the driver ctlr routines ! 494: * which otherwise save r10 and r11 where the interrupt and br ! 495: * level are passed through. ! 496: */ ! 497: fixctlrmask() ! 498: { ! 499: register struct uba_ctlr *um; ! 500: register struct uba_device *ui; ! 501: register struct uba_driver *ud; ! 502: #define phys(a,b) ((b)(((int)(a))&0x7fffffff)) ! 503: ! 504: for (um = ubminit; ud = phys(um->um_driver, struct uba_driver *); um++) ! 505: *phys(ud->ud_probe, short *) &= ~0xc00; ! 506: for (ui = ubdinit; ud = phys(ui->ui_driver, struct uba_driver *); ui++) ! 507: *phys(ud->ud_probe, short *) &= ~0xc00; ! 508: } ! 509: ! 510: /* ! 511: * Find devices on a UNIBUS. ! 512: * Uses per-driver routine to set <br,cvec> into <r11,r10>, ! 513: * and then fills in the tables, with help from a per-driver ! 514: * slave initialization routine. ! 515: */ ! 516: unifind(vubp, pubp, vumem, pumem, memmap, haveubasr) ! 517: struct uba_regs *vubp, *pubp; ! 518: caddr_t vumem, pumem; ! 519: struct pte *memmap; ! 520: int haveubasr; ! 521: { ! 522: #ifndef lint ! 523: register int br, cvec; /* MUST BE r11, r10 */ ! 524: #else ! 525: /* ! 526: * Lint doesn't realize that these ! 527: * can be initialized asynchronously ! 528: * when devices interrupt. ! 529: */ ! 530: register int br = 0, cvec = 0; ! 531: #endif ! 532: register struct uba_device *ui; ! 533: register struct uba_ctlr *um; ! 534: u_short *reg, *ap, addr; ! 535: struct uba_hd *uhp; ! 536: struct uba_driver *udp; ! 537: int i, (**ivec)(); ! 538: caddr_t ualloc, zmemall(); ! 539: extern int catcher[256]; ! 540: ! 541: #if VAX630 ! 542: /* ! 543: * The map registers start right at 20088000 on the ! 544: * ka630, so we have to subtract out the 2k offset to make the ! 545: * pointers work.. ! 546: */ ! 547: if (cpu == VAX_630) { ! 548: vubp = (struct uba_regs *)(((u_long)vubp)-0x800); ! 549: pubp = (struct uba_regs *)(((u_long)pubp)-0x800); ! 550: } ! 551: #endif ! 552: /* ! 553: * Initialize the UNIBUS, by freeing the map ! 554: * registers and the buffered data path registers ! 555: */ ! 556: uhp = &uba_hd[numuba]; ! 557: uhp->uh_map = (struct map *)calloc(UAMSIZ * sizeof (struct map)); ! 558: ubainitmaps(uhp); ! 559: ! 560: /* ! 561: * Save virtual and physical addresses ! 562: * of adaptor, and allocate and initialize ! 563: * the UNIBUS interrupt vector. ! 564: */ ! 565: uhp->uh_uba = vubp; ! 566: uhp->uh_physuba = pubp; ! 567: /* ! 568: * On the 8600, can't use UNIvec; ! 569: * the vectors for the second SBI overlap it. ! 570: */ ! 571: if (cpu == VAX_8600) ! 572: uhp->uh_vec = (int(**)())calloc(512); ! 573: else if (numuba == 0) ! 574: uhp->uh_vec = UNIvec; ! 575: #if NUBA > 1 ! 576: else if (numuba == 1) ! 577: uhp->uh_vec = UNI1vec; ! 578: else ! 579: uhp->uh_vec = (int(**)())calloc(512); ! 580: #endif ! 581: for (i = 0; i < 128; i++) ! 582: uhp->uh_vec[i] = ! 583: scbentry(&catcher[i*2], SCB_ISTACK); ! 584: /* ! 585: * Set last free interrupt vector for devices with ! 586: * programmable interrupt vectors. Use is to decrement ! 587: * this number and use result as interrupt vector. ! 588: */ ! 589: uhp->uh_lastiv = 0x200; ! 590: ! 591: #if VAX630 ! 592: /* ! 593: * Kludge time again. The q22 memory and device reg. address spaces ! 594: * are not physically contiguous, so we need 2 loops to map them ! 595: * into contiguous virtual space. ! 596: */ ! 597: if (cpu == VAX_630) { ! 598: ioaccess(pumem, memmap, (UBAPAGES-16)*NBPG); ! 599: ioaccess(0x20000000, memmap+(UBAPAGES-16), 16*NBPG); ! 600: } else ! 601: #endif ! 602: ioaccess(pumem, memmap, UBAPAGES * NBPG); ! 603: #if defined(VAX780) || defined(VAX8600) ! 604: if (haveubasr) { ! 605: vubp->uba_sr = vubp->uba_sr; ! 606: vubp->uba_cr = UBACR_IFS|UBACR_BRIE; ! 607: } ! 608: #endif ! 609: /* ! 610: * First configure devices that have unibus memory, ! 611: * allowing them to allocate the correct map registers. ! 612: */ ! 613: ubameminit(numuba); ! 614: /* ! 615: * Grab some memory to record the umem address space we allocate, ! 616: * so we can be sure not to place two devices at the same address. ! 617: * ! 618: * We could use just 1/8 of this (we only want a 1 bit flag) but ! 619: * we are going to give it back anyway, and that would make the ! 620: * code here bigger (which we can't give back), so ... ! 621: * ! 622: * One day, someone will make a unibus with something other than ! 623: * an 8K i/o address space, & screw this totally. ! 624: */ ! 625: ualloc = zmemall(memall, 8*1024); ! 626: if (ualloc == (caddr_t)0) ! 627: panic("no mem for unifind"); ! 628: ! 629: /* ! 630: * Map the first page of UNIBUS i/o ! 631: * space to the first page of memory ! 632: * for devices which will need to dma ! 633: * output to produce an interrupt. ! 634: */ ! 635: *(int *)(&vubp->uba_map[0]) = UBAMR_MRV; ! 636: ! 637: #define ubaoff(off) ((off)&0x1fff) ! 638: #define ubaddr(off) (u_short *)((int)vumem + (ubaoff(off)|0x3e000)) ! 639: /* ! 640: * Check each unibus mass storage controller. ! 641: * For each one which is potentially on this uba, ! 642: * see if it is really there, and if it is record it and ! 643: * then go looking for slaves. ! 644: */ ! 645: for (um = ubminit; udp = um->um_driver; um++) { ! 646: if (um->um_ubanum != numuba && um->um_ubanum != '?') ! 647: continue; ! 648: addr = (u_short)um->um_addr; ! 649: /* ! 650: * use the particular address specified first, ! 651: * or if it is given as "0", of there is no device ! 652: * at that address, try all the standard addresses ! 653: * in the driver til we find it ! 654: */ ! 655: for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) { ! 656: ! 657: if (ualloc[ubaoff(addr)]) ! 658: continue; ! 659: reg = ubaddr(addr); ! 660: if (badaddr((caddr_t)reg, 2)) ! 661: continue; ! 662: #if defined(VAX780) || defined(VAX8600) ! 663: if (haveubasr && vubp->uba_sr) { ! 664: vubp->uba_sr = vubp->uba_sr; ! 665: continue; ! 666: } ! 667: #endif ! 668: cvec = 0x200; ! 669: i = (*udp->ud_probe)(reg, um->um_ctlr, um); ! 670: #if defined(VAX780) || defined(VAX8600) ! 671: if (haveubasr && vubp->uba_sr) { ! 672: vubp->uba_sr = vubp->uba_sr; ! 673: continue; ! 674: } ! 675: #endif ! 676: if (i == 0) ! 677: continue; ! 678: printf("%s%d at uba%d csr %o ", ! 679: udp->ud_mname, um->um_ctlr, numuba, addr); ! 680: if (cvec == 0) { ! 681: printf("zero vector\n"); ! 682: continue; ! 683: } ! 684: if (cvec == 0x200) { ! 685: printf("didn't interrupt\n"); ! 686: continue; ! 687: } ! 688: printf("vec %o, ipl %x\n", cvec, br); ! 689: um->um_alive = 1; ! 690: um->um_ubanum = numuba; ! 691: um->um_hd = &uba_hd[numuba]; ! 692: um->um_addr = (caddr_t)reg; ! 693: udp->ud_minfo[um->um_ctlr] = um; ! 694: for (ivec = um->um_intr; *ivec; ivec++) { ! 695: um->um_hd->uh_vec[cvec/4] = ! 696: scbentry(*ivec, SCB_ISTACK); ! 697: cvec += 4; ! 698: } ! 699: for (ui = ubdinit; ui->ui_driver; ui++) { ! 700: if (ui->ui_driver != udp || ui->ui_alive || ! 701: ui->ui_ctlr != um->um_ctlr && ui->ui_ctlr != '?' || ! 702: ui->ui_ubanum != numuba && ui->ui_ubanum != '?') ! 703: continue; ! 704: if ((*udp->ud_slave)(ui, reg)) { ! 705: ui->ui_alive = 1; ! 706: ui->ui_ctlr = um->um_ctlr; ! 707: ui->ui_ubanum = numuba; ! 708: ui->ui_hd = &uba_hd[numuba]; ! 709: ui->ui_addr = (caddr_t)reg; ! 710: ui->ui_physaddr = pumem + ubdevreg(addr); ! 711: if (ui->ui_dk && dkn < DK_NDRIVE) ! 712: ui->ui_dk = dkn++; ! 713: else ! 714: ui->ui_dk = -1; ! 715: ui->ui_mi = um; ! 716: /* ui_type comes from driver */ ! 717: udp->ud_dinfo[ui->ui_unit] = ui; ! 718: printf("%s%d at %s%d slave %d\n", ! 719: udp->ud_dname, ui->ui_unit, ! 720: udp->ud_mname, um->um_ctlr, ui->ui_slave); ! 721: (*udp->ud_attach)(ui); ! 722: } ! 723: } ! 724: break; ! 725: } ! 726: } ! 727: /* ! 728: * Now look for non-mass storage peripherals. ! 729: */ ! 730: for (ui = ubdinit; udp = ui->ui_driver; ui++) { ! 731: if (ui->ui_ubanum != numuba && ui->ui_ubanum != '?' || ! 732: ui->ui_alive || ui->ui_slave != -1) ! 733: continue; ! 734: addr = (u_short)ui->ui_addr; ! 735: ! 736: for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) { ! 737: ! 738: if (ualloc[ubaoff(addr)]) ! 739: continue; ! 740: reg = ubaddr(addr); ! 741: if (badaddr((caddr_t)reg, 2)) ! 742: continue; ! 743: #if defined(VAX780) || defined(VAX8600) ! 744: if (haveubasr && vubp->uba_sr) { ! 745: vubp->uba_sr = vubp->uba_sr; ! 746: continue; ! 747: } ! 748: #endif ! 749: cvec = 0x200; ! 750: i = (*udp->ud_probe)(reg, ui); ! 751: #if defined(VAX780) || defined(VAX8600) ! 752: if (haveubasr && vubp->uba_sr) { ! 753: vubp->uba_sr = vubp->uba_sr; ! 754: continue; ! 755: } ! 756: #endif ! 757: if (i == 0) ! 758: continue; ! 759: printf("%s%d at uba%d csr %o ", ! 760: ui->ui_driver->ud_dname, ui->ui_unit, numuba, addr); ! 761: if (cvec == 0) { ! 762: printf("zero vector\n"); ! 763: continue; ! 764: } ! 765: if (cvec == 0x200) { ! 766: printf("didn't interrupt\n"); ! 767: continue; ! 768: } ! 769: printf("vec %o, ipl %x\n", cvec, br); ! 770: while (--i >= 0) ! 771: ualloc[ubaoff(addr+i)] = 1; ! 772: ui->ui_hd = &uba_hd[numuba]; ! 773: for (ivec = ui->ui_intr; *ivec; ivec++) { ! 774: ui->ui_hd->uh_vec[cvec/4] = ! 775: scbentry(*ivec, SCB_ISTACK); ! 776: cvec += 4; ! 777: } ! 778: ui->ui_alive = 1; ! 779: ui->ui_ubanum = numuba; ! 780: ui->ui_addr = (caddr_t)reg; ! 781: ui->ui_physaddr = pumem + ubdevreg(addr); ! 782: ui->ui_dk = -1; ! 783: /* ui_type comes from driver */ ! 784: udp->ud_dinfo[ui->ui_unit] = ui; ! 785: (*udp->ud_attach)(ui); ! 786: break; ! 787: } ! 788: } ! 789: ! 790: #ifdef AUTO_DEBUG ! 791: printf("Unibus allocation map"); ! 792: for (i = 0; i < 8*1024; ) { ! 793: register n, m; ! 794: ! 795: if ((i % 128) == 0) { ! 796: printf("\n%6o:", i); ! 797: for (n = 0; n < 128; n++) ! 798: if (ualloc[i+n]) ! 799: break; ! 800: if (n == 128) { ! 801: i += 128; ! 802: continue; ! 803: } ! 804: } ! 805: ! 806: for (n = m = 0; n < 16; n++) { ! 807: m <<= 1; ! 808: m |= ualloc[i++]; ! 809: } ! 810: ! 811: printf(" %4x", m); ! 812: } ! 813: printf("\n"); ! 814: #endif ! 815: ! 816: wmemfree(ualloc, 8*1024); ! 817: } ! 818: ! 819: setscbnex(fn) ! 820: int (*fn)(); ! 821: { ! 822: register struct scb *scbp = &scb; ! 823: ! 824: scbp = (struct scb *)((caddr_t)scbp + nsbi * 512); ! 825: scbp->scb_ipl14[nexnum] = scbp->scb_ipl15[nexnum] = ! 826: scbp->scb_ipl16[nexnum] = scbp->scb_ipl17[nexnum] = ! 827: scbentry(fn, SCB_ISTACK); ! 828: } ! 829: ! 830: /* ! 831: * Make an IO register area accessible at physical address physa ! 832: * by mapping kernel ptes starting at pte. ! 833: */ ! 834: ioaccess(physa, pte, size) ! 835: caddr_t physa; ! 836: register struct pte *pte; ! 837: int size; ! 838: { ! 839: register int i = btop(size); ! 840: register unsigned v = btop(physa); ! 841: ! 842: do ! 843: *(int *)pte++ = PG_V|PG_KW|v++; ! 844: while (--i > 0); ! 845: mtpr(TBIA, 0); ! 846: } ! 847: ! 848: /* ! 849: * Configure swap space and related parameters. ! 850: */ ! 851: swapconf() ! 852: { ! 853: register struct swdevt *swp; ! 854: register int nblks; ! 855: ! 856: for (swp = swdevt; swp->sw_dev; swp++) { ! 857: if (bdevsw[major(swp->sw_dev)].d_psize) { ! 858: nblks = ! 859: (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev); ! 860: if (swp->sw_nblks == 0 || swp->sw_nblks > nblks) ! 861: swp->sw_nblks = nblks; ! 862: } ! 863: } ! 864: if (!cold) /* in case called for mba device */ ! 865: return; ! 866: if (dumplo == 0 && bdevsw[major(dumpdev)].d_psize) ! 867: dumplo = (*bdevsw[major(dumpdev)].d_psize)(dumpdev) - physmem; ! 868: if (dumplo < 0) ! 869: dumplo = 0; ! 870: } ! 871: ! 872: #define DOSWAP /* Change swdevt, argdev, and dumpdev too */ ! 873: u_long bootdev; /* should be dev_t, but not until 32 bits */ ! 874: ! 875: static char devname[][2] = { ! 876: 'h','p', /* 0 = hp */ ! 877: 0,0, /* 1 = ht */ ! 878: 'u','p', /* 2 = up */ ! 879: 'r','k', /* 3 = hk */ ! 880: 0,0, /* 4 = sw */ ! 881: 0,0, /* 5 = tm */ ! 882: 0,0, /* 6 = ts */ ! 883: 0,0, /* 7 = mt */ ! 884: 0,0, /* 8 = tu */ ! 885: 'r','a', /* 9 = ra */ ! 886: 0,0, /* 10 = ut */ ! 887: 'r','b', /* 11 = rb */ ! 888: 0,0, /* 12 = uu */ ! 889: 0,0, /* 13 = rx */ ! 890: 'r','l', /* 14 = rl */ ! 891: }; ! 892: ! 893: #define PARTITIONMASK 0x7 ! 894: #define PARTITIONSHIFT 3 ! 895: ! 896: /* ! 897: * Attempt to find the device from which we were booted. ! 898: * If we can do so, and not instructed not to do so, ! 899: * change rootdev to correspond to the load device. ! 900: */ ! 901: setroot() ! 902: { ! 903: int majdev, mindev, unit, part, adaptor; ! 904: dev_t temp, orootdev; ! 905: struct swdevt *swp; ! 906: ! 907: if (boothowto & RB_DFLTROOT || ! 908: (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) ! 909: return; ! 910: majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK; ! 911: if (majdev > sizeof(devname) / sizeof(devname[0])) ! 912: return; ! 913: adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK; ! 914: part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK; ! 915: unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK; ! 916: if (majdev == 0) { /* MBA device */ ! 917: #if NMBA > 0 ! 918: register struct mba_device *mbap; ! 919: int mask; ! 920: ! 921: /* ! 922: * The MBA number used at boot time is not necessarily the same as the ! 923: * MBA number used by the kernel. In order to change the rootdev we need to ! 924: * convert the boot MBA number to the kernel MBA number. The address space ! 925: * for an MBA used by the boot code is 0x20010000 + 0x2000 * MBA_number ! 926: * on the 78? and 86?0, 0xf28000 + 0x2000 * MBA_number on the 750. ! 927: * Therefore we can search the mba_hd table for the MBA that has the physical ! 928: * address corresponding to the boot MBA number. ! 929: */ ! 930: #define PHYSADRSHFT 13 ! 931: #define PHYSMBAMASK780 0x7 ! 932: #define PHYSMBAMASK750 0x3 ! 933: ! 934: switch (cpu) { ! 935: ! 936: case VAX_780: ! 937: case VAX_8600: ! 938: default: ! 939: mask = PHYSMBAMASK780; ! 940: break; ! 941: ! 942: case VAX_750: ! 943: mask = PHYSMBAMASK750; ! 944: break; ! 945: } ! 946: for (mbap = mbdinit; mbap->mi_driver; mbap++) ! 947: if (mbap->mi_alive && mbap->mi_drive == unit && ! 948: (((long)mbap->mi_hd->mh_physmba >> PHYSADRSHFT) ! 949: & mask) == adaptor) ! 950: break; ! 951: if (mbap->mi_driver == 0) ! 952: return; ! 953: mindev = mbap->mi_unit; ! 954: #else ! 955: return; ! 956: #endif ! 957: } else { ! 958: register struct uba_device *ubap; ! 959: ! 960: for (ubap = ubdinit; ubap->ui_driver; ubap++) ! 961: if (ubap->ui_alive && ubap->ui_slave == unit && ! 962: ubap->ui_ubanum == adaptor && ! 963: ubap->ui_driver->ud_dname[0] == devname[majdev][0] && ! 964: ubap->ui_driver->ud_dname[1] == devname[majdev][1]) ! 965: break; ! 966: ! 967: if (ubap->ui_driver == 0) ! 968: return; ! 969: mindev = ubap->ui_unit; ! 970: } ! 971: mindev = (mindev << PARTITIONSHIFT) + part; ! 972: orootdev = rootdev; ! 973: rootdev = makedev(majdev, mindev); ! 974: /* ! 975: * If the original rootdev is the same as the one ! 976: * just calculated, don't need to adjust the swap configuration. ! 977: */ ! 978: if (rootdev == orootdev) ! 979: return; ! 980: ! 981: printf("Changing root device to %c%c%d%c\n", ! 982: devname[majdev][0], devname[majdev][1], ! 983: mindev >> PARTITIONSHIFT, part + 'a'); ! 984: ! 985: #ifdef DOSWAP ! 986: mindev &= ~PARTITIONMASK; ! 987: for (swp = swdevt; swp->sw_dev; swp++) { ! 988: if (majdev == major(swp->sw_dev) && ! 989: mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) { ! 990: temp = swdevt[0].sw_dev; ! 991: swdevt[0].sw_dev = swp->sw_dev; ! 992: swp->sw_dev = temp; ! 993: break; ! 994: } ! 995: } ! 996: if (swp->sw_dev == 0) ! 997: return; ! 998: ! 999: /* ! 1000: * If argdev and dumpdev were the same as the old primary swap ! 1001: * device, move them to the new primary swap device. ! 1002: */ ! 1003: if (temp == dumpdev) ! 1004: dumpdev = swdevt[0].sw_dev; ! 1005: if (temp == argdev) ! 1006: argdev = swdevt[0].sw_dev; ! 1007: #endif ! 1008: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.