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