1 /* $NetBSD: dec_kn300.c,v 1.45 2025/03/09 01:06:42 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1998 by Matthew Jacob 5 * NASA AMES Research Center. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice immediately at the beginning of the file, without modification, 13 * this list of conditions, and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 34 35 __KERNEL_RCSID(0, "$NetBSD: dec_kn300.c,v 1.45 2025/03/09 01:06:42 thorpej Exp $"); 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/device.h> 40 41 #include <machine/rpb.h> 42 #include <machine/alpha.h> 43 #include <machine/autoconf.h> 44 #include <machine/frame.h> 45 #include <machine/cpuconf.h> 46 #include <machine/logout.h> 47 48 #include <dev/pci/pcivar.h> 49 50 #include <uvm/uvm_extern.h> 51 52 #include <alpha/mcbus/mcbusreg.h> 53 #include <alpha/mcbus/mcbusvar.h> 54 #include <alpha/pci/mcpciareg.h> 55 #include <alpha/pci/mcpciavar.h> 56 57 void dec_kn300_init(void); 58 void dec_kn300_cons_init(void); 59 static void dec_kn300_device_register(device_t, void *); 60 static void dec_kn300_mcheck_handler 61 (unsigned long, struct trapframe *, unsigned long, unsigned long); 62 63 #define ALPHASERVER_4100 "AlphaServer 4100" 64 65 const struct alpha_variation_table dec_kn300_variations[] = { 66 { 0, ALPHASERVER_4100 }, 67 { 0, NULL }, 68 }; 69 70 void 71 dec_kn300_init(void) 72 { 73 uint64_t variation; 74 int cachesize; 75 76 platform.family = ALPHASERVER_4100; 77 78 if ((platform.model = alpha_dsr_sysname()) == NULL) { 79 variation = hwrpb->rpb_variation & SV_ST_MASK; 80 if ((platform.model = alpha_variation_name(variation, 81 dec_kn300_variations)) == NULL) 82 platform.model = alpha_unknown_sysname(); 83 } 84 85 platform.iobus = "mcbus"; 86 platform.cons_init = dec_kn300_cons_init; 87 platform.device_register = dec_kn300_device_register; 88 platform.mcheck_handler = dec_kn300_mcheck_handler; 89 90 /* 91 * Determine B-cache size by looking at the primary (console) 92 * MCPCIA's WHOAMI register. 93 */ 94 mcpcia_init(); 95 96 if (mcbus_primary.mcbus_valid) { 97 switch (mcbus_primary.mcbus_bcache) { 98 default: 99 case CPU_BCache_0MB: 100 /* No B-cache or invalid; default to 1MB. */ 101 /* FALLTHROUGH */ 102 103 case CPU_BCache_1MB: 104 cachesize = (1 * 1024 * 1024); 105 break; 106 107 case CPU_BCache_2MB: 108 cachesize = (2 * 1024 * 1024); 109 break; 110 111 case CPU_BCache_4MB: 112 cachesize = (4 * 1024 * 1024); 113 break; 114 } 115 } else { 116 /* Default to 1MB. */ 117 cachesize = (1 * 1024 * 1024); 118 } 119 120 uvmexp.ncolors = atop(cachesize); 121 } 122 123 void 124 dec_kn300_cons_init(void) 125 { 126 struct mcpcia_config *ccp; 127 extern struct mcpcia_config mcpcia_console_configuration; 128 129 ccp = &mcpcia_console_configuration; 130 /* It's already initialized. */ 131 132 pci_consinit(&ccp->cc_pc, &ccp->cc_iot, &ccp->cc_memt, 133 &ccp->cc_iot, &ccp->cc_memt); 134 } 135 136 /* #define BDEBUG 1 */ 137 static void 138 dec_kn300_device_register(device_t dev, void *aux) 139 { 140 static device_t primarydev; 141 struct bootdev_data *b = bootdev_data; 142 143 if (booted_device != NULL || b == NULL) { 144 return; 145 } 146 147 if (primarydev == NULL) { 148 if (device_is_a(dev, "mcpcia")) { 149 struct mcbus_dev_attach_args *ma = aux; 150 151 if (b->bus == ma->ma_mid - 4) { 152 primarydev = dev; 153 #ifdef BDEBUG 154 printf("\nprimarydev = %s\n", 155 device_xname(dev)); 156 #endif 157 } 158 } 159 return; 160 } 161 162 pci_find_bootdev(primarydev, dev, aux); 163 } 164 165 166 /* 167 * KN300 Machine Check Handlers. 168 */ 169 static void kn300_softerr(unsigned long, unsigned long, 170 unsigned long, struct trapframe *); 171 172 static void kn300_mcheck(unsigned long, unsigned long, 173 unsigned long, struct trapframe *); 174 175 /* 176 * "soft" error structure in system area for KN300 processor. 177 * It differs from the EV5 'common' structure in a minor but 178 * exceedingly stupid and annoying fashion. 179 */ 180 181 typedef struct { 182 /* 183 * Should be mc_cc_ev5 structure. Contents are the same, 184 * just in different places. 185 */ 186 uint64_t ei_stat; 187 uint64_t ei_addr; 188 uint64_t fill_syndrome; 189 uint64_t isr; 190 /* 191 * Platform Specific Area 192 */ 193 uint32_t whami; 194 uint32_t sys_env; 195 uint64_t mcpcia_regs; 196 uint32_t pci_rev; 197 uint32_t mc_err0; 198 uint32_t mc_err1; 199 uint32_t cap_err; 200 uint32_t mdpa_stat; 201 uint32_t mdpa_syn; 202 uint32_t mdpb_stat; 203 uint32_t mdpb_syn; 204 uint64_t end_rsvd; 205 } mc_soft300; 206 #define CAP_ERR_CRDX 204 207 208 static void 209 kn300_softerr(unsigned long mces, unsigned long type, unsigned long logout, struct trapframe *framep) 210 { 211 static const char *sys = "system"; 212 static const char *proc = "processor"; 213 int whami; 214 mc_hdr_ev5 *hdr; 215 mc_soft300 *ptr; 216 static const char *fmt1 = " %-25s = 0x%l016x\n"; 217 218 hdr = (mc_hdr_ev5 *) logout; 219 ptr = (mc_soft300 *) (logout + sizeof (*hdr)); 220 whami = alpha_pal_whami(); 221 222 printf("kn300: CPU ID %d %s correctable error corrected by %s\n", whami, 223 (type == ALPHA_SYS_ERROR)? sys : proc, 224 ((hdr->mcheck_code & 0xff00) == (EV5_CORRECTED << 8))? proc : 225 (((hdr->mcheck_code & 0xff00) == (CAP_ERR_CRDX << 8)) ? 226 "I/O Bridge Module" : sys)); 227 228 printf(" Machine Check Code 0x%lx\n", hdr->mcheck_code); 229 printf(" Physical Address of Error 0x%lx\n", ptr->ei_addr); 230 if (ptr->ei_stat & 0x80000000L) 231 printf(" Corrected ECC Error "); 232 else 233 printf(" Other Error"); 234 if (ptr->ei_stat & 0x40000000L) 235 printf("in Memory "); 236 else 237 printf("in B-Cache "); 238 if (ptr->ei_stat & 0x400000000L) 239 printf("during I-Cache fill\n"); 240 else 241 printf("during D-Cache fill\n"); 242 243 printf(fmt1, "EI Status", ptr->ei_stat); 244 printf(fmt1, "Fill Syndrome", ptr->fill_syndrome); 245 printf(fmt1, "Interrupt Status Reg.", ptr->isr); 246 printf("\n"); 247 printf(fmt1, "Whami Reg.", ptr->whami); 248 printf(fmt1, "Sys. Env. Reg.", ptr->sys_env); 249 printf(fmt1, "MCPCIA Regs.", ptr->mcpcia_regs); 250 printf(fmt1, "PCI Rev. Reg.", ptr->pci_rev); 251 printf(fmt1, "MC_ERR0 Reg.", ptr->mc_err0); 252 printf(fmt1, "MC_ERR1 Reg.", ptr->mc_err1); 253 printf(fmt1, "CAP_ERR Reg.", ptr->cap_err); 254 printf(fmt1, "MDPA_STAT Reg.", ptr->mdpa_stat); 255 printf(fmt1, "MDPA_SYN Reg.", ptr->mdpa_syn); 256 printf(fmt1, "MDPB_STAT Reg.", ptr->mdpb_stat); 257 printf(fmt1, "MDPB_SYN Reg.", ptr->mdpb_syn); 258 259 /* 260 * Clear error by rewriting register. 261 */ 262 alpha_pal_wrmces(mces); 263 } 264 265 /* 266 * KN300 specific machine check handler 267 */ 268 269 static void 270 kn300_mcheck(unsigned long mces, unsigned long type, unsigned long logout, struct trapframe *framep) 271 { 272 struct mchkinfo *mcp; 273 static const char *fmt1 = " %-25s = 0x%l016x\n"; 274 int i; 275 mc_hdr_ev5 *hdr; 276 mc_uc_ev5 *ptr; 277 struct mcpcia_iodsnap *iodsnp; 278 279 /* 280 * If we expected a machine check, just go handle it in common code. 281 */ 282 mcp = &curcpu()->ci_mcinfo; 283 if (mcp->mc_expected) { 284 machine_check(mces, framep, type, logout); 285 return; 286 } 287 288 hdr = (mc_hdr_ev5 *) logout; 289 ptr = (mc_uc_ev5 *) (logout + sizeof (*hdr)); 290 ev5_logout_print(hdr, ptr); 291 292 iodsnp = (struct mcpcia_iodsnap *) ((unsigned long) hdr + 293 (unsigned long) hdr->la_system_offset); 294 for (i = 0; i < MCPCIA_PER_MCBUS; i++, iodsnp++) { 295 if (!IS_MCPCIA_MAGIC(iodsnp->pci_rev)) { 296 continue; 297 } 298 printf(" IOD %d register dump:\n", i); 299 printf(fmt1, "Base Addr of PCI bridge", iodsnp->base_addr); 300 printf(fmt1, "Whami Reg.", iodsnp->whami); 301 printf(fmt1, "Sys. Env. Reg.", iodsnp->sys_env); 302 printf(fmt1, "PCI Rev. Reg.", iodsnp->pci_rev); 303 printf(fmt1, "CAP_CTL Reg.", iodsnp->cap_ctrl); 304 printf(fmt1, "HAE_MEM Reg.", iodsnp->hae_mem); 305 printf(fmt1, "HAE_IO Reg.", iodsnp->hae_io); 306 printf(fmt1, "INT_CTL Reg.", iodsnp->int_ctl); 307 printf(fmt1, "INT_REG Reg.", iodsnp->int_reg); 308 printf(fmt1, "INT_MASK0 Reg.", iodsnp->int_mask0); 309 printf(fmt1, "INT_MASK1 Reg.", iodsnp->int_mask1); 310 printf(fmt1, "MC_ERR0 Reg.", iodsnp->mc_err0); 311 printf(fmt1, "MC_ERR1 Reg.", iodsnp->mc_err1); 312 printf(fmt1, "CAP_ERR Reg.", iodsnp->cap_err); 313 printf(fmt1, "PCI_ERR1 Reg.", iodsnp->pci_err1); 314 printf(fmt1, "MDPA_STAT Reg.", iodsnp->mdpa_stat); 315 printf(fmt1, "MDPA_SYN Reg.", iodsnp->mdpa_syn); 316 printf(fmt1, "MDPB_STAT Reg.", iodsnp->mdpb_stat); 317 printf(fmt1, "MDPB_SYN Reg.", iodsnp->mdpb_syn); 318 319 } 320 /* 321 * Now that we've printed all sorts of useful information 322 * and have decided that we really can't do any more to 323 * respond to the error, go on to the common code for 324 * final disposition. Usually this means that we die. 325 */ 326 /* 327 * XXX: HANDLE PCI ERRORS HERE? 328 */ 329 machine_check(mces, framep, type, logout); 330 } 331 332 static void 333 dec_kn300_mcheck_handler(unsigned long mces, struct trapframe *framep, unsigned long vector, unsigned long param) 334 { 335 switch (vector) { 336 case ALPHA_SYS_ERROR: 337 case ALPHA_PROC_ERROR: 338 kn300_softerr(mces, vector, param, framep); 339 break; 340 341 case ALPHA_SYS_MCHECK: 342 case ALPHA_PROC_MCHECK: 343 kn300_mcheck(mces, vector, param, framep); 344 break; 345 default: 346 printf("KN300_MCHECK: unknown check vector 0x%lx\n", vector); 347 machine_check(mces, framep, vector, param); 348 break; 349 } 350 } 351