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.15 (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 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 #include "kra.h" /* XXX wrong file */ 21 22 #include "param.h" 23 #include "systm.h" 24 #include "map.h" 25 #include "buf.h" 26 #include "dkstat.h" 27 #include "vm.h" 28 #include "malloc.h" 29 #include "conf.h" 30 #include "dmap.h" 31 #include "reboot.h" 32 33 #include "pte.h" 34 #include "cpu.h" 35 #include "mem.h" 36 #include "mtpr.h" 37 #include "nexus.h" 38 #include "scb.h" 39 #include "ioa.h" 40 #include "../vaxbi/bireg.h" 41 #include "../vaxmba/mbareg.h" 42 #include "../vaxmba/mbavar.h" 43 #include "../vaxuba/ubareg.h" 44 #include "../vaxuba/ubavar.h" 45 46 /* 47 * The following several variables are related to 48 * the configuration process, and are used in initializing 49 * the machine. 50 */ 51 int cold; /* if 1, still working on cold-start */ 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 * RIDICULOUS! CONFIG SHOULD GENERATE AN ioconf.h FOR US, with 61 * mba glue also in `glue.s'. (Unibus adapter glue is special, though.) 62 */ 63 #if NMBA > 0 64 int (*mbaintv[4])() = { Xmba0int, Xmba1int, Xmba2int, Xmba3int }; 65 #if NMBA > 4 66 Need to expand the table for more than 4 massbus adaptors 67 #endif 68 #endif 69 #if defined(VAX780) || defined(VAX8600) 70 int (*ubaintv[])() = 71 { 72 Xua0int, Xua1int, Xua2int, Xua3int, 73 #if NUBA > 4 74 Xua4int, Xua5int, Xua6int, Xua7int, 75 #endif 76 #if NUBA > 8 77 Need to expand the table for more than 8 unibus adaptors 78 #endif 79 }; 80 #endif 81 #if NKDB > 0 82 /* kdb50 driver does not appear in udminit[] (not without csr!) */ 83 int Xkdbintr0(); /* generated by autoconf */ 84 int (*kdbintv[])() = { Xkdbintr0 }; 85 #if NKDB > 1 86 Need to expand the table for more than 1 KDB adapter 87 #endif 88 #endif 89 90 /* 91 * This allocates the space for the per-uba information, 92 * such as buffered data path usage. 93 */ 94 struct uba_hd uba_hd[NUBA]; 95 96 /* 97 * Determine mass storage and memory configuration for a machine. 98 * Get cpu type, and then switch out to machine specific procedures 99 * which will probe adaptors to see what is out there. 100 */ 101 configure() 102 { 103 union cpusid cpusid; 104 register struct percpu *ocp; 105 register struct pte *ip; 106 107 cpusid.cpusid = mfpr(SID); 108 switch (cpusid.cpuany.cp_type) { 109 #if VAX8600 110 case VAX_8600: 111 printf("VAX 8600, serial# %d(%d), hardware ECO level %d(%d)\n", 112 cpusid.cpu780.cp_sno, cpusid.cpu780.cp_plant, 113 cpusid.cpu780.cp_eco >> 4, cpusid.cpu780.cp_eco); 114 break; 115 #endif 116 #if VAX8200 117 case VAX_8200: 118 printf("\ 119 VAX 82%c0, hardware rev %d, ucode patch rev %d, sec patch %d, ucode rev %d\n", 120 cpusid.cpu8200.cp_5 ? '5' : '0', 121 cpusid.cpu8200.cp_hrev, cpusid.cpu8200.cp_patch, 122 cpusid.cpu8200.cp_secp, cpusid.cpu8200.cp_urev); 123 mastercpu = mfpr(BINID); 124 break; 125 #endif 126 #if VAX780 127 case VAX_780: 128 printf("\ 129 VAX 11/78%c, serial# %d(%d), hardware ECO level %d(%d)\n", 130 cpusid.cpu780.cp_5 ? '5' : '0', 131 cpusid.cpu780.cp_sno, cpusid.cpu780.cp_plant, 132 cpusid.cpu780.cp_eco >> 4, cpusid.cpu780.cp_eco); 133 break; 134 #endif 135 #if VAX750 136 case VAX_750: 137 printf("VAX 11/750, hardware rev %d, ucode rev %d\n", 138 cpusid.cpu750.cp_hrev, cpusid.cpu750.cp_urev); 139 break; 140 #endif 141 #if VAX730 142 case VAX_730: 143 printf("VAX 11/730, ucode rev %d\n", cpusid.cpu730.cp_urev); 144 break; 145 #endif 146 #if VAX630 147 case VAX_630: 148 printf("MicroVAX-II\n"); 149 break; 150 #endif 151 } 152 for (ocp = percpu; ocp->pc_cputype; ocp++) 153 if (ocp->pc_cputype == cpusid.cpuany.cp_type) { 154 cpuspeed = ocp->pc_cpuspeed; 155 cpuops = ocp->pc_ops; 156 if (cpuops->cpu_init != NULL) 157 (*cpuops->cpu_init)(); 158 probeio(ocp); 159 /* 160 * Write protect the scb and UNIBUS interrupt vectors. 161 * It is strange that this code is here, but this is 162 * as soon as we are done mucking with it, and the 163 * write-enable was done in assembly language 164 * to which we will never return. 165 */ 166 for (ip = kvtopte(scb); ip < kvtopte(eUNIvec); ip++) { 167 *(int *)ip &= ~PG_PROT; 168 *(int *)ip |= PG_KR; 169 } 170 mtpr(TBIA, 0); 171 #if GENERIC 172 if ((boothowto & RB_ASKNAME) == 0) 173 setroot(); 174 setconf(); 175 #else 176 setroot(); 177 #endif 178 /* 179 * Configure swap area and related system 180 * parameter based on device(s) used. 181 */ 182 swapconf(); 183 cold = 0; 184 memenable(); 185 return; 186 } 187 printf("cpu type %d not configured\n", cpusid.cpuany.cp_type); 188 asm("halt"); 189 } 190 191 #if VAX8600 || VAX780 || VAX750 || VAX730 192 int nexnum; /* current nexus number */ 193 int nsbi; /* current sbi number */ 194 #endif 195 #if VAX8200 196 int numkdb; /* current ``kdb'' number */ 197 int bi_nodes; /* XXX remembers found bi nodes */ 198 #endif 199 200 /* 201 * Probe the main IO bus(es). 202 * The percpu structure gives us a handle on the addresses and/or types. 203 */ 204 probeio(pcpu) 205 register struct percpu *pcpu; 206 { 207 register struct iobus *iob; 208 int ioanum; 209 210 ioanum = 0; 211 for (iob = pcpu->pc_io; ioanum < pcpu->pc_nioa; ioanum++, iob++) { 212 213 switch (iob->io_type) { 214 215 #if VAX630 216 case IO_QBUS: 217 probeqbus((struct qbus *)iob->io_details); 218 break; 219 #endif 220 221 #if VAX780 || VAX750 || VAX730 222 case IO_SBI780: 223 case IO_CMI750: 224 case IO_XXX730: 225 probenexi((struct nexusconnect *)iob->io_details); 226 break; 227 #endif 228 229 #if VAX8600 230 case IO_ABUS: 231 probe_Abus(ioanum, iob); 232 break; 233 #endif 234 235 #if VAX8200 236 case IO_BI: 237 probe_bi((struct bibus *)iob->io_details); 238 break; 239 #endif 240 241 default: 242 if (iob->io_addr) { 243 printf( 244 "IO adaptor %d, type %d, at address 0x%x is unsupported\n", 245 ioanum, iob->io_type, iob->io_addr); 246 } else 247 printf("IO adaptor %d, type %d, is unsupported\n", 248 ioanum, iob->io_type); 249 break; 250 } 251 } 252 } 253 254 #if VAX8600 255 probe_Abus(ioanum, iob) 256 register struct iobus *iob; 257 { 258 register struct ioa *ioap; 259 union ioacsr ioacsr; 260 int type; 261 struct sbia_regs *sbiaregs; 262 #ifdef notyet 263 int sbi1fail(), sbi1alert(), sbi1fault(), sbi1err(); 264 #endif 265 266 ioap = &ioa[ioanum]; 267 ioaccess(iob->io_addr, Ioamap[ioanum], iob->io_size); 268 if (badaddr((caddr_t)ioap, 4)) 269 return; 270 ioacsr.ioa_csr = ioap->ioacsr.ioa_csr; 271 type = ioacsr.ioa_type & IOA_TYPMSK; 272 273 switch (type) { 274 275 case IOA_SBIA: 276 printf("SBIA%d at IO adaptor %d address 0x%x\n", 277 nsbi, ioanum, iob->io_addr); 278 #ifdef notyet 279 /* I AM NOT SURE THESE ARE IN THE SAME PLACES */ 280 if (nscb == 1) { 281 scb[1].scb_sbifail = scbentry(sbi1fail, SCB_ISTACK); 282 /* maybe not sbifail, maybe scb1.scb_cmrd */ 283 /* but how can I find out without a broken SBIA1? */ 284 scb[1].scb_sbialert = scbentry(sbi1alert, SCB_ISTACK); 285 scb[1].scb_sbifault = scbentry(sbi1fault, SCB_ISTACK); 286 scb[1].scb_sbierr = scbentry(sbi1err, SCB_ISTACK); 287 } 288 #endif 289 probenexi((struct nexusconnect *)iob->io_details); 290 nsbi++; 291 sbiaregs = (struct sbia_regs *)ioap; 292 sbiaregs->sbi_errsum = -1; 293 sbiaregs->sbi_error = 0x1000; 294 sbiaregs->sbi_fltsts = 0xc0000; 295 break; 296 297 default: 298 printf("IOA%d at address 0x%x is unsupported (type = 0x%x)\n", 299 ioanum, iob->io_addr, ioacsr.ioa_type); 300 break; 301 } 302 } 303 #endif 304 305 #if VAX8600 || VAX780 || VAX750 || VAX730 306 /* 307 * Probe nexus space, finding the interconnects 308 * and setting up and probing mba's and uba's for devices. 309 */ 310 probenexi(pnc) 311 register struct nexusconnect *pnc; 312 { 313 register struct nexus *nxv; 314 struct nexus *nxp = pnc->psb_nexbase; 315 union nexcsr nexcsr; 316 int i; 317 318 ioaccess((caddr_t)nxp, Nexmap[nsbi * NNEXSBI], 319 pnc->psb_nnexus * sizeof(struct nexus)); 320 nxv = &nexus[nsbi * NNEXSBI]; 321 for (nexnum = 0; nexnum < pnc->psb_nnexus; nexnum++, nxp++, nxv++) { 322 if (badaddr((caddr_t)nxv, 4)) 323 continue; 324 if (pnc->psb_nextype && pnc->psb_nextype[nexnum] != NEX_ANY) 325 nexcsr.nex_csr = pnc->psb_nextype[nexnum]; 326 else 327 nexcsr = nxv->nexcsr; 328 if (nexcsr.nex_csr&NEX_APD) 329 continue; 330 switch (nexcsr.nex_type) { 331 332 case NEX_MBA: 333 printf("mba%d at tr%d\n", nummba, nexnum); 334 if (nummba >= NMBA) { 335 printf("%d mba's", ++nummba); 336 goto unconfig; 337 } 338 #if NMBA > 0 339 mbafind(nxv, nxp); 340 nummba++; 341 #endif 342 break; 343 344 case NEX_UBA0: 345 case NEX_UBA1: 346 case NEX_UBA2: 347 case NEX_UBA3: 348 printf("uba%d at tr%d\n", numuba, nexnum); 349 if (numuba >= NUBA) { 350 printf("%d uba's", ++numuba); 351 goto unconfig; 352 } 353 #if NUBA > 0 354 #if VAX750 355 if (numuba >= 2 && cpu == VAX_750) { 356 printf("More than 2 UBA's"); 357 goto unsupp; 358 } 359 #endif 360 #if defined(VAX780) || defined(VAX8600) 361 if (cpu == VAX_780 || cpu == VAX_8600) 362 setscbnex(ubaintv[numuba]); 363 #endif 364 i = nexcsr.nex_type - NEX_UBA0; 365 probeuba((struct uba_regs *)nxv, (struct uba_regs *)nxp, 366 pnc->psb_umaddr[i]); 367 #endif /* NUBA */ 368 break; 369 370 case NEX_DR32: 371 /* there can be more than one... are there other codes??? */ 372 printf("dr32"); 373 goto unsupp; 374 375 case NEX_MEM4: 376 case NEX_MEM4I: 377 case NEX_MEM16: 378 case NEX_MEM16I: 379 printf("mcr%d at tr%d\n", nmcr, nexnum); 380 if (nmcr >= MAXNMCR) { 381 printf("%d mcr's", ++nmcr); 382 goto unconfig; 383 } 384 switch (cpu) { 385 #if VAX780 386 case VAX_780: 387 /* only ka780 code looks at type */ 388 mcrtype[nmcr] = M780C; 389 break; 390 #endif 391 default: 392 break; 393 } 394 mcraddr[nmcr++] = (caddr_t)nxv; 395 break; 396 397 #if VAX780 398 case NEX_MEM64I: 399 case NEX_MEM64L: 400 case NEX_MEM64LI: 401 case NEX_MEM256I: 402 case NEX_MEM256L: 403 case NEX_MEM256LI: 404 printf("mcr%d (el) at tr%d\n", nmcr, nexnum); 405 if (nmcr >= MAXNMCR) { 406 printf("%d mcr's", ++nmcr); 407 goto unconfig; 408 } 409 mcrtype[nmcr] = M780EL; 410 mcraddr[nmcr++] = (caddr_t)nxv; 411 if (nexcsr.nex_type != NEX_MEM64I && 412 nexcsr.nex_type != NEX_MEM256I) 413 break; 414 /* fall into ... */ 415 416 case NEX_MEM64U: 417 case NEX_MEM64UI: 418 case NEX_MEM256U: 419 case NEX_MEM256UI: 420 printf("mcr%d (eu) at tr%d\n", nmcr, nexnum); 421 if (nmcr >= MAXNMCR) { 422 printf("%d mcr's", ++nmcr); 423 goto unconfig; 424 } 425 mcrtype[nmcr] = M780EU; 426 mcraddr[nmcr++] = (caddr_t)nxv; 427 break; 428 #endif 429 430 case NEX_MPM0: 431 case NEX_MPM1: 432 case NEX_MPM2: 433 case NEX_MPM3: 434 printf("mpm"); 435 goto unsupp; 436 437 case NEX_CI: 438 printf("ci"); 439 goto unsupp; 440 441 default: 442 printf("nexus type %x", nexcsr.nex_type); 443 unsupp: 444 printf(" unsupported (at tr %d)\n", nexnum); 445 continue; 446 unconfig: 447 printf(" not configured\n"); 448 continue; 449 } 450 } 451 if (nummba > NMBA) 452 nummba = NMBA; 453 if (numuba > NUBA) 454 numuba = NUBA; 455 if (nmcr > MAXNMCR) 456 nmcr = MAXNMCR; 457 } 458 459 setscbnex(fn) 460 int (*fn)(); 461 { 462 register struct scb *scbp = &scb[nsbi]; 463 464 scbp->scb_ipl14[nexnum] = scbp->scb_ipl15[nexnum] = 465 scbp->scb_ipl16[nexnum] = scbp->scb_ipl17[nexnum] = 466 scbentry(fn, SCB_ISTACK); 467 } 468 #endif 469 470 #include "bi.h" 471 #if NBI > 0 472 /* 473 * Probe BI node space. 474 * 475 * THIS DEPENDS ON BI SPACE == NEXUS SPACE 476 * THIS WILL NOT WORK FOR MULTIPLE BIs 477 */ 478 probe_bi(p) 479 register struct bibus *p; 480 { 481 register struct bi_node *biv, *bip; 482 register int node; 483 short dtype; 484 485 /* must ignore BI errors while configuring */ 486 bip = p->pbi_base; 487 ioaccess((caddr_t)bip, Nexmap[0], sizeof(*bip) * NNODEBI);/* XXX */ 488 printf("vaxbi0 at address 0x%x\n", bip); 489 biv = (struct bi_node *) &nexus[0]; /* XXX */ 490 for (node = 0; node < NNODEBI; node++, bip++, biv++) { 491 if (badaddr((caddr_t)biv, 4)) 492 continue; 493 bi_nodes |= 1 << node; /* XXX */ 494 dtype = biv->biic.bi_dtype; 495 /* clear bus errors */ 496 biv->biic.bi_ber = ~(BIBER_MBZ|BIBER_NMR|BIBER_UPEN); 497 switch (dtype) { 498 499 case BIDT_KA820: { 500 /* is this right?? */ 501 int cp5 = biv->biic.bi_revs & 0x8000 ? '5' : '0'; 502 503 if (node != mastercpu) { 504 printf("slave ka82%c cpu", cp5); 505 goto unsupp; 506 } 507 printf("ka82%c cpu at node %x\n", cp5, node); 508 biv->biic.bi_intrdes = 1 << mastercpu; 509 biv->biic.bi_csr |= BICSR_SEIE | BICSR_HEIE; 510 break; 511 } 512 513 case BIDT_DWBUA: 514 if (numuba >= NUBA || /*XXX*/numuba > 2) { 515 printf("%d uba's", ++numuba); 516 goto unconfig; 517 } 518 #if NUBA > 0 519 printf("uba%d at node %x\n", numuba, node); 520 521 /* 522 * Run a self test reset to drop any `old' errors, 523 * so that they cannot cause a BI bus error. 524 */ 525 (void) bi_selftest(&biv->biic); 526 527 /* 528 * Enable interrupts. DWBUAs must have 529 * high priority. 530 */ 531 biv->biic.bi_intrdes = 1 << mastercpu; 532 biv->biic.bi_csr = (biv->biic.bi_csr&~BICSR_ARB_MASK) | 533 BICSR_ARB_HIGH; 534 probeuba((struct uba_regs *)biv, (struct uba_regs *)bip, 535 (caddr_t)UMEM8200(node)); 536 #endif /* NUBA */ 537 break; 538 539 case BIDT_MS820: 540 printf("mcr%d at node %x\n", nmcr, node); 541 if (nmcr >= MAXNMCR) { 542 printf("%d mcr's", ++nmcr); 543 goto unconfig; 544 } 545 mcraddr[nmcr++] = (caddr_t)biv; 546 biv->biic.bi_intrdes = 1 << mastercpu; 547 biv->biic.bi_csr |= BICSR_SEIE | BICSR_HEIE; 548 break; 549 550 case BIDT_KDB50: 551 if (numkdb >= NKDB) { 552 printf("%d kdb's", ++numkdb); 553 goto unconfig; 554 } 555 #if NKDB > 0 556 printf("kdb%d at node %x\n", numkdb, node); 557 kdbconfig(numkdb, (struct biiregs *)biv, 558 (struct biiregs *)bip, 559 (int)&scb[0].scb_ipl15[node] - (int)&scb[0]); 560 scb[0].scb_ipl15[node] = 561 scbentry(kdbintv[numkdb], SCB_ISTACK); 562 kdbfind(numkdb); 563 #endif 564 numkdb++; 565 break; 566 567 case BIDT_DEBNA: 568 case BIDT_DEBNK: 569 printf("debna/debnk ethernet"); 570 goto unsupp; 571 572 default: 573 printf("node type 0x%x ", dtype); 574 unsupp: 575 printf(" unsupported (at node %x)\n", node); 576 break; 577 unconfig: 578 printf(" not configured (at node %x)\n", node); 579 continue; 580 } 581 #ifdef DO_EINTRCSR 582 biv->biic.bi_eintrcsr = BIEIC_IPL17 | 583 (int)&scb[0].scb_bierr - (int)&scb[0]; 584 /* but bi reset will need to restore this */ 585 #endif 586 } 587 if (numuba > NUBA) 588 numuba = NUBA; 589 if (numkdb > NKDB) 590 numkdb = NKDB; 591 if (nmcr > MAXNMCR) 592 nmcr = MAXNMCR; 593 } 594 595 #if NKDB > 0 596 /* 597 * Find drives attached to a particular KDB50. 598 */ 599 kdbfind(kdbnum) 600 int kdbnum; 601 { 602 extern struct uba_driver kdbdriver; 603 register struct uba_device *ui; 604 register struct uba_driver *udp = &kdbdriver; 605 int t; 606 607 for (ui = ubdinit; ui->ui_driver; ui++) { 608 /* ui->ui_ubanum is trash */ 609 if (ui->ui_driver != udp || ui->ui_alive || 610 ui->ui_ctlr != kdbnum && ui->ui_ctlr != '?') 611 continue; 612 t = ui->ui_ctlr; 613 ui->ui_ctlr = kdbnum; 614 if ((*udp->ud_slave)(ui) == 0) { 615 ui->ui_ctlr = t; 616 continue; 617 } 618 ui->ui_alive = 1; 619 ui->ui_ubanum = -1; 620 621 /* make these invalid so we can see if someone uses them */ 622 /* might as well make each one different too */ 623 ui->ui_hd = (struct uba_hd *)0xc0000010; 624 ui->ui_addr = (caddr_t)0xc0000014; 625 ui->ui_physaddr = (caddr_t)0xc0000018; 626 ui->ui_mi = (struct uba_ctlr *)0xc000001c; 627 628 if (ui->ui_dk && dkn < DK_NDRIVE) 629 ui->ui_dk = dkn++; 630 else 631 ui->ui_dk = -1; 632 /* ui_type comes from driver */ 633 udp->ud_dinfo[ui->ui_unit] = ui; 634 printf("%s%d at %s%d slave %d\n", 635 udp->ud_dname, ui->ui_unit, 636 udp->ud_mname, ui->ui_ctlr, ui->ui_slave); 637 (*udp->ud_attach)(ui); 638 } 639 } 640 #endif /* NKDB > 0 */ 641 #endif /* NBI > 0 */ 642 643 #if NMBA > 0 644 struct mba_device *mbaconfig(); 645 /* 646 * Find devices attached to a particular mba 647 * and look for each device found in the massbus 648 * initialization tables. 649 */ 650 mbafind(nxv, nxp) 651 struct nexus *nxv, *nxp; 652 { 653 register struct mba_regs *mdp; 654 register struct mba_drv *mbd; 655 register struct mba_device *mi; 656 register struct mba_slave *ms; 657 int dn, dt, sn; 658 struct mba_device fnd; 659 660 mdp = (struct mba_regs *)nxv; 661 mba_hd[nummba].mh_mba = mdp; 662 mba_hd[nummba].mh_physmba = (struct mba_regs *)nxp; 663 setscbnex(mbaintv[nummba]); 664 mdp->mba_cr = MBCR_INIT; 665 mdp->mba_cr = MBCR_IE; 666 fnd.mi_mba = mdp; 667 fnd.mi_mbanum = nummba; 668 for (mbd = mdp->mba_drv, dn = 0; mbd < &mdp->mba_drv[8]; mbd++, dn++) { 669 if ((mbd->mbd_ds&MBDS_DPR) == 0) 670 continue; 671 mdp->mba_sr |= MBSR_NED; /* si kludge */ 672 dt = mbd->mbd_dt & 0xffff; 673 if (dt == 0) 674 continue; 675 if (mdp->mba_sr&MBSR_NED) 676 continue; /* si kludge */ 677 if (dt == MBDT_MOH) 678 continue; 679 fnd.mi_drive = dn; 680 #define qeq(a, b) ( a == b || a == '?' ) 681 if ((mi = mbaconfig(&fnd, dt)) && (dt & MBDT_TAP)) 682 for (sn = 0; sn < 8; sn++) { 683 mbd->mbd_tc = sn; 684 for (ms = mbsinit; ms->ms_driver; ms++) 685 if (ms->ms_driver == mi->mi_driver && 686 ms->ms_alive == 0 && 687 qeq(ms->ms_ctlr, mi->mi_unit) && 688 qeq(ms->ms_slave, sn) && 689 (*ms->ms_driver->md_slave)(mi, ms, sn)) { 690 printf("%s%d at %s%d slave %d\n" 691 , ms->ms_driver->md_sname 692 , ms->ms_unit 693 , mi->mi_driver->md_dname 694 , mi->mi_unit 695 , sn 696 ); 697 ms->ms_alive = 1; 698 ms->ms_ctlr = mi->mi_unit; 699 ms->ms_slave = sn; 700 break; 701 } 702 } 703 } 704 } 705 706 /* 707 * Have found a massbus device; 708 * see if it is in the configuration table. 709 * If so, fill in its data. 710 */ 711 struct mba_device * 712 mbaconfig(ni, type) 713 register struct mba_device *ni; 714 register int type; 715 { 716 register struct mba_device *mi; 717 register short *tp; 718 register struct mba_hd *mh; 719 720 for (mi = mbdinit; mi->mi_driver; mi++) { 721 if (mi->mi_alive) 722 continue; 723 tp = mi->mi_driver->md_type; 724 for (mi->mi_type = 0; *tp; tp++, mi->mi_type++) 725 if (*tp == (type&MBDT_TYPE)) 726 goto found; 727 continue; 728 found: 729 #define match(fld) (ni->fld == mi->fld || mi->fld == '?') 730 if (!match(mi_drive) || !match(mi_mbanum)) 731 continue; 732 printf("%s%d at mba%d drive %d", 733 mi->mi_driver->md_dname, mi->mi_unit, 734 ni->mi_mbanum, ni->mi_drive); 735 mi->mi_alive = 1; 736 mh = &mba_hd[ni->mi_mbanum]; 737 mi->mi_hd = mh; 738 mh->mh_mbip[ni->mi_drive] = mi; 739 mh->mh_ndrive++; 740 mi->mi_mba = ni->mi_mba; 741 mi->mi_drv = &mi->mi_mba->mba_drv[ni->mi_drive]; 742 mi->mi_mbanum = ni->mi_mbanum; 743 mi->mi_drive = ni->mi_drive; 744 /* 745 * If drive has never been seen before, 746 * give it a dkn for statistics. 747 */ 748 if (mi->mi_driver->md_info[mi->mi_unit] == 0) { 749 mi->mi_driver->md_info[mi->mi_unit] = mi; 750 if (mi->mi_dk && dkn < DK_NDRIVE) 751 mi->mi_dk = dkn++; 752 else 753 mi->mi_dk = -1; 754 } 755 (*mi->mi_driver->md_attach)(mi); 756 printf("\n"); 757 return (mi); 758 } 759 return (0); 760 } 761 #endif 762 763 /* 764 * Fixctlrmask fixes the masks of the driver ctlr routines 765 * which otherwise save r10 and r11 where the interrupt and br 766 * level are passed through. 767 */ 768 fixctlrmask() 769 { 770 register struct uba_ctlr *um; 771 register struct uba_device *ui; 772 register struct uba_driver *ud; 773 #define phys(a,b) ((b)(((int)(a))&0x7fffffff)) 774 775 for (um = ubminit; ud = phys(um->um_driver, struct uba_driver *); um++) 776 *phys(ud->ud_probe, short *) &= ~0xc00; 777 for (ui = ubdinit; ud = phys(ui->ui_driver, struct uba_driver *); ui++) 778 *phys(ud->ud_probe, short *) &= ~0xc00; 779 } 780 781 #ifdef QBA 782 /* 783 * Configure a Q-bus. 784 */ 785 probeqbus(qb) 786 struct qbus *qb; 787 { 788 register struct uba_hd *uhp = &uba_hd[numuba]; 789 790 ioaccess((caddr_t)qb->qb_map, Nexmap[0], 791 qb->qb_memsize * sizeof (struct pte)); 792 uhp->uh_type = qb->qb_type; 793 uhp->uh_uba = (struct uba_regs *)0xc0000000; /* no uba adaptor regs */ 794 uhp->uh_mr = (struct pte *)&nexus[0]; 795 /* 796 * The map registers start right at 20088000 on the 797 * ka630, so we have to subtract out the 2k offset to make the 798 * pointers work.. 799 */ 800 uhp->uh_physuba = (struct uba_regs *)(((u_long)qb->qb_map)-0x800); 801 802 uhp->uh_memsize = qb->qb_memsize; 803 ioaccess(qb->qb_maddr, UMEMmap[numuba], uhp->uh_memsize * NBPG); 804 uhp->uh_mem = umem[numuba]; 805 806 /* 807 * The I/O page is mapped to the 8K of the umem address space 808 * immediately after the memory section that is mapped. 809 */ 810 ioaccess(qb->qb_iopage, UMEMmap[numuba] + uhp->uh_memsize, 811 UBAIOPAGES * NBPG); 812 uhp->uh_iopage = umem[numuba] + (uhp->uh_memsize * NBPG); 813 814 unifind(uhp, qb->qb_iopage); 815 } 816 #endif 817 818 #if NUBA > 0 819 probeuba(vubp, pubp, pumem) 820 struct uba_regs *vubp, *pubp; 821 caddr_t pumem; 822 { 823 register struct uba_hd *uhp = &uba_hd[numuba]; 824 825 /* 826 * Save virtual and physical addresses of adaptor. 827 */ 828 switch (cpu) { 829 #ifdef DW780 830 case VAX_8600: 831 case VAX_780: 832 uhp->uh_type = DW780; 833 break; 834 #endif 835 #ifdef DW750 836 case VAX_750: 837 uhp->uh_type = DW750; 838 break; 839 #endif 840 #ifdef DW730 841 case VAX_730: 842 uhp->uh_type = DW730; 843 break; 844 #endif 845 #ifdef DWBUA 846 case VAX_8200: 847 uhp->uh_type = DWBUA; 848 break; 849 #endif 850 default: 851 panic("unknown UBA type"); 852 /*NOTREACHED*/ 853 } 854 uhp->uh_uba = vubp; 855 uhp->uh_physuba = pubp; 856 uhp->uh_mr = vubp->uba_map; 857 uhp->uh_memsize = UBAPAGES; 858 859 ioaccess(pumem, UMEMmap[numuba], (UBAPAGES + UBAIOPAGES) * NBPG); 860 uhp->uh_mem = umem[numuba]; 861 uhp->uh_iopage = umem[numuba] + (uhp->uh_memsize * NBPG); 862 863 unifind(uhp, pumem + (uhp->uh_memsize * NBPG)); 864 } 865 866 /* 867 * Find devices on a UNIBUS. 868 * Uses per-driver routine to set <br,cvec> into <r11,r10>, 869 * and then fills in the tables, with help from a per-driver 870 * slave initialization routine. 871 */ 872 unifind(uhp0, pumem) 873 struct uba_hd *uhp0; 874 caddr_t pumem; 875 { 876 #ifndef lint 877 register int br, cvec; /* MUST BE r11, r10 */ 878 #else 879 /* 880 * Lint doesn't realize that these 881 * can be initialized asynchronously 882 * when devices interrupt. 883 */ 884 register int br = 0, cvec = 0; 885 #endif 886 register struct uba_device *ui; 887 register struct uba_ctlr *um; 888 register struct uba_hd *uhp = uhp0; 889 u_short *reg, *ap, addr; 890 struct uba_driver *udp; 891 int i, (**ivec)(); 892 caddr_t ualloc; 893 extern quad catcher[128]; 894 #if DW780 || DWBUA 895 struct uba_regs *vubp = uhp->uh_uba; 896 #endif 897 898 /* 899 * Initialize the UNIBUS, by freeing the map 900 * registers and the buffered data path registers 901 */ 902 uhp->uh_map = (struct map *) 903 malloc((u_long)(UAMSIZ * sizeof (struct map)), M_DEVBUF, 904 M_NOWAIT); 905 if (uhp->uh_map == 0) 906 panic("no mem for unibus map"); 907 bzero((caddr_t)uhp->uh_map, (unsigned)(UAMSIZ * sizeof (struct map))); 908 ubainitmaps(uhp); 909 910 /* 911 * Initialize space for the UNIBUS interrupt vectors. 912 * On the 8600, can't use first slot in UNIvec 913 * (the vectors for the second SBI overlap it); 914 * move each set of vectors forward. 915 */ 916 #if VAX8600 917 if (cpu == VAX_8600) 918 uhp->uh_vec = UNIvec[numuba + 1]; 919 else 920 #endif 921 uhp->uh_vec = UNIvec[numuba]; 922 for (i = 0; i < 128; i++) 923 uhp->uh_vec[i] = scbentry(&catcher[i], SCB_ISTACK); 924 /* 925 * Set last free interrupt vector for devices with 926 * programmable interrupt vectors. Use is to decrement 927 * this number and use result as interrupt vector. 928 */ 929 uhp->uh_lastiv = 0x200; 930 931 #ifdef DWBUA 932 if (uhp->uh_type == DWBUA) 933 BUA(vubp)->bua_offset = (int)uhp->uh_vec - (int)&scb[0]; 934 #endif 935 936 #ifdef DW780 937 if (uhp->uh_type == DW780) { 938 vubp->uba_sr = vubp->uba_sr; 939 vubp->uba_cr = UBACR_IFS|UBACR_BRIE; 940 } 941 #endif 942 /* 943 * First configure devices that have unibus memory, 944 * allowing them to allocate the correct map registers. 945 */ 946 ubameminit(numuba); 947 /* 948 * Grab some memory to record the umem address space we allocate, 949 * so we can be sure not to place two devices at the same address. 950 * 951 * We could use just 1/8 of this (we only want a 1 bit flag) but 952 * we are going to give it back anyway, and that would make the 953 * code here bigger (which we can't give back), so ... 954 * 955 * One day, someone will make a unibus with something other than 956 * an 8K i/o address space, & screw this totally. 957 */ 958 ualloc = (caddr_t)malloc((u_long)(8 * 1024), M_TEMP, M_NOWAIT); 959 if (ualloc == (caddr_t)0) 960 panic("no mem for unifind"); 961 bzero(ualloc, 8*1024); 962 963 /* 964 * Map the first page of UNIBUS i/o 965 * space to the first page of memory 966 * for devices which will need to dma 967 * output to produce an interrupt. 968 */ 969 *(int *)(&uhp->uh_mr[0]) = UBAMR_MRV; 970 971 #define ubaddr(uhp, off) (u_short *)((int)(uhp)->uh_iopage + ubdevreg(off)) 972 /* 973 * Check each unibus mass storage controller. 974 * For each one which is potentially on this uba, 975 * see if it is really there, and if it is record it and 976 * then go looking for slaves. 977 */ 978 for (um = ubminit; udp = um->um_driver; um++) { 979 if (um->um_ubanum != numuba && um->um_ubanum != '?' || 980 um->um_alive) 981 continue; 982 addr = (u_short)um->um_addr; 983 /* 984 * use the particular address specified first, 985 * or if it is given as "0", of there is no device 986 * at that address, try all the standard addresses 987 * in the driver til we find it 988 */ 989 for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) { 990 991 if (ualloc[ubdevreg(addr)]) 992 continue; 993 reg = ubaddr(uhp, addr); 994 if (badaddr((caddr_t)reg, 2)) 995 continue; 996 #ifdef DW780 997 if (uhp->uh_type == DW780 && vubp->uba_sr) { 998 vubp->uba_sr = vubp->uba_sr; 999 continue; 1000 } 1001 #endif 1002 cvec = 0x200; 1003 i = (*udp->ud_probe)(reg, um->um_ctlr, um); 1004 #ifdef DW780 1005 if (uhp->uh_type == DW780 && vubp->uba_sr) { 1006 vubp->uba_sr = vubp->uba_sr; 1007 continue; 1008 } 1009 #endif 1010 if (i == 0) 1011 continue; 1012 printf("%s%d at uba%d csr %o ", 1013 udp->ud_mname, um->um_ctlr, numuba, addr); 1014 if (cvec == 0) { 1015 printf("zero vector\n"); 1016 continue; 1017 } 1018 if (cvec == 0x200) { 1019 printf("didn't interrupt\n"); 1020 continue; 1021 } 1022 printf("vec %o, ipl %x\n", cvec, br); 1023 csralloc(ualloc, addr, i); 1024 um->um_alive = 1; 1025 um->um_ubanum = numuba; 1026 um->um_hd = uhp; 1027 um->um_addr = (caddr_t)reg; 1028 udp->ud_minfo[um->um_ctlr] = um; 1029 for (cvec /= 4, ivec = um->um_intr; *ivec; cvec++, ivec++) 1030 uhp->uh_vec[cvec] = scbentry(*ivec, SCB_ISTACK); 1031 for (ui = ubdinit; ui->ui_driver; ui++) { 1032 int t; 1033 1034 if (ui->ui_driver != udp || ui->ui_alive || 1035 ui->ui_ctlr != um->um_ctlr && ui->ui_ctlr != '?' || 1036 ui->ui_ubanum != numuba && ui->ui_ubanum != '?') 1037 continue; 1038 t = ui->ui_ctlr; 1039 ui->ui_ctlr = um->um_ctlr; 1040 if ((*udp->ud_slave)(ui, reg) == 0) 1041 ui->ui_ctlr = t; 1042 else { 1043 ui->ui_alive = 1; 1044 ui->ui_ubanum = numuba; 1045 ui->ui_hd = uhp; 1046 ui->ui_addr = (caddr_t)reg; 1047 ui->ui_physaddr = pumem + ubdevreg(addr); 1048 if (ui->ui_dk && dkn < DK_NDRIVE) 1049 ui->ui_dk = dkn++; 1050 else 1051 ui->ui_dk = -1; 1052 ui->ui_mi = um; 1053 /* ui_type comes from driver */ 1054 udp->ud_dinfo[ui->ui_unit] = ui; 1055 printf("%s%d at %s%d slave %d", 1056 udp->ud_dname, ui->ui_unit, 1057 udp->ud_mname, um->um_ctlr, ui->ui_slave); 1058 (*udp->ud_attach)(ui); 1059 printf("\n"); 1060 } 1061 } 1062 break; 1063 } 1064 } 1065 /* 1066 * Now look for non-mass storage peripherals. 1067 */ 1068 for (ui = ubdinit; udp = ui->ui_driver; ui++) { 1069 if (ui->ui_ubanum != numuba && ui->ui_ubanum != '?' || 1070 ui->ui_alive || ui->ui_slave != -1) 1071 continue; 1072 addr = (u_short)ui->ui_addr; 1073 1074 for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) { 1075 1076 if (ualloc[ubdevreg(addr)]) 1077 continue; 1078 reg = ubaddr(uhp, addr); 1079 if (badaddr((caddr_t)reg, 2)) 1080 continue; 1081 #ifdef DW780 1082 if (uhp->uh_type == DW780 && vubp->uba_sr) { 1083 vubp->uba_sr = vubp->uba_sr; 1084 continue; 1085 } 1086 #endif 1087 cvec = 0x200; 1088 i = (*udp->ud_probe)(reg, ui); 1089 #ifdef DW780 1090 if (uhp->uh_type == DW780 && vubp->uba_sr) { 1091 vubp->uba_sr = vubp->uba_sr; 1092 continue; 1093 } 1094 #endif 1095 if (i == 0) 1096 continue; 1097 printf("%s%d at uba%d csr %o ", 1098 ui->ui_driver->ud_dname, ui->ui_unit, numuba, addr); 1099 if (cvec == 0) { 1100 printf("zero vector\n"); 1101 continue; 1102 } 1103 if (cvec == 0x200) { 1104 printf("didn't interrupt\n"); 1105 continue; 1106 } 1107 printf("vec %o, ipl %x\n", cvec, br); 1108 csralloc(ualloc, addr, i); 1109 ui->ui_hd = uhp; 1110 for (cvec /= 4, ivec = ui->ui_intr; *ivec; cvec++, ivec++) 1111 uhp->uh_vec[cvec] = scbentry(*ivec, SCB_ISTACK); 1112 ui->ui_alive = 1; 1113 ui->ui_ubanum = numuba; 1114 ui->ui_addr = (caddr_t)reg; 1115 ui->ui_physaddr = pumem + ubdevreg(addr); 1116 ui->ui_dk = -1; 1117 /* ui_type comes from driver */ 1118 udp->ud_dinfo[ui->ui_unit] = ui; 1119 (*udp->ud_attach)(ui); 1120 break; 1121 } 1122 } 1123 1124 #ifdef DW780 1125 if (uhp->uh_type == DW780) 1126 uhp->uh_uba->uba_cr = UBACR_IFS | UBACR_BRIE | 1127 UBACR_USEFIE | UBACR_SUEFIE | 1128 (uhp->uh_uba->uba_cr & 0x7c000000); 1129 #endif 1130 numuba++; 1131 1132 #ifdef AUTO_DEBUG 1133 printf("Unibus allocation map"); 1134 for (i = 0; i < 8*1024; ) { 1135 register n, m; 1136 1137 if ((i % 128) == 0) { 1138 printf("\n%6o:", i); 1139 for (n = 0; n < 128; n++) 1140 if (ualloc[i+n]) 1141 break; 1142 if (n == 128) { 1143 i += 128; 1144 continue; 1145 } 1146 } 1147 1148 for (n = m = 0; n < 16; n++) { 1149 m <<= 1; 1150 m |= ualloc[i++]; 1151 } 1152 1153 printf(" %4x", m); 1154 } 1155 printf("\n"); 1156 #endif 1157 1158 free(ualloc, M_TEMP); 1159 } 1160 #endif /* NUBA */ 1161 1162 /* 1163 * Mark addresses starting at "addr" and continuing 1164 * "size" bytes as allocated in the map "ualloc". 1165 * Warn if the new allocation overlaps a previous allocation. 1166 */ 1167 static 1168 csralloc(ualloc, addr, size) 1169 caddr_t ualloc; 1170 u_short addr; 1171 register int size; 1172 { 1173 register caddr_t p; 1174 int warned = 0; 1175 1176 p = &ualloc[ubdevreg(addr+size)]; 1177 while (--size >= 0) { 1178 if (*--p && !warned) { 1179 printf( 1180 "WARNING: device registers overlap those for a previous device!\n"); 1181 warned = 1; 1182 } 1183 *p = 1; 1184 } 1185 } 1186 1187 /* 1188 * Make an IO register area accessible at physical address physa 1189 * by mapping kernel ptes starting at pte. 1190 */ 1191 ioaccess(physa, pte, size) 1192 caddr_t physa; 1193 register struct pte *pte; 1194 int size; 1195 { 1196 register int i = btoc(size); 1197 register unsigned v = btop(physa); 1198 1199 do 1200 *(int *)pte++ = PG_V|PG_KW|v++; 1201 while (--i > 0); 1202 mtpr(TBIA, 0); 1203 } 1204 1205 /* 1206 * Configure swap space and related parameters. 1207 */ 1208 swapconf() 1209 { 1210 register struct swdevt *swp; 1211 register int nblks; 1212 1213 for (swp = swdevt; swp->sw_dev; swp++) 1214 if (bdevsw[major(swp->sw_dev)].d_psize) { 1215 nblks = 1216 (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev); 1217 if (nblks != -1 && 1218 (swp->sw_nblks == 0 || swp->sw_nblks > nblks)) 1219 swp->sw_nblks = nblks; 1220 } 1221 if (dumplo == 0 && bdevsw[major(dumpdev)].d_psize) 1222 dumplo = (*bdevsw[major(dumpdev)].d_psize)(dumpdev) - physmem; 1223 if (dumplo < 0) 1224 dumplo = 0; 1225 } 1226 1227 #define DOSWAP /* Change swdevt, argdev, and dumpdev too */ 1228 u_long bootdev; /* should be dev_t, but not until 32 bits */ 1229 1230 static char devname[][2] = { 1231 'h','p', /* 0 = hp */ 1232 0,0, /* 1 = ht */ 1233 'u','p', /* 2 = up */ 1234 'r','k', /* 3 = hk */ 1235 0,0, /* 4 = sw */ 1236 0,0, /* 5 = tm */ 1237 0,0, /* 6 = ts */ 1238 0,0, /* 7 = mt */ 1239 0,0, /* 8 = tu */ 1240 'r','a', /* 9 = ra */ 1241 0,0, /* 10 = ut */ 1242 'r','b', /* 11 = rb */ 1243 0,0, /* 12 = uu */ 1244 0,0, /* 13 = rx */ 1245 'r','l', /* 14 = rl */ 1246 0,0, /* 15 = tmscp */ 1247 'k','r', /* 16 = ra on kdb50 */ 1248 }; 1249 1250 #define PARTITIONMASK 0x7 1251 #define PARTITIONSHIFT 3 1252 1253 /* 1254 * Attempt to find the device from which we were booted. 1255 * If we can do so, and not instructed not to do so, 1256 * change rootdev to correspond to the load device. 1257 */ 1258 setroot() 1259 { 1260 int majdev, mindev, unit, part, controller, adaptor; 1261 dev_t temp, orootdev; 1262 struct swdevt *swp; 1263 1264 if (boothowto & RB_DFLTROOT || 1265 (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) 1266 return; 1267 majdev = B_TYPE(bootdev); 1268 if (majdev >= sizeof(devname) / sizeof(devname[0])) 1269 return; 1270 adaptor = B_ADAPTOR(bootdev); 1271 controller = B_CONTROLLER(bootdev); 1272 part = B_PARTITION(bootdev); 1273 unit = B_UNIT(bootdev); 1274 if (majdev == 0) { /* MBA device */ 1275 #if NMBA > 0 1276 register struct mba_device *mbap; 1277 int mask; 1278 1279 /* 1280 * The MBA number used at boot time is not necessarily the same as the 1281 * MBA number used by the kernel. In order to change the rootdev we need to 1282 * convert the boot MBA number to the kernel MBA number. The address space 1283 * for an MBA used by the boot code is 0x20010000 + 0x2000 * MBA_number 1284 * on the 78? and 86?0, 0xf28000 + 0x2000 * MBA_number on the 750. 1285 * Therefore we can search the mba_hd table for the MBA that has the physical 1286 * address corresponding to the boot MBA number. 1287 */ 1288 #define PHYSADRSHFT 13 1289 #define PHYSMBAMASK780 0x7 1290 #define PHYSMBAMASK750 0x3 1291 1292 switch (cpu) { 1293 1294 case VAX_780: 1295 case VAX_8600: 1296 default: 1297 mask = PHYSMBAMASK780; 1298 break; 1299 1300 case VAX_750: 1301 mask = PHYSMBAMASK750; 1302 break; 1303 } 1304 for (mbap = mbdinit; mbap->mi_driver; mbap++) 1305 if (mbap->mi_alive && mbap->mi_drive == unit && 1306 (((long)mbap->mi_hd->mh_physmba >> PHYSADRSHFT) 1307 & mask) == adaptor) 1308 break; 1309 if (mbap->mi_driver == 0) 1310 return; 1311 mindev = mbap->mi_unit; 1312 #else 1313 return; 1314 #endif 1315 } else { 1316 register struct uba_device *ubap; 1317 1318 for (ubap = ubdinit; ubap->ui_driver; ubap++) 1319 if (ubap->ui_alive && ubap->ui_slave == unit && 1320 ubap->ui_ctlr == controller && 1321 ubap->ui_ubanum == adaptor && 1322 ubap->ui_driver->ud_dname[0] == devname[majdev][0] && 1323 ubap->ui_driver->ud_dname[1] == devname[majdev][1]) 1324 break; 1325 1326 if (ubap->ui_driver == 0) 1327 return; 1328 mindev = ubap->ui_unit; 1329 } 1330 mindev = (mindev << PARTITIONSHIFT) + part; 1331 orootdev = rootdev; 1332 rootdev = makedev(majdev, mindev); 1333 /* 1334 * If the original rootdev is the same as the one 1335 * just calculated, don't need to adjust the swap configuration. 1336 */ 1337 if (rootdev == orootdev) 1338 return; 1339 1340 printf("Changing root device to %c%c%d%c\n", 1341 devname[majdev][0], devname[majdev][1], 1342 mindev >> PARTITIONSHIFT, part + 'a'); 1343 1344 #ifdef DOSWAP 1345 mindev &= ~PARTITIONMASK; 1346 for (swp = swdevt; swp->sw_dev; swp++) { 1347 if (majdev == major(swp->sw_dev) && 1348 mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) { 1349 temp = swdevt[0].sw_dev; 1350 swdevt[0].sw_dev = swp->sw_dev; 1351 swp->sw_dev = temp; 1352 break; 1353 } 1354 } 1355 if (swp->sw_dev == 0) 1356 return; 1357 1358 /* 1359 * If argdev and dumpdev were the same as the old primary swap 1360 * device, move them to the new primary swap device. 1361 */ 1362 if (temp == dumpdev) 1363 dumpdev = swdevt[0].sw_dev; 1364 if (temp == argdev) 1365 argdev = swdevt[0].sw_dev; 1366 #endif 1367 } 1368