1 /* $NetBSD: ka860.c,v 1.37 2024/02/02 22:00:33 andvar Exp $ */
2 /*
3 * Copyright (c) 1986, 1988 Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * @(#)ka860.c 7.4 (Berkeley) 12/16/90
31 */
32
33 /*
34 * VAX 8600 specific routines.
35 * Also contains abus spec's and memory init routines.
36 *
37 * Todo: Set up all four console lines in a VAX8600.
38 * This is: local, remote, EMM and logical.
39 *
40 * ABus code added by Johnny Billquist 2010
41 */
42
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: ka860.c,v 1.37 2024/02/02 22:00:33 andvar Exp $");
45
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/cpu.h>
49 #include <sys/device.h>
50
51 #include <machine/clock.h>
52 #include <machine/nexus.h>
53 #include <machine/ioa.h>
54 #include <machine/sid.h>
55 #include <machine/mainbus.h>
56
57 #include <vax/vax/gencons.h>
58
59 void crlattach(void);
60
61 static void ka86_memerr(void);
62 static int ka86_mchk(void *);
63 static void ka86_reboot(int);
64 static void ka86_clrf(void);
65 static void ka860_conf(void);
66 static void ka86_attach_cpu(device_t);
67 static int abus_mainbus_match(device_t, cfdata_t, void *);
68 static void abus_mainbus_attach(device_t, device_t, void*);
69 static int abus_print(void *, const char *);
70
71 static const char * const ka86_devs[] = { "cpu", "abus", NULL };
72
73 const struct cpu_dep ka860_calls = {
74 .cpu_mchk = ka86_mchk,
75 .cpu_memerr = ka86_memerr,
76 .cpu_conf = ka860_conf,
77 .cpu_gettime = generic_gettime,
78 .cpu_settime = generic_settime,
79 .cpu_vups = 6, /* ~VUPS */
80 .cpu_scbsz = 10, /* SCB pages */
81 .cpu_reboot = ka86_reboot,
82 .cpu_clrf = ka86_clrf,
83 .cpu_devs = ka86_devs,
84 .cpu_attach_cpu = ka86_attach_cpu,
85 };
86
87 /*
88 * 8600 memory register (MERG) bit definitions
89 */
90 #define M8600_ICRD 0x400 /* inhibit crd interrupts */
91 #define M8600_TB_ERR 0xf00 /* translation buffer error mask */
92
93 /*
94 * MDECC register
95 */
96 #define M8600_ADDR_PE 0x080000 /* address parity error */
97 #define M8600_DBL_ERR 0x100000 /* data double bit error */
98 #define M8600_SNG_ERR 0x200000 /* data single bit error */
99 #define M8600_BDT_ERR 0x400000 /* bad data error */
100
101 /*
102 * ESPA register is used to address scratch pad registers in the Ebox.
103 * To access a register in the scratch pad, write the ESPA with the address
104 * and then read the ESPD register.
105 *
106 * NOTE: In assmebly code, the mfpr instruction that reads the ESPD
107 * register must immediately follow the mtpr instruction that setup
108 * the ESPA register -- per the VENUS processor register spec.
109 *
110 * The scratchpad registers that are supplied for a single bit ECC
111 * error are:
112 */
113 #define SPAD_MSTAT1 0x25 /* scratch pad mstat1 register */
114 #define SPAD_MSTAT2 0x26 /* scratch pad mstat2 register */
115 #define SPAD_MDECC 0x27 /* scratch pad mdecc register */
116 #define SPAD_MEAR 0x2a /* scratch pad mear register */
117
118 #define M8600_MEMERR(mdecc) ((mdecc) & 0x780000)
119 #define M8600_HRDERR(mdecc) ((mdecc) & 0x580000)
120 #define M8600_SYN(mdecc) (((mdecc) >> 9) & 0x3f)
121 #define M8600_ADDR(mear) ((mear) & 0x3ffffffc)
122 #define M8600_ARRAY(mear) (((mear) >> 22) & 0x0f)
123
124 #define M8600_MDECC_BITS \
125 "\20\27BAD_DT_ERR\26SNG_BIT_ERR\25DBL_BIT_ERR\24ADDR_PE"
126
127 #define M8600_MSTAT1_BITS "\20\30CPR_PE_A\27CPR_PE_B\26ABUS_DT_PE\
128 \25ABUS_CTL_MSK_PE\24ABUS_ADR_PE\23ABUS_C/A_CYCLE\22ABUS_ADP_1\21ABUS_ADP_0\
129 \20TB_MISS\17BLK_HIT\16C0_TAG_MISS\15CHE_MISS\14TB_VAL_ERR\13TB_PTE_B_PE\
130 \12TB_PTE_A_PE\11TB_TAG_PE\10WR_DT_PE_B3\7WR_DT_PE_B2\6WR_DT_PE_B1\
131 \5WR_DT_PE_B0\4CHE_RD_DT_PE\3CHE_SEL\2ANY_REFL\1CP_BW_CHE_DT_PE"
132
133 #define M8600_MSTAT2_BITS "\20\20CP_BYT_WR\17ABUS_BD_DT_CODE\10MULT_ERR\
134 \7CHE_TAG_PE\6CHE_TAG_W_PE\5CHE_WRTN_BIT\4NXM\3CP-IO_BUF_ERR\2MBOX_LOCK"
135
136 /* log CRD errors */
137 void
ka86_memerr(void)138 ka86_memerr(void)
139 {
140 int mdecc, mear, mstat1, mstat2, array;
141
142 /*
143 * Scratchpad registers in the Ebox must be read by
144 * storing their ID number in ESPA and then immediately
145 * reading ESPD's contents with no other intervening
146 * machine instructions!
147 *
148 * The asm's below have a number of constants which
149 * are defined correctly above and in mtpr.h.
150 */
151 __asm("mtpr $0x27,$0x4e; mfpr $0x4f,%0" : "=g" (mdecc));
152 /* must acknowledge interrupt? */
153 if (M8600_MEMERR(mdecc)) {
154 __asm("mtpr $0x2a,$0x4e; mfpr $0x4f,%0" : "=g" (mear));
155 __asm("mtpr $0x25,$0x4e; mfpr $0x4f,%0" : "=g" (mstat1));
156 __asm("mtpr $0x26,$0x4e; mfpr $0x4f,%0" : "=g" (mstat2));
157 array = M8600_ARRAY(mear);
158
159 {
160 char sbuf[256], sbuf2[256];
161
162 printf("mcr0: ecc error, addr %x (array %d) syn %x\n",
163 M8600_ADDR(mear), array, M8600_SYN(mdecc));
164
165 snprintb(sbuf, sizeof(sbuf), M8600_MSTAT1_BITS, mstat1);
166 snprintb(sbuf2, sizeof(sbuf2), M8600_MSTAT2_BITS, mstat2);
167 printf("\tMSTAT1 = %s\n\tMSTAT2 = %s\n", sbuf, sbuf2);
168 }
169
170 mtpr(0, PR_EHSR);
171 mtpr(mfpr(PR_MERG) | M8600_ICRD, PR_MERG);
172 }
173 }
174
175 #define NMC8600 7
176 const char * const mc8600[] = {
177 "unkn type", "fbox error", "ebox error", "ibox error",
178 "mbox error", "tbuf error", "mbox 1D error"
179 };
180 /* codes for above */
181 #define MC_FBOX 1
182 #define MC_EBOX 2
183 #define MC_IBOX 3
184 #define MC_MBOX 4
185 #define MC_TBUF 5
186 #define MC_MBOX1D 6
187
188 /* error bits */
189 #define MBOX_FE 0x8000 /* Mbox fatal error */
190 #define FBOX_SERV 0x10000000 /* Fbox service error */
191 #define IBOX_ERR 0x2000 /* Ibox error */
192 #define EBOX_ERR 0x1e00 /* Ebox error */
193 #define MBOX_1D 0x81d0000 /* Mbox 1D error */
194 #define EDP_PE 0x200
195
196 struct mc8600frame {
197 int mc86_bcnt; /* byte count == 0x58 */
198 int mc86_ehmsts;
199 int mc86_evmqsav;
200 int mc86_ebcs;
201 int mc86_edpsr;
202 int mc86_cslint;
203 int mc86_ibesr;
204 int mc86_ebxwd1;
205 int mc86_ebxwd2;
206 int mc86_ivasav;
207 int mc86_vibasav;
208 int mc86_esasav;
209 int mc86_isasav;
210 int mc86_cpc;
211 int mc86_mstat1;
212 int mc86_mstat2;
213 int mc86_mdecc;
214 int mc86_merg;
215 int mc86_cshctl;
216 int mc86_mear;
217 int mc86_medr;
218 int mc86_accs;
219 int mc86_cses;
220 int mc86_pc; /* trapped pc */
221 int mc86_psl; /* trapped psl */
222 };
223
224 /* machine check */
225 int
ka86_mchk(void * cmcf)226 ka86_mchk(void *cmcf)
227 {
228 struct mc8600frame *mcf = (struct mc8600frame *)cmcf;
229 int type;
230
231 if (mcf->mc86_ebcs & MBOX_FE)
232 mcf->mc86_ehmsts |= MC_MBOX;
233 else if (mcf->mc86_ehmsts & FBOX_SERV)
234 mcf->mc86_ehmsts |= MC_FBOX;
235 else if (mcf->mc86_ebcs & EBOX_ERR) {
236 if (mcf->mc86_ebcs & EDP_PE)
237 mcf->mc86_ehmsts |= MC_MBOX;
238 else
239 mcf->mc86_ehmsts |= MC_EBOX;
240 } else if (mcf->mc86_ehmsts & IBOX_ERR)
241 mcf->mc86_ehmsts |= MC_IBOX;
242 else if (mcf->mc86_mstat1 & M8600_TB_ERR)
243 mcf->mc86_ehmsts |= MC_TBUF;
244 else if ((mcf->mc86_cslint & MBOX_1D) == MBOX_1D)
245 mcf->mc86_ehmsts |= MC_MBOX1D;
246
247 type = mcf->mc86_ehmsts & 0x7;
248 printf("machine check %x: %s\n", type,
249 type < NMC8600 ? mc8600[type] : "???");
250 printf("\tehm.sts %x evmqsav %x ebcs %x edpsr %x cslint %x\n",
251 mcf->mc86_ehmsts, mcf->mc86_evmqsav, mcf->mc86_ebcs,
252 mcf->mc86_edpsr, mcf->mc86_cslint);
253 printf("\tibesr %x ebxwd %x %x ivasav %x vibasav %x\n",
254 mcf->mc86_ibesr, mcf->mc86_ebxwd1, mcf->mc86_ebxwd2,
255 mcf->mc86_ivasav, mcf->mc86_vibasav);
256 printf("\tesasav %x isasav %x cpc %x mstat %x %x mdecc %x\n",
257 mcf->mc86_esasav, mcf->mc86_isasav, mcf->mc86_cpc,
258 mcf->mc86_mstat1, mcf->mc86_mstat2, mcf->mc86_mdecc);
259 printf("\tmerg %x cshctl %x mear %x medr %x accs %x cses %x\n",
260 mcf->mc86_merg, mcf->mc86_cshctl, mcf->mc86_mear,
261 mcf->mc86_medr, mcf->mc86_accs, mcf->mc86_cses);
262 printf("\tpc %x psl %x\n", mcf->mc86_pc, mcf->mc86_psl);
263 mtpr(0, PR_EHSR);
264 return (MCHK_PANIC);
265 }
266
267 struct ka86 {
268 unsigned snr:12,
269 plant:4,
270 eco:7,
271 v8650:1,
272 type:8;
273 };
274
275 /* The manufacturing plant information comes from EK-86XV1-MG-003
276 * VAX 86XX System Maintenance Guide
277 * /bqt
278 */
279
280 static const char * const manuf[] = {"Unknown",
281 "Galway, Ireland",
282 "Franklin, MA",
283 "Burlington, VT",
284 "Marlboro, MA"};
285
286 const int mindex[] = {0,1,1,1, 0,2,2,2, 0,0,3,3, 3,4,4,4};
287
288 void
ka860_conf(void)289 ka860_conf(void)
290 {
291 /* Enable cache */
292 mtpr(3, PR_CSWP);
293
294 /* enable CRD reports */
295 mtpr(mfpr(PR_MERG) & ~M8600_ICRD, PR_MERG);
296 }
297
298 void
ka86_attach_cpu(device_t self)299 ka86_attach_cpu(device_t self)
300 {
301 struct ka86 * const ka86 = (void *)&vax_cpudata;
302 int fpa;
303
304 aprint_naive(": KA86%d, S/N %d, Rev. %c, manufactured in %s.\n",
305 ka86->v8650 ? 5 : 0, ka86->snr, ka86->eco+64,
306 manuf[mindex[ka86->plant]]);
307 aprint_normal(": KA86%d, S/N %d, Rev. %c, manufactured in %s.\n",
308 ka86->v8650 ? 5 : 0, ka86->snr, ka86->eco+64,
309 manuf[mindex[ka86->plant]]);
310 fpa = mfpr(PR_ACCS);
311 if (fpa & 255) {
312 aprint_naive_dev(self,
313 "FPA present: type %d, serial number %d\n",
314 fpa & 255, fpa >> 16);
315 aprint_normal_dev(self,
316 "FPA present: type %d, serial number %d\n",
317 fpa & 255, fpa >> 16);
318 mtpr(0x8000, PR_ACCS);
319 } else {
320 aprint_naive_dev(self, "no FPA\n");
321 aprint_normal_dev(self, "no FPA\n");
322 }
323
324 /*
325 * Init CPU.
326 * Attach crl first.
327 */
328
329 crlattach();
330 }
331
332 /*
333 * Clear restart flag.
334 */
335 void
ka86_clrf(void)336 ka86_clrf(void)
337 {
338 /*
339 * We block all interrupts here so that there won't be any
340 * interrupts for an ongoing printout.
341 */
342 int s = splhigh(), old = mfpr(PR_TXCS);
343
344 #define WAIT while ((mfpr(PR_TXCS) & GC_RDY) == 0) ;
345
346 WAIT;
347
348 /* Enable channel to console */
349 mtpr(GC_LT|GC_WRT, PR_TXCS);
350 WAIT;
351
352 /* clear warm start flag */
353 mtpr(GC_CWFL, PR_TXDB);
354 WAIT;
355
356 /* clear cold start flag */
357 mtpr(GC_CCFL, PR_TXDB);
358 WAIT;
359
360 /* restore old state */
361 mtpr(old|GC_WRT, PR_TXCS);
362 splx(s);
363 }
364
365 void
ka86_reboot(int howto)366 ka86_reboot(int howto)
367 {
368 WAIT;
369
370 /* Enable channel to console */
371 mtpr(GC_LT|GC_WRT, PR_TXCS);
372 WAIT;
373
374 mtpr(GC_BTFL, PR_TXDB);
375 WAIT;
376
377 __asm("halt");
378 }
379
380
381 CFATTACH_DECL_NEW(abus_mainbus, 0,
382 abus_mainbus_match, abus_mainbus_attach, NULL, NULL);
383
abus_mainbus_match(device_t parent,cfdata_t self,void * aux)384 int abus_mainbus_match(device_t parent, cfdata_t self, void *aux)
385 {
386 return (vax_bustype == VAX_ABUS);
387 }
388
abus_mainbus_attach(device_t parent,device_t self,void * aux)389 void abus_mainbus_attach(device_t parent, device_t self, void *aux)
390 {
391 struct mainbus_attach_args * const ma = aux;
392 struct abus_attach_args aa;
393
394 unsigned int tmp;
395 volatile struct sbia_regs *sbiar;
396
397 int type, i;
398
399 aprint_naive("\n");
400 aprint_normal("\n");
401
402 for (i = 0; i < NIOA8600; i++) {
403 sbiar = (struct sbia_regs *)vax_map_physmem((paddr_t)IOA8600(i),
404 (IOAMAPSIZ / VAX_NBPG));
405 if (badaddr(sbiar, 4)) {
406 vax_unmap_physmem((vaddr_t)sbiar,
407 (IOAMAPSIZ / VAX_NBPG));
408 continue;
409 }
410
411 tmp = sbiar->sbi_cfg;
412 type = tmp & IOA_TYPMSK;
413
414 switch (type) {
415
416 case IOA_SBIA:
417
418 aa.aa_base = (bus_addr_t)(SBIA8600(i));
419 aa.aa_num = i;
420 aa.aa_name = "sbi";
421 aa.aa_type = tmp;
422 aa.aa_iot = ma->ma_iot;
423 aa.aa_dmat = ma->ma_dmat;
424
425 sbiar->sbi_errsum = -1;
426 sbiar->sbi_error = 0x1000;
427 sbiar->sbi_fltsts = 0xc0000;
428
429 config_found(self, &aa, abus_print, CFARGS_NONE);
430 break;
431
432 default:
433 aprint_naive("IOAdapter %#x unsupported\n", type);
434 aprint_normal("IOAdapter %#x unsupported\n", type);
435 }
436
437 vax_unmap_physmem((vaddr_t)sbiar, (IOAMAPSIZ / VAX_NBPG));
438 }
439 }
440
abus_print(void * aux,const char * name)441 int abus_print(void *aux, const char *name)
442 {
443 struct abus_attach_args *aa = aux;
444
445 if (name) {
446 aprint_naive("%s%d at %s\n", aa->aa_name, aa->aa_num, name);
447 aprint_normal("%s%d at %s\n", aa->aa_name, aa->aa_num, name);
448 }
449 return UNSUPP;
450 }
451