Home | History | Annotate | Line # | Download | only in vax
      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
    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, 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 
    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