Annotation of sys/arch/alpha/tc/tc_3000_500.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: tc_3000_500.c,v 1.13 2006/03/04 12:33:17 miod Exp $ */
! 2: /* $NetBSD: tc_3000_500.c,v 1.24 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: #include <machine/rpb.h>
! 39:
! 40: #include <dev/tc/tcvar.h>
! 41: #include <alpha/tc/tc_conf.h>
! 42: #include <alpha/tc/tc_3000_500.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: void tc_3000_500_intr_setup(void);
! 52: void tc_3000_500_intr_establish(struct device *, void *,
! 53: tc_intrlevel_t, int (*)(void *), void *);
! 54: void tc_3000_500_intr_disestablish(struct device *, void *);
! 55: void tc_3000_500_iointr(void *, unsigned long);
! 56:
! 57: int tc_3000_500_intrnull(void *);
! 58: int tc_3000_500_fb_cnattach(u_int64_t);
! 59:
! 60: #define C(x) ((void *)(u_long)x)
! 61: #define KV(x) (ALPHA_PHYS_TO_K0SEG(x))
! 62:
! 63: struct tc_slotdesc tc_3000_500_slots[] = {
! 64: { KV(0x100000000), C(TC_3000_500_DEV_OPT0), }, /* 0 - opt slot 0 */
! 65: { KV(0x120000000), C(TC_3000_500_DEV_OPT1), }, /* 1 - opt slot 1 */
! 66: { KV(0x140000000), C(TC_3000_500_DEV_OPT2), }, /* 2 - opt slot 2 */
! 67: { KV(0x160000000), C(TC_3000_500_DEV_OPT3), }, /* 3 - opt slot 3 */
! 68: { KV(0x180000000), C(TC_3000_500_DEV_OPT4), }, /* 4 - opt slot 4 */
! 69: { KV(0x1a0000000), C(TC_3000_500_DEV_OPT5), }, /* 5 - opt slot 5 */
! 70: { KV(0x1c0000000), C(TC_3000_500_DEV_BOGUS), }, /* 6 - TCDS ASIC */
! 71: { KV(0x1e0000000), C(TC_3000_500_DEV_BOGUS), }, /* 7 - IOCTL ASIC */
! 72: };
! 73: int tc_3000_500_nslots =
! 74: sizeof(tc_3000_500_slots) / sizeof(tc_3000_500_slots[0]);
! 75:
! 76: struct tc_builtin tc_3000_500_graphics_builtins[] = {
! 77: { "FLAMG-IO", 7, 0x00000000, C(TC_3000_500_DEV_IOASIC), },
! 78: { "PMAGB-BA", 7, 0x02000000, C(TC_3000_500_DEV_CXTURBO), },
! 79: { "PMAZ-DS ", 6, 0x00000000, C(TC_3000_500_DEV_TCDS), },
! 80: };
! 81: int tc_3000_500_graphics_nbuiltins = sizeof(tc_3000_500_graphics_builtins) /
! 82: sizeof(tc_3000_500_graphics_builtins[0]);
! 83:
! 84: struct tc_builtin tc_3000_500_nographics_builtins[] = {
! 85: { "FLAMG-IO", 7, 0x00000000, C(TC_3000_500_DEV_IOASIC), },
! 86: { "PMAZ-DS ", 6, 0x00000000, C(TC_3000_500_DEV_TCDS), },
! 87: };
! 88: int tc_3000_500_nographics_nbuiltins = sizeof(tc_3000_500_nographics_builtins) /
! 89: sizeof(tc_3000_500_nographics_builtins[0]);
! 90:
! 91: u_int32_t tc_3000_500_intrbits[TC_3000_500_NCOOKIES] = {
! 92: TC_3000_500_IR_OPT0,
! 93: TC_3000_500_IR_OPT1,
! 94: TC_3000_500_IR_OPT2,
! 95: TC_3000_500_IR_OPT3,
! 96: TC_3000_500_IR_OPT4,
! 97: TC_3000_500_IR_OPT5,
! 98: TC_3000_500_IR_TCDS,
! 99: TC_3000_500_IR_IOASIC,
! 100: TC_3000_500_IR_CXTURBO,
! 101: };
! 102:
! 103: struct tcintr {
! 104: int (*tci_func)(void *);
! 105: void *tci_arg;
! 106: struct evcount tci_count;
! 107: char tci_name[12];
! 108: } tc_3000_500_intr[TC_3000_500_NCOOKIES];
! 109:
! 110: u_int32_t tc_3000_500_imask; /* intrs we want to ignore; mirrors IMR. */
! 111:
! 112: void
! 113: tc_3000_500_intr_setup()
! 114: {
! 115: u_long i;
! 116:
! 117: /*
! 118: * Disable all slot interrupts. Note that this cannot
! 119: * actually disable CXTurbo, TCDS, and IOASIC interrupts.
! 120: */
! 121: tc_3000_500_imask = *(volatile u_int32_t *)TC_3000_500_IMR_READ;
! 122: for (i = 0; i < TC_3000_500_NCOOKIES; i++)
! 123: tc_3000_500_imask |= tc_3000_500_intrbits[i];
! 124: *(volatile u_int32_t *)TC_3000_500_IMR_WRITE = tc_3000_500_imask;
! 125: tc_mb();
! 126:
! 127: /*
! 128: * Set up interrupt handlers.
! 129: */
! 130: for (i = 0; i < TC_3000_500_NCOOKIES; i++) {
! 131: tc_3000_500_intr[i].tci_func = tc_3000_500_intrnull;
! 132: tc_3000_500_intr[i].tci_arg = (void *)i;
! 133: snprintf(tc_3000_500_intr[i].tci_name,
! 134: sizeof tc_3000_500_intr[i].tci_name, "tc slot %u", i);
! 135: evcount_attach(&tc_3000_500_intr[i].tci_count,
! 136: tc_3000_500_intr[i].tci_name, NULL, &evcount_intr);
! 137: }
! 138: }
! 139:
! 140: void
! 141: tc_3000_500_intr_establish(tcadev, cookie, level, func, arg)
! 142: struct device *tcadev;
! 143: void *cookie, *arg;
! 144: tc_intrlevel_t level;
! 145: int (*func)(void *);
! 146: {
! 147: u_long dev = (u_long)cookie;
! 148:
! 149: #ifdef DIAGNOSTIC
! 150: /* XXX bounds-check cookie. */
! 151: #endif
! 152:
! 153: if (tc_3000_500_intr[dev].tci_func != tc_3000_500_intrnull)
! 154: panic("tc_3000_500_intr_establish: cookie %lu twice", dev);
! 155:
! 156: tc_3000_500_intr[dev].tci_func = func;
! 157: tc_3000_500_intr[dev].tci_arg = arg;
! 158:
! 159: tc_3000_500_imask &= ~tc_3000_500_intrbits[dev];
! 160: *(volatile u_int32_t *)TC_3000_500_IMR_WRITE = tc_3000_500_imask;
! 161: tc_mb();
! 162: }
! 163:
! 164: void
! 165: tc_3000_500_intr_disestablish(tcadev, cookie)
! 166: struct device *tcadev;
! 167: void *cookie;
! 168: {
! 169: u_long dev = (u_long)cookie;
! 170:
! 171: #ifdef DIAGNOSTIC
! 172: /* XXX bounds-check cookie. */
! 173: #endif
! 174:
! 175: if (tc_3000_500_intr[dev].tci_func == tc_3000_500_intrnull)
! 176: panic("tc_3000_500_intr_disestablish: cookie %lu bad intr",
! 177: dev);
! 178:
! 179: tc_3000_500_imask |= tc_3000_500_intrbits[dev];
! 180: *(volatile u_int32_t *)TC_3000_500_IMR_WRITE = tc_3000_500_imask;
! 181: tc_mb();
! 182:
! 183: tc_3000_500_intr[dev].tci_func = tc_3000_500_intrnull;
! 184: tc_3000_500_intr[dev].tci_arg = (void *)dev;
! 185: }
! 186:
! 187: int
! 188: tc_3000_500_intrnull(val)
! 189: void *val;
! 190: {
! 191:
! 192: panic("tc_3000_500_intrnull: uncaught TC intr for cookie %ld",
! 193: (u_long)val);
! 194: }
! 195:
! 196: void
! 197: tc_3000_500_iointr(arg, vec)
! 198: void *arg;
! 199: unsigned long vec;
! 200: {
! 201: u_int32_t ir;
! 202: int ifound;
! 203:
! 204: #ifdef DIAGNOSTIC
! 205: int s;
! 206: if (vec != 0x800)
! 207: panic("INVALID ASSUMPTION: vec 0x%lx, not 0x800", vec);
! 208: s = splhigh();
! 209: if (s != ALPHA_PSL_IPL_IO)
! 210: panic("INVALID ASSUMPTION: IPL %d, not %d", s,
! 211: ALPHA_PSL_IPL_IO);
! 212: splx(s);
! 213: #endif
! 214:
! 215: do {
! 216: tc_syncbus();
! 217: ir = *(volatile u_int32_t *)TC_3000_500_IR_CLEAR;
! 218:
! 219: /* Ignore interrupts that we haven't enabled. */
! 220: ir &= ~(tc_3000_500_imask & 0x1ff);
! 221:
! 222: ifound = 0;
! 223:
! 224: #define CHECKINTR(slot) \
! 225: if (ir & tc_3000_500_intrbits[slot]) { \
! 226: ifound = 1; \
! 227: tc_3000_500_intr[slot].tci_count.ec_count++; \
! 228: (*tc_3000_500_intr[slot].tci_func) \
! 229: (tc_3000_500_intr[slot].tci_arg); \
! 230: }
! 231: /* Do them in order of priority; highest slot # first. */
! 232: CHECKINTR(TC_3000_500_DEV_CXTURBO);
! 233: CHECKINTR(TC_3000_500_DEV_IOASIC);
! 234: CHECKINTR(TC_3000_500_DEV_TCDS);
! 235: CHECKINTR(TC_3000_500_DEV_OPT5);
! 236: CHECKINTR(TC_3000_500_DEV_OPT4);
! 237: CHECKINTR(TC_3000_500_DEV_OPT3);
! 238: CHECKINTR(TC_3000_500_DEV_OPT2);
! 239: CHECKINTR(TC_3000_500_DEV_OPT1);
! 240: CHECKINTR(TC_3000_500_DEV_OPT0);
! 241: #undef CHECKINTR
! 242:
! 243: #ifdef DIAGNOSTIC
! 244: #define PRINTINTR(msg, bits) \
! 245: if (ir & bits) \
! 246: printf(msg);
! 247: PRINTINTR("Second error occurred\n", TC_3000_500_IR_ERR2);
! 248: PRINTINTR("DMA buffer error\n", TC_3000_500_IR_DMABE);
! 249: PRINTINTR("DMA cross 2K boundary\n", TC_3000_500_IR_DMA2K);
! 250: PRINTINTR("TC reset in progress\n", TC_3000_500_IR_TCRESET);
! 251: PRINTINTR("TC parity error\n", TC_3000_500_IR_TCPAR);
! 252: PRINTINTR("DMA tag error\n", TC_3000_500_IR_DMATAG);
! 253: PRINTINTR("Single-bit error\n", TC_3000_500_IR_DMASBE);
! 254: PRINTINTR("Double-bit error\n", TC_3000_500_IR_DMADBE);
! 255: PRINTINTR("TC I/O timeout\n", TC_3000_500_IR_TCTIMEOUT);
! 256: PRINTINTR("DMA block too long\n", TC_3000_500_IR_DMABLOCK);
! 257: PRINTINTR("Invalid I/O address\n", TC_3000_500_IR_IOADDR);
! 258: PRINTINTR("DMA scatter/gather invalid\n", TC_3000_500_IR_DMASG);
! 259: PRINTINTR("Scatter/gather parity error\n",
! 260: TC_3000_500_IR_SGPAR);
! 261: #undef PRINTINTR
! 262: #endif
! 263: } while (ifound);
! 264: }
! 265:
! 266: #if NWSDISPLAY > 0
! 267: /*
! 268: * tc_3000_500_fb_cnattach --
! 269: * Attempt to map the CTB output device to a slot and attach the
! 270: * framebuffer as the output side of the console.
! 271: */
! 272: int
! 273: tc_3000_500_fb_cnattach(turbo_slot)
! 274: u_int64_t turbo_slot;
! 275: {
! 276: u_int32_t output_slot;
! 277:
! 278: output_slot = turbo_slot & 0xffffffff;
! 279:
! 280: if (output_slot >= tc_3000_500_nslots) {
! 281: return EINVAL;
! 282: }
! 283:
! 284: if (hwrpb->rpb_variation & SV_GRAPHICS) {
! 285: if (output_slot == 0) {
! 286: #if NSFB > 0
! 287: sfb_cnattach(KV(0x1e0000000) + 0x02000000);
! 288: return 0;
! 289: #else
! 290: return ENXIO;
! 291: #endif
! 292: }
! 293: } else {
! 294: /*
! 295: * Slots 0-2 in the tc_3000_500_slots array are only
! 296: * on the 500 models that also have the CXTurbo
! 297: * (500/800/900) and a total of 6 TC slots. For the
! 298: * 400/600/700, slots 0-2 are in table locations 3-5, so
! 299: * offset the CTB slot by 3 to get the address in our table.
! 300: */
! 301: output_slot += 3;
! 302: }
! 303: return tc_fb_cnattach(tc_3000_500_slots[output_slot-1].tcs_addr);
! 304: }
! 305: #endif /* NWSDISPLAY */
! 306:
! 307: #if 0
! 308: /*
! 309: * tc_3000_500_ioslot --
! 310: * Set the PBS bits for devices on the TC.
! 311: */
! 312: void
! 313: tc_3000_500_ioslot(slot, flags, set)
! 314: u_int32_t slot, flags;
! 315: int set;
! 316: {
! 317: volatile u_int32_t *iosp;
! 318: u_int32_t ios;
! 319: int s;
! 320:
! 321: iosp = (volatile u_int32_t *)TC_3000_500_IOSLOT;
! 322: ios = *iosp;
! 323: flags <<= (slot * 3);
! 324: if (set)
! 325: ios |= flags;
! 326: else
! 327: ios &= ~flags;
! 328: s = splhigh();
! 329: *iosp = ios;
! 330: tc_mb();
! 331: splx(s);
! 332: }
! 333: #endif
CVSweb