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.1 (Berkeley) 05/26/88 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 ui->ui_addr = (caddr_t)reg; 306 ui->ui_physaddr = (caddr_t)addr; 307 ui->ui_dk = -1; 308 /* ui_type comes from driver */ 309 udp->ud_dinfo[ui->ui_unit] = ui; 310 (*udp->ud_attach)(ui); 311 break; 312 } 313 } 314 free(valloc, M_TEMP); 315 } 316 317 /* 318 * Mark addresses starting at addr and continuing 319 * size bytes as allocated in the map. 320 * Warn if the new allocation overlaps a previous allocation. 321 */ 322 csralloc(valloc, addr, size) 323 caddr_t valloc; 324 long addr; 325 register int size; 326 { 327 register caddr_t p; 328 int warned = 0; 329 330 if (!VBIOMAPPED(addr)) 331 return; 332 size = VSIZE(size); 333 p = &VALLOC(addr) + size; 334 while (--size >= 0) { 335 if (*--p && !warned) { 336 printf( 337 "WARNING: device registers overlap those for a previous device\n"); 338 warned = 1; 339 } 340 *p = 1; 341 } 342 } 343 344 /* 345 * Tahoe VERSAbus adapator support routines. 346 */ 347 348 caddr_t vbcur = (caddr_t)&vbbase; 349 int vbx = 0; 350 /* 351 * Allocate page tables for mapping intermediate i/o buffers. 352 * Called by device drivers during autoconfigure. 353 */ 354 vbmapalloc(npf, ppte, putl) 355 int npf; 356 struct pte **ppte; 357 caddr_t *putl; 358 { 359 360 if (vbcur + npf*NBPG > (caddr_t)&vbend) 361 return (0); 362 *ppte = &VBmap[vbx]; 363 *putl = vbcur; 364 vbx += npf; 365 vbcur += npf*NBPG; 366 return (1); 367 } 368 369 caddr_t vbmcur = (caddr_t)&vmem1; 370 int vbmx = 0; 371 /* 372 * Allocate page tables and map VERSAbus i/o space. 373 * Called by device drivers during autoconfigure. 374 */ 375 vbmemalloc(npf, addr, ppte, putl) 376 int npf; 377 caddr_t addr; 378 struct pte **ppte; 379 caddr_t *putl; 380 { 381 382 if (vbmcur + npf*NBPG > (caddr_t)&vmemend) 383 return (0); 384 *ppte = &VMEMmap1[vbmx]; 385 *putl = vbmcur; 386 vbmx += npf; 387 vbmcur += npf*NBPG; 388 vbaccess(*ppte, addr, npf); /* map i/o space */ 389 return (1); 390 } 391 392 /* 393 * Configure swap space and related parameters. 394 */ 395 swapconf() 396 { 397 register struct swdevt *swp; 398 register int nblks; 399 400 for (swp = swdevt; swp->sw_dev; swp++) 401 if (bdevsw[major(swp->sw_dev)].d_psize) { 402 nblks = 403 (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev); 404 if (nblks != -1 && 405 (swp->sw_nblks == 0 || swp->sw_nblks > nblks)) 406 swp->sw_nblks = nblks; 407 } 408 if (dumplo == 0 && bdevsw[major(dumpdev)].d_psize) 409 dumplo = (*bdevsw[major(dumpdev)].d_psize)(dumpdev) - physmem; 410 if (dumplo < 0) 411 dumplo = 0; 412 } 413 414 #define DOSWAP /* change swdevt, argdev, and dumpdev too */ 415 u_long bootdev; /* should be dev_t, but not until 32 bits */ 416 417 static char devname[][2] = { 418 0,0, /* 0 = ud */ 419 'd','k', /* 1 = vd */ 420 0,0, /* 2 = xp */ 421 }; 422 423 #define PARTITIONMASK 0x7 424 #define PARTITIONSHIFT 3 425 426 /* 427 * Attempt to find the device from which we were booted. 428 * If we can do so, and not instructed not to do so, 429 * change rootdev to correspond to the load device. 430 */ 431 setroot() 432 { 433 int majdev, mindev, unit, part, controller, adaptor; 434 dev_t temp, orootdev; 435 struct swdevt *swp; 436 437 if (boothowto & RB_DFLTROOT || 438 (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) 439 return; 440 majdev = B_TYPE(bootdev); 441 if (majdev >= sizeof(devname) / sizeof(devname[0])) 442 return; 443 adaptor = B_ADAPTOR(bootdev); 444 controller = B_CONTROLLER(bootdev); 445 part = B_PARTITION(bootdev); 446 unit = B_UNIT(bootdev); 447 /* 448 * Search Versabus devices. 449 * 450 * WILL HAVE TO DISTINGUISH VME/VERSABUS SOMETIME 451 */ 452 { 453 register struct vba_device *vbap; 454 455 for (vbap = vbdinit; vbap->ui_driver; vbap++) 456 if (vbap->ui_alive && vbap->ui_slave == unit && 457 vbap->ui_ctlr == controller && 458 vbap->ui_vbanum == adaptor && 459 vbap->ui_driver->ud_dname[0] == devname[majdev][0] && 460 vbap->ui_driver->ud_dname[1] == devname[majdev][1]) 461 break; 462 if (vbap->ui_driver == 0) 463 return; 464 mindev = vbap->ui_unit; 465 } 466 mindev = (mindev << PARTITIONSHIFT) + part; 467 orootdev = rootdev; 468 rootdev = makedev(majdev, mindev); 469 /* 470 * If the original rootdev is the same as the one 471 * just calculated, don't need to adjust the swap configuration. 472 */ 473 if (rootdev == orootdev) 474 return; 475 printf("changing root device to %c%c%d%c\n", 476 devname[majdev][0], devname[majdev][1], 477 mindev >> PARTITIONSHIFT, part + 'a'); 478 #ifdef DOSWAP 479 mindev &= ~PARTITIONMASK; 480 for (swp = swdevt; swp->sw_dev; swp++) { 481 if (majdev == major(swp->sw_dev) && 482 mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) { 483 temp = swdevt[0].sw_dev; 484 swdevt[0].sw_dev = swp->sw_dev; 485 swp->sw_dev = temp; 486 break; 487 } 488 } 489 if (swp->sw_dev == 0) 490 return; 491 /* 492 * If argdev and dumpdev were the same as the old primary swap 493 * device, move them to the new primary swap device. 494 */ 495 if (temp == dumpdev) 496 dumpdev = swdevt[0].sw_dev; 497 if (temp == argdev) 498 argdev = swdevt[0].sw_dev; 499 #endif 500 } 501