1 /* $OpenBSD: tc_3000_300.c,v 1.17 2010/09/22 12:36:32 miod 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 #include "sfb.h" 46 47 #if NSFB > 0 48 extern int sfb_cnattach(tc_addr_t); 49 #endif 50 51 int tc_3000_300_intrnull(void *); 52 53 #define C(x) ((void *)(u_long)x) 54 #define KV(x) (ALPHA_PHYS_TO_K0SEG(x)) 55 56 /* 57 * We have to read and modify the IOASIC registers directly, because 58 * the TC option slot interrupt request and mask bits are stored there, 59 * and the ioasic code isn't initted when we need to frob some interrupt 60 * bits. 61 */ 62 #define DEC_3000_300_IOASIC_ADDR KV(0x1a0000000) 63 64 struct tc_slotdesc tc_3000_300_slots[] = { 65 { KV(0x100000000), C(TC_3000_300_DEV_OPT0), }, /* 0 - opt slot 0 */ 66 { KV(0x120000000), C(TC_3000_300_DEV_OPT1), }, /* 1 - opt slot 1 */ 67 { KV(0x140000000), C(TC_3000_300_DEV_BOGUS), }, /* 2 - unused */ 68 { KV(0x160000000), C(TC_3000_300_DEV_BOGUS), }, /* 3 - unused */ 69 { KV(0x180000000), C(TC_3000_300_DEV_BOGUS), }, /* 4 - TCDS ASIC */ 70 { KV(0x1a0000000), C(TC_3000_300_DEV_BOGUS), }, /* 5 - IOCTL ASIC */ 71 { KV(0x1c0000000), C(TC_3000_300_DEV_BOGUS), }, /* 6 - CXTurbo */ 72 }; 73 int tc_3000_300_nslots = 74 sizeof(tc_3000_300_slots) / sizeof(tc_3000_300_slots[0]); 75 76 struct tc_builtin tc_3000_300_builtins[] = { 77 { "PMAGB-BA", 6, 0x02000000, C(TC_3000_300_DEV_CXTURBO), }, 78 { "FLAMG-IO", 5, 0x00000000, C(TC_3000_300_DEV_IOASIC), }, 79 { "PMAZ-DS ", 4, 0x00000000, C(TC_3000_300_DEV_TCDS), }, 80 }; 81 int tc_3000_300_nbuiltins = 82 sizeof(tc_3000_300_builtins) / sizeof(tc_3000_300_builtins[0]); 83 84 struct tcintr { 85 int (*tci_func)(void *); 86 void *tci_arg; 87 struct evcount tci_count; 88 } tc_3000_300_intr[TC_3000_300_NCOOKIES]; 89 90 void 91 tc_3000_300_intr_setup() 92 { 93 volatile u_int32_t *imskp; 94 u_long i; 95 96 /* 97 * Disable all interrupts that we can (can't disable builtins). 98 */ 99 imskp = (volatile u_int32_t *)(DEC_3000_300_IOASIC_ADDR + IOASIC_IMSK); 100 *imskp &= ~(IOASIC_INTR_300_OPT0 | IOASIC_INTR_300_OPT1); 101 102 /* 103 * Set up interrupt handlers. 104 */ 105 for (i = 0; i < TC_3000_300_NCOOKIES; i++) { 106 tc_3000_300_intr[i].tci_func = tc_3000_300_intrnull; 107 tc_3000_300_intr[i].tci_arg = (void *)i; 108 } 109 } 110 111 void 112 tc_3000_300_intr_establish(tcadev, cookie, level, func, arg, name) 113 struct device *tcadev; 114 void *cookie, *arg; 115 int level; 116 int (*func)(void *); 117 const char *name; 118 { 119 volatile u_int32_t *imskp; 120 u_long dev = (u_long)cookie; 121 122 #ifdef DIAGNOSTIC 123 /* XXX bounds-check cookie. */ 124 #endif 125 126 if (tc_3000_300_intr[dev].tci_func != tc_3000_300_intrnull) 127 panic("tc_3000_300_intr_establish: cookie %lu twice", dev); 128 129 tc_3000_300_intr[dev].tci_func = func; 130 tc_3000_300_intr[dev].tci_arg = arg; 131 if (name != NULL) 132 evcount_attach(&tc_3000_300_intr[dev].tci_count, name, NULL); 133 134 imskp = (volatile u_int32_t *)(DEC_3000_300_IOASIC_ADDR + IOASIC_IMSK); 135 switch (dev) { 136 case TC_3000_300_DEV_OPT0: 137 *imskp |= IOASIC_INTR_300_OPT0; 138 break; 139 case TC_3000_300_DEV_OPT1: 140 *imskp |= IOASIC_INTR_300_OPT1; 141 break; 142 default: 143 /* interrupts for builtins always enabled */ 144 break; 145 } 146 } 147 148 void 149 tc_3000_300_intr_disestablish(tcadev, cookie, name) 150 struct device *tcadev; 151 void *cookie; 152 const char *name; 153 { 154 volatile u_int32_t *imskp; 155 u_long dev = (u_long)cookie; 156 157 #ifdef DIAGNOSTIC 158 /* XXX bounds-check cookie. */ 159 #endif 160 161 if (tc_3000_300_intr[dev].tci_func == tc_3000_300_intrnull) 162 panic("tc_3000_300_intr_disestablish: cookie %lu bad intr", 163 dev); 164 165 imskp = (volatile u_int32_t *)(DEC_3000_300_IOASIC_ADDR + IOASIC_IMSK); 166 switch (dev) { 167 case TC_3000_300_DEV_OPT0: 168 *imskp &= ~IOASIC_INTR_300_OPT0; 169 break; 170 case TC_3000_300_DEV_OPT1: 171 *imskp &= ~IOASIC_INTR_300_OPT1; 172 break; 173 default: 174 /* interrupts for builtins always enabled */ 175 break; 176 } 177 178 tc_3000_300_intr[dev].tci_func = tc_3000_300_intrnull; 179 tc_3000_300_intr[dev].tci_arg = (void *)dev; 180 if (name != NULL) 181 evcount_detach(&tc_3000_300_intr[dev].tci_count); 182 } 183 184 int 185 tc_3000_300_intrnull(val) 186 void *val; 187 { 188 189 panic("tc_3000_300_intrnull: uncaught TC intr for cookie %ld", 190 (u_long)val); 191 } 192 193 void 194 tc_3000_300_iointr(arg, vec) 195 void *arg; 196 unsigned long vec; 197 { 198 u_int32_t tcir, ioasicir, ioasicimr; 199 int ifound; 200 201 #ifdef DIAGNOSTIC 202 int s; 203 if (vec != 0x800) 204 panic("INVALID ASSUMPTION: vec 0x%lx, not 0x800", vec); 205 s = splhigh(); 206 if (s != ALPHA_PSL_IPL_IO) 207 panic("INVALID ASSUMPTION: IPL %d, not %d", s, 208 ALPHA_PSL_IPL_IO); 209 splx(s); 210 #endif 211 212 do { 213 tc_syncbus(); 214 215 /* find out what interrupts/errors occurred */ 216 tcir = *(volatile u_int32_t *)TC_3000_300_IR; 217 ioasicir = *(volatile u_int32_t *) 218 (DEC_3000_300_IOASIC_ADDR + IOASIC_INTR); 219 ioasicimr = *(volatile u_int32_t *) 220 (DEC_3000_300_IOASIC_ADDR + IOASIC_IMSK); 221 tc_mb(); 222 223 /* Ignore interrupts that aren't enabled out. */ 224 ioasicir &= ioasicimr; 225 226 /* clear the interrupts/errors we found. */ 227 *(volatile u_int32_t *)TC_3000_300_IR = tcir; 228 /* XXX can't clear TC option slot interrupts here? */ 229 tc_wmb(); 230 231 ifound = 0; 232 233 #define CHECKINTR(slot, flag) \ 234 if (flag) { \ 235 ifound = 1; \ 236 tc_3000_300_intr[slot].tci_count.ec_count++; \ 237 (*tc_3000_300_intr[slot].tci_func) \ 238 (tc_3000_300_intr[slot].tci_arg); \ 239 } 240 /* Do them in order of priority; highest slot # first. */ 241 CHECKINTR(TC_3000_300_DEV_CXTURBO, 242 tcir & TC_3000_300_IR_CXTURBO); 243 CHECKINTR(TC_3000_300_DEV_IOASIC, 244 (tcir & TC_3000_300_IR_IOASIC) && 245 (ioasicir & ~(IOASIC_INTR_300_OPT1|IOASIC_INTR_300_OPT0))); 246 CHECKINTR(TC_3000_300_DEV_TCDS, tcir & TC_3000_300_IR_TCDS); 247 CHECKINTR(TC_3000_300_DEV_OPT1, 248 ioasicir & IOASIC_INTR_300_OPT1); 249 CHECKINTR(TC_3000_300_DEV_OPT0, 250 ioasicir & IOASIC_INTR_300_OPT0); 251 #undef CHECKINTR 252 253 #ifdef DIAGNOSTIC 254 #define PRINTINTR(msg, bits) \ 255 if (tcir & bits) \ 256 printf(msg); 257 PRINTINTR("BCache tag parity error\n", 258 TC_3000_300_IR_BCTAGPARITY); 259 PRINTINTR("TC overrun error\n", TC_3000_300_IR_TCOVERRUN); 260 PRINTINTR("TC I/O timeout\n", TC_3000_300_IR_TCTIMEOUT); 261 PRINTINTR("Bcache parity error\n", 262 TC_3000_300_IR_BCACHEPARITY); 263 PRINTINTR("Memory parity error\n", TC_3000_300_IR_MEMPARITY); 264 #undef PRINTINTR 265 #endif 266 } while (ifound); 267 } 268 269 #if NWSDISPLAY > 0 270 /* 271 * tc_3000_300_fb_cnattach -- 272 * Attempt to map the CTB output device to a slot and attach the 273 * framebuffer as the output side of the console. 274 */ 275 int 276 tc_3000_300_fb_cnattach(turbo_slot) 277 u_int64_t turbo_slot; 278 { 279 u_int32_t output_slot; 280 281 output_slot = turbo_slot & 0xffffffff; 282 283 if (output_slot >= tc_3000_300_nslots) { 284 return EINVAL; 285 } 286 287 if (output_slot == 0) { 288 #if NSFB > 0 289 sfb_cnattach(KV(0x1c0000000) + 0x02000000); 290 return 0; 291 #else 292 return ENXIO; 293 #endif 294 } 295 296 return tc_fb_cnattach(tc_3000_300_slots[output_slot-1].tcs_addr); 297 } 298 #endif /* NWSDISPLAY */ 299