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