1 /* autoconf.c 4.37 82/05/06 */ 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 if ((mbd->mbd_ds&MBDS_DPR) == 0) 232 continue; 233 dt = mbd->mbd_dt & 0xffff; 234 if (dt == 0) 235 continue; 236 if (dt == MBDT_MOH) 237 continue; 238 fnd.mi_drive = dn; 239 if ((mi = mbaconfig(&fnd, dt)) && (dt & MBDT_TAP)) { 240 for (ms = mbsinit; ms->ms_driver; ms++) 241 if (ms->ms_driver == mi->mi_driver && ms->ms_alive == 0 && 242 (ms->ms_ctlr == mi->mi_unit || ms->ms_ctlr=='?')) { 243 if ((*ms->ms_driver->md_slave)(mi, ms)) { 244 printf("%s%d at %s%d slave %d\n", 245 ms->ms_driver->md_sname, 246 ms->ms_unit, 247 mi->mi_driver->md_dname, 248 mi->mi_unit, 249 ms->ms_slave); 250 ms->ms_alive = 1; 251 ms->ms_ctlr = mi->mi_unit; 252 } 253 } 254 } 255 } 256 mdp->mba_cr = MBCR_INIT; 257 mdp->mba_cr = MBCR_IE; 258 } 259 260 /* 261 * Have found a massbus device; 262 * see if it is in the configuration table. 263 * If so, fill in its data. 264 */ 265 struct mba_device * 266 mbaconfig(ni, type) 267 register struct mba_device *ni; 268 register int type; 269 { 270 register struct mba_device *mi; 271 register short *tp; 272 register struct mba_hd *mh; 273 274 for (mi = mbdinit; mi->mi_driver; mi++) { 275 if (mi->mi_alive) 276 continue; 277 tp = mi->mi_driver->md_type; 278 for (mi->mi_type = 0; *tp; tp++, mi->mi_type++) 279 if (*tp == (type&MBDT_TYPE)) 280 goto found; 281 continue; 282 found: 283 #define match(fld) (ni->fld == mi->fld || mi->fld == '?') 284 if (!match(mi_drive) || !match(mi_mbanum)) 285 continue; 286 printf("%s%d at mba%d drive %d\n", 287 mi->mi_driver->md_dname, mi->mi_unit, 288 ni->mi_mbanum, ni->mi_drive); 289 mi->mi_alive = 1; 290 mh = &mba_hd[ni->mi_mbanum]; 291 mi->mi_hd = mh; 292 mh->mh_mbip[ni->mi_drive] = mi; 293 mh->mh_ndrive++; 294 mi->mi_mba = ni->mi_mba; 295 mi->mi_drv = &mi->mi_mba->mba_drv[ni->mi_drive]; 296 mi->mi_mbanum = ni->mi_mbanum; 297 mi->mi_drive = ni->mi_drive; 298 /* 299 * If drive has never been seen before, 300 * give it a dkn for statistics. 301 */ 302 if (mi->mi_driver->md_info[mi->mi_unit] == 0) { 303 mi->mi_driver->md_info[mi->mi_unit] = mi; 304 if (mi->mi_dk && dkn < DK_NDRIVE) 305 mi->mi_dk = dkn++; 306 else 307 mi->mi_dk = -1; 308 } 309 (*mi->mi_driver->md_attach)(mi); 310 return (mi); 311 } 312 return (0); 313 } 314 #endif 315 316 /* 317 * Fixctlrmask fixes the masks of the driver ctlr routines 318 * which otherwise save r10 and r11 where the interrupt and br 319 * level are passed through. 320 */ 321 fixctlrmask() 322 { 323 register struct uba_ctlr *um; 324 register struct uba_device *ui; 325 register struct uba_driver *ud; 326 #define phys(a,b) ((b)(((int)(a))&0x7fffffff)) 327 328 for (um = ubminit; ud = phys(um->um_driver, struct uba_driver *); um++) 329 *phys(ud->ud_probe, short *) &= ~0xc00; 330 for (ui = ubdinit; ud = phys(ui->ui_driver, struct uba_driver *); ui++) 331 *phys(ud->ud_probe, short *) &= ~0xc00; 332 } 333 334 /* 335 * Find devices on a UNIBUS. 336 * Uses per-driver routine to set <br,cvec> into <r11,r10>, 337 * and then fills in the tables, with help from a per-driver 338 * slave initialization routine. 339 */ 340 unifind(vubp, pubp, vumem, pumem, memmap) 341 struct uba_regs *vubp, *pubp; 342 caddr_t vumem, pumem; 343 struct pte *memmap; 344 { 345 #ifndef lint 346 register int br, cvec; /* MUST BE r11, r10 */ 347 #else 348 /* 349 * Lint doesn't realize that these 350 * can be initialized asynchronously 351 * when devices interrupt. 352 */ 353 register int br = 0, cvec = 0; 354 #endif 355 register struct uba_device *ui; 356 register struct uba_ctlr *um; 357 u_short *reg, addr; 358 struct uba_hd *uhp; 359 struct uba_driver *udp; 360 int i, (**ivec)(), haveubasr = 0; 361 362 /* 363 * Initialize the UNIBUS, by freeing the map 364 * registers and the buffered data path registers 365 */ 366 uhp = &uba_hd[numuba]; 367 uhp->uh_map = (struct map *)calloc(UAMSIZ * sizeof (struct map)); 368 rminit(uhp->uh_map, NUBMREG, 1, "uba", UAMSIZ); 369 switch (cpu) { 370 #if VAX780 371 case VAX_780: 372 uhp->uh_bdpfree = (1<<NBDP780) - 1; 373 haveubasr = 1; 374 break; 375 #endif 376 #if VAX750 377 case VAX_750: 378 uhp->uh_bdpfree = (1<<NBDP750) - 1; 379 break; 380 #endif 381 #if VAX7ZZ 382 case VAX_7ZZ: 383 break; 384 #endif 385 } 386 387 /* 388 * Save virtual and physical addresses 389 * of adaptor, and allocate and initialize 390 * the UNIBUS interrupt vector. 391 */ 392 uhp->uh_uba = vubp; 393 uhp->uh_physuba = pubp; 394 /* HAVE TO DO SOMETHING SPECIAL FOR SECOND UNIBUS ON COMETS HERE */ 395 if (numuba == 0) 396 uhp->uh_vec = UNIvec; 397 else 398 uhp->uh_vec = (int(**)())calloc(512); 399 for (i = 0; i < 128; i++) 400 uhp->uh_vec[i] = 401 scbentry(&catcher[i*2], SCB_ISTACK); 402 /* 403 * Set last free interrupt vector for devices with 404 * programmable interrupt vectors. Use is to decrement 405 * this number and use result as interrupt vector. 406 */ 407 uhp->uh_lastiv = 0x200; 408 409 ubaaccess(pumem, memmap); 410 #if VAX780 411 if (haveubasr) { 412 vubp->uba_sr = vubp->uba_sr; 413 vubp->uba_cr = UBACR_IFS|UBACR_BRIE; 414 } 415 #endif 416 /* 417 * Map the first page of UNIBUS i/o 418 * space to the first page of memory 419 * for devices which will need to dma 420 * output to produce an interrupt. 421 */ 422 *(int *)(&vubp->uba_map[0]) = UBAMR_MRV; 423 424 #define ubaddr(off) (u_short *)((int)vumem + ((off)&0x3ffff)) 425 #define ubdevreg(addr) (addr&0x1fff|0760000) 426 /* 427 * Check each unibus mass storage controller. 428 * For each one which is potentially on this uba, 429 * see if it is really there, and if it is record it and 430 * then go looking for slaves. 431 */ 432 for (um = ubminit; udp = um->um_driver; um++) { 433 if (um->um_ubanum != numuba && um->um_ubanum != '?') 434 continue; 435 addr = (u_short)um->um_addr; 436 reg = ubaddr(addr|0x3e000); 437 if (badaddr((caddr_t)reg, 2)) 438 continue; 439 #if VAX780 440 if (haveubasr && vubp->uba_sr) { 441 vubp->uba_sr = vubp->uba_sr; 442 continue; 443 } 444 #endif 445 cvec = 0x200; 446 i = (*udp->ud_probe)(reg); 447 #if VAX780 448 if (haveubasr && vubp->uba_sr) { 449 vubp->uba_sr = vubp->uba_sr; 450 continue; 451 } 452 #endif 453 if (i == 0) 454 continue; 455 printf("%s%d at uba%d csr %o ", 456 udp->ud_mname, um->um_ctlr, numuba, addr); 457 if (cvec == 0) { 458 printf("zero vector\n"); 459 continue; 460 } 461 if (cvec == 0x200) { 462 printf("didn't interrupt\n"); 463 continue; 464 } 465 printf("vec %o, ipl %x\n", cvec, br); 466 um->um_alive = 1; 467 um->um_ubanum = numuba; 468 um->um_hd = &uba_hd[numuba]; 469 um->um_addr = (caddr_t)reg; 470 udp->ud_minfo[um->um_ctlr] = um; 471 for (ivec = um->um_intr; *ivec; ivec++) { 472 um->um_hd->uh_vec[cvec/4] = 473 scbentry(*ivec, SCB_ISTACK); 474 cvec += 4; 475 } 476 for (ui = ubdinit; ui->ui_driver; ui++) { 477 if (ui->ui_driver != udp || ui->ui_alive || 478 ui->ui_ctlr != um->um_ctlr && ui->ui_ctlr != '?' || 479 ui->ui_ubanum != numuba && ui->ui_ubanum != '?') 480 continue; 481 if ((*udp->ud_slave)(ui, reg)) { 482 ui->ui_alive = 1; 483 ui->ui_ctlr = um->um_ctlr; 484 ui->ui_ubanum = numuba; 485 ui->ui_hd = &uba_hd[numuba]; 486 ui->ui_addr = (caddr_t)reg; 487 ui->ui_physaddr = pumem + ubdevreg(addr); 488 if (ui->ui_dk && dkn < DK_NDRIVE) 489 ui->ui_dk = dkn++; 490 else 491 ui->ui_dk = -1; 492 ui->ui_mi = um; 493 /* ui_type comes from driver */ 494 udp->ud_dinfo[ui->ui_unit] = ui; 495 printf("%s%d at %s%d slave %d\n", 496 udp->ud_dname, ui->ui_unit, 497 udp->ud_mname, um->um_ctlr, ui->ui_slave); 498 (*udp->ud_attach)(ui); 499 } 500 } 501 } 502 /* 503 * Now look for non-mass storage peripherals. 504 */ 505 for (ui = ubdinit; udp = ui->ui_driver; ui++) { 506 if (ui->ui_ubanum != numuba && ui->ui_ubanum != '?' || 507 ui->ui_alive || ui->ui_slave != -1) 508 continue; 509 addr = (u_short)ui->ui_addr; 510 reg = ubaddr(addr|0x3e000); 511 if (badaddr((caddr_t)reg, 2)) 512 continue; 513 #if VAX780 514 if (haveubasr && vubp->uba_sr) { 515 vubp->uba_sr = vubp->uba_sr; 516 continue; 517 } 518 #endif 519 cvec = 0x200; 520 i = (*udp->ud_probe)(reg, um->um_ctlr); 521 #if VAX780 522 if (haveubasr && vubp->uba_sr) { 523 vubp->uba_sr = vubp->uba_sr; 524 continue; 525 } 526 #endif 527 if (i == 0) 528 continue; 529 printf("%s%d at uba%d csr %o ", 530 ui->ui_driver->ud_dname, ui->ui_unit, numuba, addr); 531 if (cvec == 0) { 532 printf("zero vector\n"); 533 continue; 534 } 535 if (cvec == 0x200) { 536 printf("didn't interrupt\n"); 537 continue; 538 } 539 printf("vec %o, ipl %x\n", cvec, br); 540 ui->ui_hd = &uba_hd[numuba]; 541 for (ivec = ui->ui_intr; *ivec; ivec++) { 542 ui->ui_hd->uh_vec[cvec/4] = 543 scbentry(*ivec, SCB_ISTACK); 544 cvec += 4; 545 } 546 ui->ui_alive = 1; 547 ui->ui_ubanum = numuba; 548 ui->ui_addr = (caddr_t)reg; 549 ui->ui_physaddr = pumem + ubdevreg(addr); 550 ui->ui_dk = -1; 551 /* ui_type comes from driver */ 552 udp->ud_dinfo[ui->ui_unit] = ui; 553 (*udp->ud_attach)(ui); 554 } 555 } 556 557 setscbnex(fn) 558 int (*fn)(); 559 { 560 register struct scb *scbp = &scb; 561 562 scbp->scb_ipl14[nexnum] = scbp->scb_ipl15[nexnum] = 563 scbp->scb_ipl16[nexnum] = scbp->scb_ipl17[nexnum] = 564 scbentry(fn, SCB_ISTACK); 565 } 566 567 /* 568 * Make a nexus accessible at physical address phys 569 * by mapping kernel ptes starting at pte. 570 * 571 * WE LEAVE ALL NEXI MAPPED; THIS IS PERHAPS UNWISE 572 * SINCE MISSING NEXI DONT RESPOND. BUT THEN AGAIN 573 * PRESENT NEXI DONT RESPOND TO ALL OF THEIR ADDRESS SPACE. 574 */ 575 nxaccess(physa, pte) 576 struct nexus *physa; 577 register struct pte *pte; 578 { 579 register int i = btop(sizeof (struct nexus)); 580 register unsigned v = btop(physa); 581 582 do 583 *(int *)pte++ = PG_V|PG_KW|v++; 584 while (--i > 0); 585 mtpr(TBIA, 0); 586 } 587 588 ubaaccess(pumem, pte) 589 caddr_t pumem; 590 register struct pte *pte; 591 { 592 register int i = 512; 593 register unsigned v = btop(pumem); 594 595 do 596 *(int *)pte++ = PG_V|PG_KW|v++; 597 while (--i > 0); 598 mtpr(TBIA, 0); 599 } 600