1 /* $OpenBSD: tc_3000_300.c,v 1.19 2017/11/02 14:04:24 mpi Exp $ */ 2 /* $NetBSD: tc_3000_300.c,v 1.26 2001/07/27 00:25:21 thorpej Exp $ */ 3 4 /* 5 * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. 6 * All rights reserved. 7 * 8 * Author: Chris G. Demetriou 9 * 10 * Permission to use, copy, modify and distribute this software and 11 * its documentation is hereby granted, provided that both the copyright 12 * notice and this permission notice appear in all copies of the 13 * software, derivative works or modified versions, and any portions 14 * thereof, and that both notices appear in supporting documentation. 15 * 16 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 17 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 18 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 19 * 20 * Carnegie Mellon requests users of this software to return to 21 * 22 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 23 * School of Computer Science 24 * Carnegie Mellon University 25 * Pittsburgh PA 15213-3890 26 * 27 * any improvements or extensions that they make and grant Carnegie the 28 * rights to redistribute these changes. 29 */ 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/device.h> 34 #include <sys/malloc.h> 35 36 #include <machine/autoconf.h> 37 #include <machine/pte.h> 38 39 #include <dev/tc/tcvar.h> 40 #include <dev/tc/ioasicreg.h> 41 #include <alpha/tc/tc_conf.h> 42 #include <alpha/tc/tc_3000_300.h> 43 44 #include "wsdisplay.h" 45 46 int tc_3000_300_intrnull(void *); 47 48 #define C(x) ((void *)(u_long)x) 49 #define KV(x) (ALPHA_PHYS_TO_K0SEG(x)) 50 51 /* 52 * We have to read and modify the IOASIC registers directly, because 53 * the TC option slot interrupt request and mask bits are stored there, 54 * and the ioasic code isn't initted when we need to frob some interrupt 55 * bits. 56 */ 57 #define DEC_3000_300_IOASIC_ADDR KV(0x1a0000000) 58 59 struct tc_slotdesc tc_3000_300_slots[] = { 60 { KV(0x100000000), C(TC_3000_300_DEV_OPT0), }, /* 0 - opt slot 0 */ 61 { KV(0x120000000), C(TC_3000_300_DEV_OPT1), }, /* 1 - opt slot 1 */ 62 { KV(0x140000000), C(TC_3000_300_DEV_BOGUS), }, /* 2 - unused */ 63 { KV(0x160000000), C(TC_3000_300_DEV_BOGUS), }, /* 3 - unused */ 64 { KV(0x180000000), C(TC_3000_300_DEV_BOGUS), }, /* 4 - TCDS ASIC */ 65 { KV(0x1a0000000), C(TC_3000_300_DEV_BOGUS), }, /* 5 - IOCTL ASIC */ 66 { KV(0x1c0000000), C(TC_3000_300_DEV_BOGUS), }, /* 6 - CXTurbo */ 67 }; 68 int tc_3000_300_nslots = 69 sizeof(tc_3000_300_slots) / sizeof(tc_3000_300_slots[0]); 70 71 struct tc_builtin tc_3000_300_builtins[] = { 72 { "PMAGB-BA", 6, 0x02000000, C(TC_3000_300_DEV_CXTURBO), }, 73 { "FLAMG-IO", 5, 0x00000000, C(TC_3000_300_DEV_IOASIC), }, 74 { "PMAZ-DS ", 4, 0x00000000, C(TC_3000_300_DEV_TCDS), }, 75 }; 76 int tc_3000_300_nbuiltins = 77 sizeof(tc_3000_300_builtins) / sizeof(tc_3000_300_builtins[0]); 78 79 struct tcintr { 80 int (*tci_func)(void *); 81 void *tci_arg; 82 int tci_level; 83 struct evcount tci_count; 84 } tc_3000_300_intr[TC_3000_300_NCOOKIES]; 85 86 void 87 tc_3000_300_intr_setup() 88 { 89 volatile u_int32_t *imskp; 90 u_long i; 91 92 /* 93 * Disable all interrupts that we can (can't disable builtins). 94 */ 95 imskp = (volatile u_int32_t *)(DEC_3000_300_IOASIC_ADDR + IOASIC_IMSK); 96 *imskp &= ~(IOASIC_INTR_300_OPT0 | IOASIC_INTR_300_OPT1); 97 98 /* 99 * Set up interrupt handlers. 100 */ 101 for (i = 0; i < TC_3000_300_NCOOKIES; i++) { 102 tc_3000_300_intr[i].tci_func = tc_3000_300_intrnull; 103 tc_3000_300_intr[i].tci_arg = (void *)i; 104 tc_3000_300_intr[i].tci_level = IPL_HIGH; 105 } 106 } 107 108 void 109 tc_3000_300_intr_establish(tcadev, cookie, level, func, arg, name) 110 struct device *tcadev; 111 void *cookie, *arg; 112 int level; 113 int (*func)(void *); 114 const char *name; 115 { 116 volatile u_int32_t *imskp; 117 u_long dev = (u_long)cookie; 118 119 #ifdef DIAGNOSTIC 120 /* XXX bounds-check cookie. */ 121 #endif 122 123 if (tc_3000_300_intr[dev].tci_func != tc_3000_300_intrnull) 124 panic("tc_3000_300_intr_establish: cookie %lu twice", dev); 125 126 tc_3000_300_intr[dev].tci_func = func; 127 tc_3000_300_intr[dev].tci_arg = arg; 128 tc_3000_300_intr[dev].tci_level = level; 129 if (name != NULL) 130 evcount_attach(&tc_3000_300_intr[dev].tci_count, name, NULL); 131 132 imskp = (volatile u_int32_t *)(DEC_3000_300_IOASIC_ADDR + IOASIC_IMSK); 133 switch (dev) { 134 case TC_3000_300_DEV_OPT0: 135 *imskp |= IOASIC_INTR_300_OPT0; 136 break; 137 case TC_3000_300_DEV_OPT1: 138 *imskp |= IOASIC_INTR_300_OPT1; 139 break; 140 default: 141 /* interrupts for builtins always enabled */ 142 break; 143 } 144 } 145 146 void 147 tc_3000_300_intr_disestablish(tcadev, cookie, name) 148 struct device *tcadev; 149 void *cookie; 150 const char *name; 151 { 152 volatile u_int32_t *imskp; 153 u_long dev = (u_long)cookie; 154 155 #ifdef DIAGNOSTIC 156 /* XXX bounds-check cookie. */ 157 #endif 158 159 if (tc_3000_300_intr[dev].tci_func == tc_3000_300_intrnull) 160 panic("tc_3000_300_intr_disestablish: cookie %lu bad intr", 161 dev); 162 163 imskp = (volatile u_int32_t *)(DEC_3000_300_IOASIC_ADDR + IOASIC_IMSK); 164 switch (dev) { 165 case TC_3000_300_DEV_OPT0: 166 *imskp &= ~IOASIC_INTR_300_OPT0; 167 break; 168 case TC_3000_300_DEV_OPT1: 169 *imskp &= ~IOASIC_INTR_300_OPT1; 170 break; 171 default: 172 /* interrupts for builtins always enabled */ 173 break; 174 } 175 176 tc_3000_300_intr[dev].tci_func = tc_3000_300_intrnull; 177 tc_3000_300_intr[dev].tci_arg = (void *)dev; 178 tc_3000_300_intr[dev].tci_level = IPL_HIGH; 179 if (name != NULL) 180 evcount_detach(&tc_3000_300_intr[dev].tci_count); 181 } 182 183 int 184 tc_3000_300_intrnull(val) 185 void *val; 186 { 187 188 panic("tc_3000_300_intrnull: uncaught TC intr for cookie %ld", 189 (u_long)val); 190 } 191 192 void 193 tc_3000_300_iointr(arg, vec) 194 void *arg; 195 unsigned long vec; 196 { 197 u_int32_t tcir, ioasicir, ioasicimr; 198 int ifound; 199 200 do { 201 tc_syncbus(); 202 203 /* find out what interrupts/errors occurred */ 204 tcir = *(volatile u_int32_t *)TC_3000_300_IR; 205 ioasicir = *(volatile u_int32_t *) 206 (DEC_3000_300_IOASIC_ADDR + IOASIC_INTR); 207 ioasicimr = *(volatile u_int32_t *) 208 (DEC_3000_300_IOASIC_ADDR + IOASIC_IMSK); 209 tc_mb(); 210 211 /* Ignore interrupts that aren't enabled out. */ 212 ioasicir &= ioasicimr; 213 214 /* clear the interrupts/errors we found. */ 215 *(volatile u_int32_t *)TC_3000_300_IR = tcir; 216 /* XXX can't clear TC option slot interrupts here? */ 217 tc_wmb(); 218 219 ifound = 0; 220 221 #ifdef MULTIPROCESSOR 222 #define INTRLOCK(slot) \ 223 if (tc_3000_300_intr[slot].tci_level < IPL_CLOCK) \ 224 __mp_lock(&kernel_lock) 225 #define INTRUNLOCK(slot) \ 226 if (tc_3000_300_intr[slot].tci_level < IPL_CLOCK) \ 227 __mp_unlock(&kernel_lock) 228 #else 229 #define INTRLOCK(slot) do { } while (0) 230 #define INTRUNLOCK(slot) do { } while (0) 231 #endif 232 #define CHECKINTR(slot, flag) \ 233 if (flag) { \ 234 ifound = 1; \ 235 INTRLOCK(slot); \ 236 (*tc_3000_300_intr[slot].tci_func) \ 237 (tc_3000_300_intr[slot].tci_arg); \ 238 tc_3000_300_intr[slot].tci_count.ec_count++; \ 239 INTRUNLOCK(slot); \ 240 } 241 242 /* Do them in order of priority; highest slot # first. */ 243 CHECKINTR(TC_3000_300_DEV_CXTURBO, 244 tcir & TC_3000_300_IR_CXTURBO); 245 CHECKINTR(TC_3000_300_DEV_IOASIC, 246 (tcir & TC_3000_300_IR_IOASIC) && 247 (ioasicir & ~(IOASIC_INTR_300_OPT1|IOASIC_INTR_300_OPT0))); 248 CHECKINTR(TC_3000_300_DEV_TCDS, tcir & TC_3000_300_IR_TCDS); 249 CHECKINTR(TC_3000_300_DEV_OPT1, 250 ioasicir & IOASIC_INTR_300_OPT1); 251 CHECKINTR(TC_3000_300_DEV_OPT0, 252 ioasicir & IOASIC_INTR_300_OPT0); 253 254 #undef INTRUNLOCK 255 #undef INTRLOCK 256 #undef CHECKINTR 257 258 #ifdef DIAGNOSTIC 259 #define PRINTINTR(msg, bits) \ 260 if (tcir & bits) \ 261 printf(msg); 262 263 PRINTINTR("BCache tag parity error\n", 264 TC_3000_300_IR_BCTAGPARITY); 265 PRINTINTR("TC overrun error\n", TC_3000_300_IR_TCOVERRUN); 266 PRINTINTR("TC I/O timeout\n", TC_3000_300_IR_TCTIMEOUT); 267 PRINTINTR("Bcache parity error\n", 268 TC_3000_300_IR_BCACHEPARITY); 269 PRINTINTR("Memory parity error\n", TC_3000_300_IR_MEMPARITY); 270 271 #undef PRINTINTR 272 #endif 273 } while (ifound); 274 } 275 276 #if NWSDISPLAY > 0 277 /* 278 * tc_3000_300_fb_cnattach -- 279 * Attempt to map the CTB output device to a slot and attach the 280 * framebuffer as the output side of the console. 281 */ 282 int 283 tc_3000_300_fb_cnattach(turbo_slot) 284 u_int64_t turbo_slot; 285 { 286 u_int32_t output_slot; 287 288 output_slot = turbo_slot & 0xffffffff; 289 290 if (output_slot >= tc_3000_300_nslots) { 291 return EINVAL; 292 } 293 294 if (output_slot == 0) { 295 return ENXIO; 296 } 297 298 return tc_fb_cnattach(tc_3000_300_slots[output_slot-1].tcs_addr); 299 } 300 #endif /* NWSDISPLAY */ 301