xref: /netbsd/sys/arch/vax/vax/ka860.c (revision 6550d01e)
1 /*	$NetBSD: ka860.c,v 1.34 2010/12/14 23:44:49 matt 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.34 2010/12/14 23:44:49 matt 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 immedately 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
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
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
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
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
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
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 
384 int abus_mainbus_match(device_t parent, cfdata_t self, void *aux)
385 {
386   return (vax_bustype == VAX_ABUS);
387 }
388 
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);
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 
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