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