Annotation of sys/arch/alpha/tc/tc_3000_300.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: tc_3000_300.c,v 1.12 2006/03/04 12:33:17 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: char tci_name[12];
! 89: } tc_3000_300_intr[TC_3000_300_NCOOKIES];
! 90:
! 91: void
! 92: tc_3000_300_intr_setup()
! 93: {
! 94: volatile u_int32_t *imskp;
! 95: u_long i;
! 96:
! 97: /*
! 98: * Disable all interrupts that we can (can't disable builtins).
! 99: */
! 100: imskp = (volatile u_int32_t *)(DEC_3000_300_IOASIC_ADDR + IOASIC_IMSK);
! 101: *imskp &= ~(IOASIC_INTR_300_OPT0 | IOASIC_INTR_300_OPT1);
! 102:
! 103: /*
! 104: * Set up interrupt handlers.
! 105: */
! 106: for (i = 0; i < TC_3000_300_NCOOKIES; i++) {
! 107: tc_3000_300_intr[i].tci_func = tc_3000_300_intrnull;
! 108: tc_3000_300_intr[i].tci_arg = (void *)i;
! 109: snprintf(tc_3000_300_intr[i].tci_name,
! 110: sizeof tc_3000_300_intr[i].tci_name, "tc slot %u", i);
! 111: evcount_attach(&tc_3000_300_intr[i].tci_count,
! 112: tc_3000_300_intr[i].tci_name, NULL, &evcount_intr);
! 113: }
! 114: }
! 115:
! 116: void
! 117: tc_3000_300_intr_establish(tcadev, cookie, level, func, arg)
! 118: struct device *tcadev;
! 119: void *cookie, *arg;
! 120: tc_intrlevel_t level;
! 121: int (*func)(void *);
! 122: {
! 123: volatile u_int32_t *imskp;
! 124: u_long dev = (u_long)cookie;
! 125:
! 126: #ifdef DIAGNOSTIC
! 127: /* XXX bounds-check cookie. */
! 128: #endif
! 129:
! 130: if (tc_3000_300_intr[dev].tci_func != tc_3000_300_intrnull)
! 131: panic("tc_3000_300_intr_establish: cookie %lu twice", dev);
! 132:
! 133: tc_3000_300_intr[dev].tci_func = func;
! 134: tc_3000_300_intr[dev].tci_arg = arg;
! 135:
! 136: imskp = (volatile u_int32_t *)(DEC_3000_300_IOASIC_ADDR + IOASIC_IMSK);
! 137: switch (dev) {
! 138: case TC_3000_300_DEV_OPT0:
! 139: *imskp |= IOASIC_INTR_300_OPT0;
! 140: break;
! 141: case TC_3000_300_DEV_OPT1:
! 142: *imskp |= IOASIC_INTR_300_OPT1;
! 143: break;
! 144: default:
! 145: /* interrupts for builtins always enabled */
! 146: break;
! 147: }
! 148: }
! 149:
! 150: void
! 151: tc_3000_300_intr_disestablish(tcadev, cookie)
! 152: struct device *tcadev;
! 153: void *cookie;
! 154: {
! 155: volatile u_int32_t *imskp;
! 156: u_long dev = (u_long)cookie;
! 157:
! 158: #ifdef DIAGNOSTIC
! 159: /* XXX bounds-check cookie. */
! 160: #endif
! 161:
! 162: if (tc_3000_300_intr[dev].tci_func == tc_3000_300_intrnull)
! 163: panic("tc_3000_300_intr_disestablish: cookie %lu bad intr",
! 164: dev);
! 165:
! 166: imskp = (volatile u_int32_t *)(DEC_3000_300_IOASIC_ADDR + IOASIC_IMSK);
! 167: switch (dev) {
! 168: case TC_3000_300_DEV_OPT0:
! 169: *imskp &= ~IOASIC_INTR_300_OPT0;
! 170: break;
! 171: case TC_3000_300_DEV_OPT1:
! 172: *imskp &= ~IOASIC_INTR_300_OPT1;
! 173: break;
! 174: default:
! 175: /* interrupts for builtins always enabled */
! 176: break;
! 177: }
! 178:
! 179: tc_3000_300_intr[dev].tci_func = tc_3000_300_intrnull;
! 180: tc_3000_300_intr[dev].tci_arg = (void *)dev;
! 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: #ifdef DIAGNOSTIC
! 201: int s;
! 202: if (vec != 0x800)
! 203: panic("INVALID ASSUMPTION: vec 0x%lx, not 0x800", vec);
! 204: s = splhigh();
! 205: if (s != ALPHA_PSL_IPL_IO)
! 206: panic("INVALID ASSUMPTION: IPL %d, not %d", s,
! 207: ALPHA_PSL_IPL_IO);
! 208: splx(s);
! 209: #endif
! 210:
! 211: do {
! 212: tc_syncbus();
! 213:
! 214: /* find out what interrupts/errors occurred */
! 215: tcir = *(volatile u_int32_t *)TC_3000_300_IR;
! 216: ioasicir = *(volatile u_int32_t *)
! 217: (DEC_3000_300_IOASIC_ADDR + IOASIC_INTR);
! 218: ioasicimr = *(volatile u_int32_t *)
! 219: (DEC_3000_300_IOASIC_ADDR + IOASIC_IMSK);
! 220: tc_mb();
! 221:
! 222: /* Ignore interrupts that aren't enabled out. */
! 223: ioasicir &= ioasicimr;
! 224:
! 225: /* clear the interrupts/errors we found. */
! 226: *(volatile u_int32_t *)TC_3000_300_IR = tcir;
! 227: /* XXX can't clear TC option slot interrupts here? */
! 228: tc_wmb();
! 229:
! 230: ifound = 0;
! 231:
! 232: #define CHECKINTR(slot, flag) \
! 233: if (flag) { \
! 234: ifound = 1; \
! 235: tc_3000_300_intr[slot].tci_count.ec_count++; \
! 236: (*tc_3000_300_intr[slot].tci_func) \
! 237: (tc_3000_300_intr[slot].tci_arg); \
! 238: }
! 239: /* Do them in order of priority; highest slot # first. */
! 240: CHECKINTR(TC_3000_300_DEV_CXTURBO,
! 241: tcir & TC_3000_300_IR_CXTURBO);
! 242: CHECKINTR(TC_3000_300_DEV_IOASIC,
! 243: (tcir & TC_3000_300_IR_IOASIC) &&
! 244: (ioasicir & ~(IOASIC_INTR_300_OPT1|IOASIC_INTR_300_OPT0)));
! 245: CHECKINTR(TC_3000_300_DEV_TCDS, tcir & TC_3000_300_IR_TCDS);
! 246: CHECKINTR(TC_3000_300_DEV_OPT1,
! 247: ioasicir & IOASIC_INTR_300_OPT1);
! 248: CHECKINTR(TC_3000_300_DEV_OPT0,
! 249: ioasicir & IOASIC_INTR_300_OPT0);
! 250: #undef CHECKINTR
! 251:
! 252: #ifdef DIAGNOSTIC
! 253: #define PRINTINTR(msg, bits) \
! 254: if (tcir & bits) \
! 255: printf(msg);
! 256: PRINTINTR("BCache tag parity error\n",
! 257: TC_3000_300_IR_BCTAGPARITY);
! 258: PRINTINTR("TC overrun error\n", TC_3000_300_IR_TCOVERRUN);
! 259: PRINTINTR("TC I/O timeout\n", TC_3000_300_IR_TCTIMEOUT);
! 260: PRINTINTR("Bcache parity error\n",
! 261: TC_3000_300_IR_BCACHEPARITY);
! 262: PRINTINTR("Memory parity error\n", TC_3000_300_IR_MEMPARITY);
! 263: #undef PRINTINTR
! 264: #endif
! 265: } while (ifound);
! 266: }
! 267:
! 268: #if NWSDISPLAY > 0
! 269: /*
! 270: * tc_3000_300_fb_cnattach --
! 271: * Attempt to map the CTB output device to a slot and attach the
! 272: * framebuffer as the output side of the console.
! 273: */
! 274: int
! 275: tc_3000_300_fb_cnattach(turbo_slot)
! 276: u_int64_t turbo_slot;
! 277: {
! 278: u_int32_t output_slot;
! 279:
! 280: output_slot = turbo_slot & 0xffffffff;
! 281:
! 282: if (output_slot >= tc_3000_300_nslots) {
! 283: return EINVAL;
! 284: }
! 285:
! 286: if (output_slot == 0) {
! 287: #if NSFB > 0
! 288: sfb_cnattach(KV(0x1c0000000) + 0x02000000);
! 289: return 0;
! 290: #else
! 291: return ENXIO;
! 292: #endif
! 293: }
! 294:
! 295: return tc_fb_cnattach(tc_3000_300_slots[output_slot-1].tcs_addr);
! 296: }
! 297: #endif /* NWSDISPLAY */
CVSweb