1 /* $NetBSD: dec_5100.c,v 1.33 2001/09/18 16:15:20 tsutsui Exp $ */ 2 3 /* 4 * Copyright (c) 1998 Jonathan Stone. 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. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Jonathan Stone for 17 * the NetBSD Project. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 33 34 __KERNEL_RCSID(0, "$NetBSD: dec_5100.c,v 1.33 2001/09/18 16:15:20 tsutsui Exp $"); 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/device.h> 39 #include <sys/kernel.h> 40 41 #include <machine/cpu.h> 42 #include <machine/intr.h> 43 #include <machine/locore.h> 44 #include <machine/sysconf.h> 45 46 #include <mips/mips/mips_mcclock.h> /* mcclock CPUspeed estimation */ 47 48 #include <pmax/pmax/machdep.h> 49 #include <pmax/pmax/kn01.h> /* common definitions */ 50 #include <pmax/pmax/kn230.h> 51 #include <pmax/dev/dcvar.h> 52 53 #include <pmax/ibus/ibusvar.h> 54 55 void dec_5100_init __P((void)); /* XXX */ 56 static void dec_5100_bus_reset __P((void)); 57 static void dec_5100_cons_init __P((void)); 58 static void dec_5100_intr __P((unsigned, unsigned, unsigned, unsigned)); 59 static void dec_5100_intr_establish __P((struct device *, void *, 60 int, int (*)(void *), void *)); 61 static void dec_5100_memintr __P((void)); 62 63 void 64 dec_5100_init() 65 { 66 platform.iobus = "baseboard"; 67 platform.bus_reset = dec_5100_bus_reset; 68 platform.cons_init = dec_5100_cons_init; 69 platform.iointr = dec_5100_intr; 70 platform.intr_establish = dec_5100_intr_establish; 71 platform.memsize = memsize_scan; 72 /* no high resolution timer available */ 73 74 /* set correct wbflush routine for this motherboard */ 75 mips_set_wbflush(kn230_wbflush); 76 77 splvec.splbio = MIPS_SPL1; 78 splvec.splnet = MIPS_SPL1; 79 splvec.spltty = MIPS_SPL_0_1; 80 splvec.splvm = MIPS_SPL_0_1_2; 81 splvec.splclock = MIPS_SPL_0_1_2; 82 splvec.splstatclock = MIPS_SPL_0_1_2; 83 84 /* calibrate cpu_mhz value */ 85 mc_cpuspeed(MIPS_PHYS_TO_KSEG1(KN01_SYS_CLOCK), MIPS_INT_MASK_2); 86 87 sprintf(cpu_model, "DECsystem 5100 (MIPSMATE)"); 88 } 89 90 /* 91 * Initialize the memory system and I/O buses. 92 */ 93 static void 94 dec_5100_bus_reset() 95 { 96 u_int32_t icsr; 97 98 /* clear any memory error condition */ 99 icsr = *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(KN230_SYS_ICSR); 100 icsr |= KN230_CSR_INTR_WMERR; 101 *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(KN230_SYS_ICSR) = icsr; 102 103 /* nothing else to do */ 104 kn230_wbflush(); 105 } 106 107 static void 108 dec_5100_cons_init() 109 { 110 /* 111 * Delay to allow PROM putchars to complete. 112 * FIFO depth * character time, 113 * character time = (1000000 / (defaultrate / 10)) 114 */ 115 DELAY(160000000 / 9600); /* XXX */ 116 117 dc_cnattach(KN230_SYS_DZ0, 0); 118 } 119 120 static void 121 dec_5100_intr_establish(dev, cookie, level, handler, arg) 122 struct device *dev; 123 void *cookie; 124 int level; 125 int (*handler) __P((void *)); 126 void *arg; 127 { 128 129 intrtab[(int)cookie].ih_func = handler; 130 intrtab[(int)cookie].ih_arg = arg; 131 } 132 133 134 #define CALLINTR(vvv, ibit) \ 135 do { \ 136 if ((icsr & (ibit)) && intrtab[vvv].ih_func) { \ 137 (*intrtab[vvv].ih_func)(intrtab[vvv].ih_arg); \ 138 intrcnt[vvv]++; \ 139 } \ 140 } while (0) 141 142 static void 143 dec_5100_intr(status, cause, pc, ipending) 144 unsigned status; 145 unsigned cause; 146 unsigned pc; 147 unsigned ipending; 148 { 149 u_int32_t icsr; 150 151 if (ipending & MIPS_INT_MASK_4) { 152 #ifdef DDB 153 Debugger(); 154 #else 155 prom_haltbutton(); 156 #endif 157 } 158 159 icsr = *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(KN230_SYS_ICSR); 160 161 /* handle clock interrupts ASAP */ 162 if (ipending & MIPS_INT_MASK_2) { 163 struct clockframe cf; 164 165 __asm __volatile("lbu $0,48(%0)" :: 166 "r"(MIPS_PHYS_TO_KSEG1(KN01_SYS_CLOCK))); 167 cf.pc = pc; 168 cf.sr = status; 169 hardclock(&cf); 170 pmax_clock_evcnt.ev_count++; 171 172 /* keep clock interrupts enabled when we return */ 173 cause &= ~MIPS_INT_MASK_2; 174 } 175 176 /* If clock interrupts were enabled, re-enable them ASAP. */ 177 _splset(MIPS_SR_INT_IE | (status & MIPS_INT_MASK_2)); 178 179 if (ipending & MIPS_INT_MASK_0) { 180 CALLINTR(SYS_DEV_SCC0, KN230_CSR_INTR_DZ0); 181 CALLINTR(SYS_DEV_OPT0, KN230_CSR_INTR_OPT0); 182 CALLINTR(SYS_DEV_OPT1, KN230_CSR_INTR_OPT1); 183 } 184 185 if (ipending & MIPS_INT_MASK_1) { 186 CALLINTR(SYS_DEV_LANCE, KN230_CSR_INTR_LANCE); 187 CALLINTR(SYS_DEV_SCSI, KN230_CSR_INTR_SII); 188 } 189 190 if (ipending & MIPS_INT_MASK_3) { 191 dec_5100_memintr(); 192 pmax_memerr_evcnt.ev_count++; 193 } 194 195 _splset(MIPS_SR_INT_IE | (status & ~cause & MIPS_HARD_INT_MASK)); 196 } 197 198 199 /* 200 * Handle write-to-nonexistent-address memory errors on MIPS_INT_MASK_3. 201 * These are reported asynchronously, due to hardware write buffering. 202 * we can't easily figure out process context, so just panic. 203 * 204 * XXX drain writebuffer on contextswitch to avoid panic? 205 */ 206 static void 207 dec_5100_memintr() 208 { 209 u_int32_t icsr; 210 211 /* read icsr and clear error */ 212 icsr = *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(KN230_SYS_ICSR); 213 icsr |= KN230_CSR_INTR_WMERR; 214 *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(KN230_SYS_ICSR) = icsr; 215 kn230_wbflush(); 216 217 #ifdef DIAGNOSTIC 218 printf("\nMemory interrupt\n"); 219 #endif 220 221 /* ignore errors during probes */ 222 if (cold) 223 return; 224 225 if (icsr & KN230_CSR_INTR_WMERR) { 226 panic("write to non-existent memory"); 227 } 228 else { 229 panic("stray memory error interrupt"); 230 } 231 } 232