Home | History | Annotate | Line # | Download | only in vax
      1 /*	$NetBSD: ka780.c,v 1.35 2024/02/04 18:47:27 andvar Exp $ */
      2 /*-
      3  * Copyright (c) 1982, 1986, 1988 The 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  *	@(#)ka780.c	7.4 (Berkeley) 5/9/91
     31  */
     32 
     33 /*
     34  * 780-specific code.
     35  */
     36 
     37 #include <sys/cdefs.h>
     38 __KERNEL_RCSID(0, "$NetBSD: ka780.c,v 1.35 2024/02/04 18:47:27 andvar Exp $");
     39 
     40 #include <sys/param.h>
     41 #include <sys/systm.h>
     42 #include <sys/bus.h>
     43 #include <sys/cpu.h>
     44 #include <sys/device.h>
     45 
     46 #include <machine/nexus.h>
     47 #include <machine/sid.h>
     48 #include <machine/clock.h>
     49 
     50 #include "ioconf.h"
     51 #include "locators.h"
     52 
     53 static	void ka780_memerr(void);
     54 static	int ka780_mchk(void *);
     55 static	void ka780_conf(void);
     56 static	void ka780_attach_cpu(device_t);
     57 static	int getsort(int type);
     58 
     59 static	int mem_sbi_match(device_t, cfdata_t, void *);
     60 static	void mem_sbi_attach(device_t, device_t, void *);
     61 
     62 CFATTACH_DECL_NEW(mem_sbi, sizeof(struct mem_softc),
     63     mem_sbi_match, mem_sbi_attach, NULL, NULL);
     64 
     65 int
     66 mem_sbi_match(device_t parent, cfdata_t cf, void *aux)
     67 {
     68 	struct sbi_attach_args * const sa = aux;
     69 
     70 	if (cf->cf_loc[SBICF_TR] != sa->sa_nexnum &&
     71 	    cf->cf_loc[SBICF_TR] != SBICF_TR_DEFAULT)
     72 		return 0;
     73 
     74 	return getsort(sa->sa_type);
     75 }
     76 
     77 int
     78 getsort(int type)
     79 {
     80 	switch (type) {
     81 	case NEX_MEM4:
     82 	case NEX_MEM4I:
     83 	case NEX_MEM16:
     84 	case NEX_MEM16I:
     85 		return M780C;
     86 
     87 	case NEX_MEM64I:
     88 	case NEX_MEM64L:
     89 	case NEX_MEM64LI:
     90 	case NEX_MEM256I:
     91 	case NEX_MEM256L:
     92 	case NEX_MEM256LI:
     93 		return M780EL;
     94 
     95 	case NEX_MEM64U:
     96 	case NEX_MEM64UI:
     97 	case NEX_MEM256U:
     98 	case NEX_MEM256UI:
     99 		return M780EU;
    100 
    101 	default:
    102 		return M_NONE;
    103 	}
    104 }
    105 
    106 static const char * const ka780_devs[] = { "cpu", "sbi", NULL };
    107 
    108 /*
    109  * Declaration of 780-specific calls.
    110  */
    111 const struct cpu_dep ka780_calls = {
    112 	.cpu_mchk	= ka780_mchk,
    113 	.cpu_memerr	= ka780_memerr,
    114 	.cpu_conf	= ka780_conf,
    115 	.cpu_gettime	= generic_gettime,
    116 	.cpu_settime	= generic_settime,
    117 	.cpu_vups	= 2,	/* ~VUPS */
    118 	.cpu_scbsz	= 5,	/* SCB pages */
    119 	.cpu_devs	= ka780_devs,
    120 	.cpu_attach_cpu	= ka780_attach_cpu,
    121 };
    122 
    123 /*
    124  * Memory controller register usage varies per controller.
    125  */
    126 struct mcr780 {
    127 	int	mc_reg[4];
    128 };
    129 
    130 #define M780_ICRD	0x40000000	/* inhibit crd interrupts, in [2] */
    131 #define M780_HIER	0x20000000	/* high error rate, in reg[2] */
    132 #define M780_ERLOG	0x10000000	/* error log request, in reg[2] */
    133 /* on a 780, memory crd's occur only when bit 15 is set in the SBIER */
    134 /* register; bit 14 there is an error bit which we also clear */
    135 /* these bits are in the back of the ``red book'' (or in the VMS code) */
    136 
    137 #define M780C_INH(mcr)	\
    138 	((mcr)->mc_reg[2] = (M780_ICRD|M780_HIER|M780_ERLOG)); \
    139 	    mtpr(0, PR_SBIER);
    140 #define M780C_ENA(mcr)	\
    141 	((mcr)->mc_reg[2] = (M780_HIER|M780_ERLOG)); mtpr(3<<14, PR_SBIER);
    142 #define M780C_ERR(mcr)	\
    143 	((mcr)->mc_reg[2] & (M780_ERLOG))
    144 
    145 #define M780C_SYN(mcr)	((mcr)->mc_reg[2] & 0xff)
    146 #define M780C_ADDR(mcr) (((mcr)->mc_reg[2] >> 8) & 0xfffff)
    147 
    148 #define M780EL_INH(mcr) \
    149 	((mcr)->mc_reg[2] = (M780_ICRD|M780_HIER|M780_ERLOG)); \
    150 	    mtpr(0, PR_SBIER);
    151 #define M780EL_ENA(mcr) \
    152 	((mcr)->mc_reg[2] = (M780_HIER|M780_ERLOG)); mtpr(3<<14, PR_SBIER);
    153 #define M780EL_ERR(mcr) \
    154 	((mcr)->mc_reg[2] & (M780_ERLOG))
    155 
    156 #define M780EL_SYN(mcr)		((mcr)->mc_reg[2] & 0x7f)
    157 #define M780EL_ADDR(mcr)	(((mcr)->mc_reg[2] >> 11) & 0x1ffff)
    158 
    159 #define M780EU_INH(mcr) \
    160 	((mcr)->mc_reg[3] = (M780_ICRD|M780_HIER|M780_ERLOG)); \
    161 	    mtpr(0, PR_SBIER);
    162 #define M780EU_ENA(mcr) \
    163 	((mcr)->mc_reg[3] = (M780_HIER|M780_ERLOG)); mtpr(3<<14, PR_SBIER);
    164 #define M780EU_ERR(mcr) \
    165 	((mcr)->mc_reg[3] & (M780_ERLOG))
    166 
    167 #define M780EU_SYN(mcr)		((mcr)->mc_reg[3] & 0x7f)
    168 #define M780EU_ADDR(mcr)	(((mcr)->mc_reg[3] >> 11) & 0x1ffff)
    169 
    170 /* enable crd interrupts */
    171 void
    172 mem_sbi_attach(device_t parent, device_t self, void *aux)
    173 {
    174 	struct sbi_attach_args * const sa = (struct sbi_attach_args *)aux;
    175 	struct mem_softc * const sc = device_private(self);
    176 	struct mcr780 * const mcr = (void *)sa->sa_ioh; /* XXX */
    177 
    178 	sc->sc_dev = self;
    179 	sc->sc_memaddr = (void *)sa->sa_ioh; /* XXX */
    180 	sc->sc_memtype = getsort(sa->sa_type);
    181 	sc->sc_memnr = sa->sa_type;
    182 
    183 	switch (sc->sc_memtype) {
    184 	case M780C:
    185 		aprint_normal(": standard");
    186 		M780C_ENA(mcr);
    187 		break;
    188 
    189 	case M780EL:
    190 		aprint_normal(": (el) ");
    191 		M780EL_ENA(mcr);
    192 		if (sc->sc_memnr != NEX_MEM64I && sc->sc_memnr != NEX_MEM256I)
    193 			break;
    194 
    195 	case M780EU:
    196 		aprint_normal(": (eu)");
    197 		M780EU_ENA(mcr);
    198 		break;
    199 	}
    200 	printf("\n");
    201 }
    202 
    203 #ifdef TRENDATA
    204 /*
    205  * Figure out what chip to replace on Trendata boards.
    206  * Assumes all your memory is Trendata or the non-Trendata
    207  * memory never fails..
    208  */
    209 const struct {
    210 	u_char	m_syndrome;
    211 	char	m_chip[4];
    212 } memlogtab[] = {
    213 	{0x01,	"C00"},	{0x02,	"C01"},	{0x04,	"C02"},	{0x08,	"C03"},
    214 	{0x10,	"C04"},	{0x19,	"L01"},	{0x1A,	"L02"},	{0x1C,	"L04"},
    215 	{0x1F,	"L07"},	{0x20,	"C05"},	{0x38,	"L00"},	{0x3B,	"L03"},
    216 	{0x3D,	"L05"},	{0x3E,	"L06"},	{0x40,	"C06"},	{0x49,	"L09"},
    217 	{0x4A,	"L10"},	{0x4c,	"L12"},	{0x4F,	"L15"},	{0x51,	"L17"},
    218 	{0x52,	"L18"},	{0x54,	"L20"},	{0x57,	"L23"},	{0x58,	"L24"},
    219 	{0x5B,	"L27"},	{0x5D,	"L29"},	{0x5E,	"L30"},	{0x68,	"L08"},
    220 	{0x6B,	"L11"},	{0x6D,	"L13"},	{0x6E,	"L14"},	{0x70,	"L16"},
    221 	{0x73,	"L19"},	{0x75,	"L21"},	{0x76,	"L22"},	{0x79,	"L25"},
    222 	{0x7A,	"L26"},	{0x7C,	"L28"},	{0x7F,	"L31"},	{0x80,	"C07"},
    223 	{0x89,	"U01"},	{0x8A,	"U02"},	{0x8C,	"U04"},	{0x8F,	"U07"},
    224 	{0x91,	"U09"},	{0x92,	"U10"},	{0x94,	"U12"},	{0x97,	"U15"},
    225 	{0x98,	"U16"},	{0x9B,	"U19"},	{0x9D,	"U21"},	{0x9E,	"U22"},
    226 	{0xA8,	"U00"},	{0xAB,	"U03"},	{0xAD,	"U05"},	{0xAE,	"U06"},
    227 	{0xB0,	"U08"},	{0xB3,	"U11"},	{0xB5,	"U13"},	{0xB6,	"U14"},
    228 	{0xB9,	"U17"},	{0xBA,	"U18"},	{0xBC,	"U20"},	{0xBF,	"U23"},
    229 	{0xC1,	"U25"},	{0xC2,	"U26"},	{0xC4,	"U28"},	{0xC7,	"U31"},
    230 	{0xE0,	"U24"},	{0xE3,	"U27"},	{0xE5,	"U29"},	{0xE6,	"U30"}
    231 };
    232 
    233 static void
    234 memlog(int m, struct mcr780 *mcr)
    235 {
    236 	int i;
    237 
    238 	for (i = 0; i < __arraycount(memlogtab); i++)
    239 		if ((u_char)(M780C_SYN(mcr)) == memlogtab[i].m_syndrome) {
    240 			printf(
    241 			    "mcr%d: replace %s chip in %s bank of memory"
    242 			    " board %d (0-15)\n",
    243 			    m, memlogtab[i].m_chip,
    244 			    (M780C_ADDR(mcr) & 0x8000) ? "upper" : "lower",
    245 			    (M780C_ADDR(mcr) >> 16));
    246 			return;
    247 		}
    248 	printf("mcr%d: multiple errors, not traceable\n", m);
    249 }
    250 #endif /* TRENDATA */
    251 
    252 /* log crd errors */
    253 void
    254 ka780_memerr(void)
    255 {
    256 	struct mem_softc *sc;
    257 	struct mcr780 *mcr;
    258 	int m;
    259 
    260 	for (m = 0; m < mem_cd.cd_ndevs; m++) {
    261 		sc = device_lookup_private(&mem_cd, m);
    262 		if (sc == NULL)
    263 			continue;
    264 		mcr = (struct mcr780 *)sc->sc_memaddr;
    265 		switch (sc->sc_memtype) {
    266 
    267 		case M780C:
    268 			if (M780C_ERR(mcr)) {
    269 				aprint_error_dev(sc->sc_dev,
    270 				    "soft ecc addr %x syn %x\n",
    271 				    M780C_ADDR(mcr), M780C_SYN(mcr));
    272 #ifdef TRENDATA
    273 				memlog(m, mcr);
    274 #endif
    275 				M780C_INH(mcr);
    276 			}
    277 			break;
    278 
    279 		case M780EL:
    280 			if (M780EL_ERR(mcr)) {
    281 				aprint_error_dev(sc->sc_dev,
    282 				    "soft ecc addr %x syn %x\n",
    283 				    M780EL_ADDR(mcr), M780EL_SYN(mcr));
    284 				M780EL_INH(mcr);
    285 			}
    286 			if (sc->sc_memnr != NEX_MEM64I &&
    287 			    sc->sc_memnr != NEX_MEM256I)
    288 				break;
    289 
    290 		case M780EU:
    291 			if (M780EU_ERR(mcr)) {
    292 				aprint_error_dev(sc->sc_dev,
    293 				    "soft ecc addr %x syn %x\n",
    294 				    M780EU_ADDR(mcr), M780EU_SYN(mcr));
    295 				M780EU_INH(mcr);
    296 			}
    297 			break;
    298 		}
    299 	}
    300 }
    301 
    302 const char mc780[][3] = {
    303 	"0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15"
    304 };
    305 
    306 struct mc780frame {
    307 	int	mc8_bcnt;		/* byte count == 0x28 */
    308 	int	mc8_summary;		/* summary parameter (as above) */
    309 	int	mc8_cpues;		/* cpu error status */
    310 	int	mc8_upc;		/* micro pc */
    311 	int	mc8_vaviba;		/* va/viba register */
    312 	int	mc8_dreg;		/* d register */
    313 	int	mc8_tber0;		/* tbuf error reg 0 */
    314 	int	mc8_tber1;		/* tbuf error reg 1 */
    315 	int	mc8_timo;		/* timeout address divided by 4 */
    316 	int	mc8_parity;		/* parity */
    317 	int	mc8_sbier;		/* sbi error register */
    318 	int	mc8_pc;			/* trapped pc */
    319 	int	mc8_psl;		/* trapped psl */
    320 };
    321 
    322 int
    323 ka780_mchk(void *cmcf)
    324 {
    325 	struct mc780frame * const mcf = (struct mc780frame *)cmcf;
    326 	int type = mcf->mc8_summary;
    327 	int sbifs;
    328 
    329 	printf("machine check %x: %s%s\n", type, mc780[type&0xf],
    330 	    (type&0xf0) ? " abort" : " fault");
    331 	printf("\tcpues %x upc %x va/viba %x dreg %x tber %x %x\n",
    332 	   mcf->mc8_cpues, mcf->mc8_upc, mcf->mc8_vaviba,
    333 	   mcf->mc8_dreg, mcf->mc8_tber0, mcf->mc8_tber1);
    334 	sbifs = mfpr(PR_SBIFS);
    335 	printf("\ttimo %x parity %x sbier %x pc %x psl %x sbifs %x\n",
    336 	   mcf->mc8_timo*4, mcf->mc8_parity, mcf->mc8_sbier,
    337 	   mcf->mc8_pc, mcf->mc8_psl, sbifs);
    338 	/* THE FUNNY BITS IN THE FOLLOWING ARE FROM THE ``BLACK BOOK'' */
    339 	/* AND SHOULD BE PUT IN AN ``sbi.h'' */
    340 	mtpr(sbifs &~ 0x2000000, PR_SBIFS);
    341 	mtpr(mfpr(PR_SBIER) | 0x70c0, PR_SBIER);
    342 	return (MCHK_PANIC);
    343 }
    344 
    345 struct ka78x {
    346 	unsigned snr:12,
    347 		 plant:3,
    348 		 eco:8,
    349 		 v785:1,
    350 		 type:8;
    351 };
    352 
    353 void
    354 ka780_conf(void)
    355 {
    356 	/* Enable cache */
    357 	mtpr(0x200000, PR_SBIMT);
    358 
    359 }
    360 
    361 void
    362 ka780_attach_cpu(device_t self)
    363 {
    364 	struct ka78x * const ka78 = (void *)&vax_cpudata;
    365 
    366 	aprint_normal(": KA%s, S/N %d(%d), hardware ECO level %d(%d)\n",
    367 	    cpu_getmodel() + 7, ka78->snr, ka78->plant, ka78->eco >> 4, ka78->eco);
    368 	aprint_normal_dev(self, "4KB L1 cache");
    369 	if (mfpr(PR_ACCS) & 255) {
    370 		aprint_normal(", FPA present\n");
    371 		mtpr(0x8000, PR_ACCS);
    372 	} else
    373 		aprint_normal(", no FPA\n");
    374 
    375 }
    376