|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1988 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.4 (Berkeley) 6/28/90 ! 7: */ ! 8: ! 9: /* ! 10: * Setup the system to run on the current machine. ! 11: * ! 12: * Configure() is called at boot time and initializes the vba ! 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: #include "param.h" ! 18: #include "systm.h" ! 19: #include "map.h" ! 20: #include "buf.h" ! 21: #include "dkstat.h" ! 22: #include "vm.h" ! 23: #include "conf.h" ! 24: #include "dmap.h" ! 25: #include "reboot.h" ! 26: #include "malloc.h" ! 27: ! 28: #include "pte.h" ! 29: #include "mem.h" ! 30: #include "mtpr.h" ! 31: #include "scb.h" ! 32: ! 33: #include "vba.h" ! 34: ! 35: #include "../tahoevba/vbavar.h" ! 36: #include "../tahoevba/vbaparam.h" ! 37: ! 38: /* ! 39: * The following several variables are related to ! 40: * the configuration process, and are used in initializing ! 41: * the machine. ! 42: */ ! 43: int dkn; /* number of iostat dk numbers assigned so far */ ! 44: int cold; /* cold start flag initialized in locore.s */ ! 45: ! 46: /* ! 47: * This allocates the space for the per-vba information. ! 48: */ ! 49: struct vba_hd vba_hd[NVBA]; ! 50: ! 51: /* ! 52: * Determine i/o configuration for a machine. ! 53: */ ! 54: configure() ! 55: { ! 56: register int *ip; ! 57: extern caddr_t Sysbase; ! 58: ! 59: vbafind(numvba, (caddr_t)vmem, VMEMmap); ! 60: numvba++; ! 61: /* ! 62: * Write protect the scb. It is strange ! 63: * that this code is here, but this is as soon ! 64: * as we are done mucking with it, and the ! 65: * write-enable was done in assembly language ! 66: * to which we will never return. ! 67: */ ! 68: ip = (int *)&Sysmap[2]; *ip &= ~PG_PROT; *ip |= PG_KR; ! 69: mtpr(TBIS, Sysbase+2*NBPG); ! 70: #if GENERIC ! 71: if ((boothowto & RB_ASKNAME) == 0) ! 72: setroot(); ! 73: setconf(); ! 74: #else ! 75: setroot(); ! 76: #endif ! 77: /* ! 78: * Configure swap area and related system ! 79: * parameter based on device(s) used. ! 80: */ ! 81: swapconf(); ! 82: cold = 0; ! 83: } ! 84: ! 85: /* ! 86: * Make the controllers accessible at physical address phys ! 87: * by mapping kernel ptes starting at pte. ! 88: */ ! 89: vbaccess(pte, iobase, n) ! 90: register struct pte *pte; ! 91: caddr_t iobase; ! 92: register int n; ! 93: { ! 94: register unsigned v = btop(iobase); ! 95: ! 96: do ! 97: *(int *)pte++ = PG_V|PG_KW|v++; ! 98: while (--n > 0); ! 99: mtpr(TBIA, 0); ! 100: } ! 101: ! 102: /* ! 103: * Fixctlrmask fixes the masks of the driver ctlr routines ! 104: * which otherwise save r11 and r12 where the interrupt and br ! 105: * level are passed through. ! 106: */ ! 107: fixctlrmask() ! 108: { ! 109: register struct vba_ctlr *vm; ! 110: register struct vba_device *vi; ! 111: register struct vba_driver *vd; ! 112: #define phys(a,b) ((b)(((int)(a))&~0xc0000000)) ! 113: ! 114: vm = phys(vbminit, struct vba_ctlr *); ! 115: for (; vd = phys(vm->um_driver, struct vba_driver *); vm++) ! 116: *phys(vd->ud_probe, short *) &= ~0x1800; ! 117: vi = phys(vbdinit, struct vba_device *); ! 118: for (; vd = phys(vi->ui_driver, struct vba_driver *); vi++) ! 119: *phys(vd->ud_probe, short *) &= ~0x1800; ! 120: } ! 121: ! 122: /* ! 123: * Find devices on the VERSAbus. ! 124: * Uses per-driver routine to see who is on the bus ! 125: * and then fills in the tables, with help from a per-driver ! 126: * slave initialization routine. ! 127: */ ! 128: vbafind(vban, vumem, memmap) ! 129: int vban; ! 130: caddr_t vumem; ! 131: struct pte memmap[]; ! 132: { ! 133: register int br, cvec; /* must be r12, r11 */ ! 134: register struct vba_device *ui; ! 135: register struct vba_ctlr *um; ! 136: u_short *reg; ! 137: long addr, *ap; ! 138: struct vba_hd *vhp; ! 139: struct vba_driver *udp; ! 140: int i, octlr, (**ivec)(); ! 141: caddr_t valloc; ! 142: extern quad catcher[SCB_LASTIV]; ! 143: ! 144: #ifdef lint ! 145: br = 0; cvec = 0; ! 146: #endif ! 147: vhp = &vba_hd[vban]; ! 148: /* ! 149: * Make the controllers accessible at physical address phys ! 150: * by mapping kernel ptes starting at pte. ! 151: */ ! 152: vbaccess(memmap, (caddr_t)VBIOBASE, (int)VBIOSIZE); ! 153: printf("vba%d at %x\n", vban, VBIOBASE); ! 154: /* ! 155: * Setup scb device entries to point into catcher array. ! 156: */ ! 157: for (i = 0; i < SCB_LASTIV; i++) ! 158: scb.scb_devint[i] = (int (*)())((int)&catcher[i]); ! 159: /* ! 160: * Set last free interrupt vector for devices with ! 161: * programmable interrupt vectors. Use is to decrement ! 162: * this number and use result as interrupt vector. ! 163: */ ! 164: vhp->vh_lastiv = SCB_LASTIV; ! 165: /* ! 166: * Grab some memory to record the address space we allocate, ! 167: * so we can be sure not to place two devices at the same address. ! 168: * Register I/O space is allocated in 256-byte sections, ! 169: * and memory I/O space is in 4Kb sections. We record allocations ! 170: * in 256-byte sections. ! 171: * ! 172: * We could use just 1/8 of this (we only want a 1 bit flag) but ! 173: * we are going to give it back anyway, and that would make the ! 174: * code here bigger (which we can't give back), so ... ! 175: */ ! 176: #define VSECT(a) ((a) / 0x100) ! 177: #define VSIZE(s) (((s) + 0xff) / 0x100) ! 178: #define VALLOC(a) (valloc[VSECT(vboff(a))]) ! 179: #define VMAPSIZE VSIZE(ctob(VBIOSIZE)) ! 180: valloc = (caddr_t)malloc((u_long)(VMAPSIZE), M_TEMP, M_NOWAIT); ! 181: if (valloc == (caddr_t)0) ! 182: panic("no mem for vbafind"); ! 183: bzero(valloc, VMAPSIZE); ! 184: ! 185: /* ! 186: * Check each VERSAbus mass storage controller. ! 187: * For each one which is potentially on this vba, ! 188: * see if it is really there, and if it is record it and ! 189: * then go looking for slaves. ! 190: */ ! 191: #define vbaddr(off) (u_short *)(vumem + vboff(off)) ! 192: for (um = vbminit; udp = um->um_driver; um++) { ! 193: if (um->um_vbanum != vban && um->um_vbanum != '?') ! 194: continue; ! 195: /* ! 196: * Use the particular address specified first, ! 197: * or if it is given as "0", if there is no device ! 198: * at that address, try all the standard addresses ! 199: * in the driver until we find it. ! 200: */ ! 201: addr = (long)um->um_addr; ! 202: for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) { ! 203: if (VBIOMAPPED(addr)) { ! 204: if (VALLOC(addr)) ! 205: continue; ! 206: reg = vbaddr(addr); ! 207: } else ! 208: reg = (u_short *)addr; ! 209: um->um_hd = vhp; ! 210: cvec = SCB_LASTIV, cold &= ~0x2; ! 211: i = (*udp->ud_probe)(reg, um); ! 212: cold |= 0x2; ! 213: if (i == 0) ! 214: continue; ! 215: printf("%s%d at vba%d csr %x ", ! 216: udp->ud_mname, um->um_ctlr, vban, addr); ! 217: if (cvec < 0 && vhp->vh_lastiv == cvec) { ! 218: printf("no space for vector(s)\n"); ! 219: continue; ! 220: } ! 221: if (cvec == SCB_LASTIV) { ! 222: printf("didn't interrupt\n"); ! 223: continue; ! 224: } ! 225: printf("vec %x, ipl %x\n", cvec, br); ! 226: csralloc(valloc, addr, i); ! 227: um->um_alive = 1; ! 228: um->um_vbanum = vban; ! 229: um->um_addr = (caddr_t)reg; ! 230: udp->ud_minfo[um->um_ctlr] = um; ! 231: for (ivec = um->um_intr; *ivec; ivec++) ! 232: ((long *)&scb)[cvec++] = (long)*ivec; ! 233: for (ui = vbdinit; ui->ui_driver; ui++) { ! 234: if (ui->ui_driver != udp || ui->ui_alive || ! 235: ui->ui_ctlr != um->um_ctlr && ui->ui_ctlr != '?' || ! 236: ui->ui_vbanum != vban && ui->ui_vbanum != '?') ! 237: continue; ! 238: octlr = ui->ui_ctlr, ui->ui_ctlr = um->um_ctlr; ! 239: if ((*udp->ud_slave)(ui, reg)) { ! 240: ui->ui_alive = 1; ! 241: ui->ui_ctlr = um->um_ctlr; ! 242: ui->ui_vbanum = vban; ! 243: ui->ui_addr = (caddr_t)reg; ! 244: ui->ui_physaddr = (caddr_t)addr; ! 245: if (ui->ui_dk && dkn < DK_NDRIVE) ! 246: ui->ui_dk = dkn++; ! 247: else ! 248: ui->ui_dk = -1; ! 249: ui->ui_mi = um; ! 250: ui->ui_hd = vhp; ! 251: /* ui_type comes from driver */ ! 252: udp->ud_dinfo[ui->ui_unit] = ui; ! 253: printf("%s%d at %s%d slave %d", ! 254: udp->ud_dname, ui->ui_unit, ! 255: udp->ud_mname, um->um_ctlr, ! 256: ui->ui_slave); ! 257: (*udp->ud_attach)(ui); ! 258: printf("\n"); ! 259: } else ! 260: ui->ui_ctlr = octlr; ! 261: } ! 262: break; ! 263: } ! 264: } ! 265: /* ! 266: * Now look for non-mass storage peripherals. ! 267: */ ! 268: for (ui = vbdinit; udp = ui->ui_driver; ui++) { ! 269: if (ui->ui_vbanum != vban && ui->ui_vbanum != '?' || ! 270: ui->ui_alive || ui->ui_slave != -1) ! 271: continue; ! 272: addr = (long)ui->ui_addr; ! 273: for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) { ! 274: if (VBIOMAPPED(addr)) { ! 275: if (VALLOC(addr)) ! 276: continue; ! 277: reg = vbaddr(addr); ! 278: } else ! 279: reg = (u_short *)addr; ! 280: ui->ui_hd = vhp; ! 281: cvec = SCB_LASTIV, cold &= ~0x2; ! 282: i = (*udp->ud_probe)(reg, ui); ! 283: cold |= 0x2; ! 284: if (i == 0) ! 285: continue; ! 286: printf("%s%d at vba%d csr %x ", ! 287: ui->ui_driver->ud_dname, ui->ui_unit, vban, addr); ! 288: if (ui->ui_intr) { ! 289: if (cvec < 0 && vhp->vh_lastiv == cvec) { ! 290: printf("no space for vector(s)\n"); ! 291: continue; ! 292: } ! 293: if (cvec == SCB_LASTIV) { ! 294: printf("didn't interrupt\n"); ! 295: continue; ! 296: } ! 297: printf("vec %x, ipl %x\n", cvec, br); ! 298: for (ivec = ui->ui_intr; *ivec; ivec++) ! 299: ((long *)&scb)[cvec++] = (long)*ivec; ! 300: } else ! 301: printf("no interrupts\n"); ! 302: csralloc(valloc, addr, i); ! 303: ui->ui_alive = 1; ! 304: ui->ui_vbanum = vban; ! 305: if (VBIOMAPPED(addr)) ! 306: ui->ui_addr = (caddr_t)reg; ! 307: ui->ui_physaddr = (caddr_t)addr; ! 308: ui->ui_dk = -1; ! 309: /* ui_type comes from driver */ ! 310: udp->ud_dinfo[ui->ui_unit] = ui; ! 311: (*udp->ud_attach)(ui); ! 312: break; ! 313: } ! 314: } ! 315: free(valloc, M_TEMP); ! 316: } ! 317: ! 318: /* ! 319: * Mark addresses starting at addr and continuing ! 320: * size bytes as allocated in the map. ! 321: * Warn if the new allocation overlaps a previous allocation. ! 322: */ ! 323: csralloc(valloc, addr, size) ! 324: caddr_t valloc; ! 325: long addr; ! 326: register int size; ! 327: { ! 328: register caddr_t p; ! 329: int warned = 0; ! 330: ! 331: if (!VBIOMAPPED(addr)) ! 332: return; ! 333: size = VSIZE(size); ! 334: p = &VALLOC(addr) + size; ! 335: while (--size >= 0) { ! 336: if (*--p && !warned) { ! 337: printf( ! 338: "WARNING: device registers overlap those for a previous device\n"); ! 339: warned = 1; ! 340: } ! 341: *p = 1; ! 342: } ! 343: } ! 344: ! 345: /* ! 346: * Tahoe VERSAbus adapator support routines. ! 347: */ ! 348: ! 349: caddr_t vbcur = (caddr_t)&vbbase; ! 350: int vbx = 0; ! 351: /* ! 352: * Allocate page tables for mapping intermediate i/o buffers. ! 353: * Called by device drivers during autoconfigure. ! 354: */ ! 355: vbmapalloc(npf, ppte, putl) ! 356: int npf; ! 357: struct pte **ppte; ! 358: caddr_t *putl; ! 359: { ! 360: ! 361: if (vbcur + npf*NBPG > (caddr_t)&vbend) ! 362: return (0); ! 363: *ppte = &VBmap[vbx]; ! 364: *putl = vbcur; ! 365: vbx += npf; ! 366: vbcur += npf*NBPG; ! 367: return (1); ! 368: } ! 369: ! 370: caddr_t vbmcur = (caddr_t)&vmem1; ! 371: int vbmx = 0; ! 372: /* ! 373: * Allocate page tables and map VERSAbus i/o space. ! 374: * Called by device drivers during autoconfigure. ! 375: */ ! 376: vbmemalloc(npf, addr, ppte, putl) ! 377: int npf; ! 378: caddr_t addr; ! 379: struct pte **ppte; ! 380: caddr_t *putl; ! 381: { ! 382: ! 383: if (vbmcur + npf*NBPG > (caddr_t)&vmemend) ! 384: return (0); ! 385: *ppte = &VMEMmap1[vbmx]; ! 386: *putl = vbmcur; ! 387: vbmx += npf; ! 388: vbmcur += npf*NBPG; ! 389: vbaccess(*ppte, addr, npf); /* map i/o space */ ! 390: return (1); ! 391: } ! 392: ! 393: /* ! 394: * Configure swap space and related parameters. ! 395: */ ! 396: swapconf() ! 397: { ! 398: register struct swdevt *swp; ! 399: register int nblks; ! 400: ! 401: for (swp = swdevt; swp->sw_dev; swp++) ! 402: if (bdevsw[major(swp->sw_dev)].d_psize) { ! 403: nblks = ! 404: (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev); ! 405: if (nblks != -1 && ! 406: (swp->sw_nblks == 0 || swp->sw_nblks > nblks)) ! 407: swp->sw_nblks = nblks; ! 408: } ! 409: dumpconf(); ! 410: } ! 411: ! 412: #define DOSWAP /* change swdevt, argdev, and dumpdev too */ ! 413: u_long bootdev; /* should be dev_t, but not until 32 bits */ ! 414: ! 415: static char devname[][2] = { ! 416: 0,0, /* 0 = ud */ ! 417: 'd','k', /* 1 = vd */ ! 418: 0,0, /* 2 = xp */ ! 419: }; ! 420: ! 421: #define PARTITIONMASK 0x7 ! 422: #define PARTITIONSHIFT 3 ! 423: ! 424: /* ! 425: * Attempt to find the device from which we were booted. ! 426: * If we can do so, and not instructed not to do so, ! 427: * change rootdev to correspond to the load device. ! 428: */ ! 429: setroot() ! 430: { ! 431: int majdev, mindev, unit, part, controller, adaptor; ! 432: dev_t temp, orootdev; ! 433: struct swdevt *swp; ! 434: ! 435: if (boothowto & RB_DFLTROOT || ! 436: (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) ! 437: return; ! 438: majdev = B_TYPE(bootdev); ! 439: if (majdev >= sizeof(devname) / sizeof(devname[0])) ! 440: return; ! 441: adaptor = B_ADAPTOR(bootdev); ! 442: controller = B_CONTROLLER(bootdev); ! 443: part = B_PARTITION(bootdev); ! 444: unit = B_UNIT(bootdev); ! 445: /* ! 446: * Search Versabus devices. ! 447: * ! 448: * WILL HAVE TO DISTINGUISH VME/VERSABUS SOMETIME ! 449: */ ! 450: { ! 451: register struct vba_device *vbap; ! 452: ! 453: for (vbap = vbdinit; vbap->ui_driver; vbap++) ! 454: if (vbap->ui_alive && vbap->ui_slave == unit && ! 455: vbap->ui_ctlr == controller && ! 456: vbap->ui_vbanum == adaptor && ! 457: vbap->ui_driver->ud_dname[0] == devname[majdev][0] && ! 458: vbap->ui_driver->ud_dname[1] == devname[majdev][1]) ! 459: break; ! 460: if (vbap->ui_driver == 0) ! 461: return; ! 462: mindev = vbap->ui_unit; ! 463: } ! 464: mindev = (mindev << PARTITIONSHIFT) + part; ! 465: orootdev = rootdev; ! 466: rootdev = makedev(majdev, mindev); ! 467: /* ! 468: * If the original rootdev is the same as the one ! 469: * just calculated, don't need to adjust the swap configuration. ! 470: */ ! 471: if (rootdev == orootdev) ! 472: return; ! 473: printf("changing root device to %c%c%d%c\n", ! 474: devname[majdev][0], devname[majdev][1], ! 475: mindev >> PARTITIONSHIFT, part + 'a'); ! 476: #ifdef DOSWAP ! 477: mindev &= ~PARTITIONMASK; ! 478: for (swp = swdevt; swp->sw_dev; swp++) { ! 479: if (majdev == major(swp->sw_dev) && ! 480: mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) { ! 481: temp = swdevt[0].sw_dev; ! 482: swdevt[0].sw_dev = swp->sw_dev; ! 483: swp->sw_dev = temp; ! 484: break; ! 485: } ! 486: } ! 487: if (swp->sw_dev == 0) ! 488: return; ! 489: /* ! 490: * If argdev and dumpdev were the same as the old primary swap ! 491: * device, move them to the new primary swap device. ! 492: */ ! 493: if (temp == dumpdev) ! 494: dumpdev = swdevt[0].sw_dev; ! 495: if (temp == argdev) ! 496: argdev = swdevt[0].sw_dev; ! 497: #endif ! 498: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.