1 /* $NetBSD: dec_maxine.c,v 1.40 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 33 /* 34 * Copyright (c) 1988 University of Utah. 35 * Copyright (c) 1992, 1993 36 * The Regents of the University of California. All rights reserved. 37 * 38 * This code is derived from software contributed to Berkeley by 39 * the Systems Programming Group of the University of Utah Computer 40 * Science Department, The Mach Operating System project at 41 * Carnegie-Mellon University and Ralph Campbell. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * 1. Redistributions of source code must retain the above copyright 47 * notice, this list of conditions and the following disclaimer. 48 * 2. Redistributions in binary form must reproduce the above copyright 49 * notice, this list of conditions and the following disclaimer in the 50 * documentation and/or other materials provided with the distribution. 51 * 3. All advertising materials mentioning features or use of this software 52 * must display the following acknowledgement: 53 * This product includes software developed by the University of 54 * California, Berkeley and its contributors. 55 * 4. Neither the name of the University nor the names of its contributors 56 * may be used to endorse or promote products derived from this software 57 * without specific prior written permission. 58 * 59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 69 * SUCH DAMAGE. 70 * 71 * @(#)machdep.c 8.3 (Berkeley) 1/12/94 72 */ 73 74 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 75 76 __KERNEL_RCSID(0, "$NetBSD: dec_maxine.c,v 1.40 2001/09/18 16:15:20 tsutsui Exp $"); 77 78 #include <sys/param.h> 79 #include <sys/systm.h> 80 #include <sys/device.h> 81 82 #include <machine/cpu.h> 83 #include <machine/sysconf.h> 84 #include <mips/mips/mips_mcclock.h> 85 86 #include <dev/tc/tcvar.h> 87 #include <dev/tc/ioasicvar.h> 88 #include <dev/tc/ioasicreg.h> 89 90 #include <pmax/pmax/maxine.h> 91 #include <pmax/pmax/machdep.h> 92 #include <pmax/pmax/memc.h> 93 94 #include <pmax/dev/xcfbvar.h> 95 #include <pmax/dev/dtopvar.h> 96 #include <pmax/tc/sccvar.h> 97 98 #include "rasterconsole.h" 99 #include "xcfb.h" 100 101 void dec_maxine_init __P((void)); /* XXX */ 102 static void dec_maxine_bus_reset __P((void)); 103 static void dec_maxine_cons_init __P((void)); 104 static void dec_maxine_intr __P((unsigned, unsigned, unsigned, unsigned)); 105 static void dec_maxine_intr_establish __P((struct device *, void *, 106 int, int (*)(void *), void *)); 107 108 static void kn02ca_wbflush __P((void)); 109 static unsigned kn02ca_clkread __P((void)); 110 111 /* 112 * local declarations 113 */ 114 static u_int32_t xine_tc3_imask; 115 static unsigned latched_cycle_cnt; 116 117 118 void 119 dec_maxine_init() 120 { 121 platform.iobus = "tcbus"; 122 platform.bus_reset = dec_maxine_bus_reset; 123 platform.cons_init = dec_maxine_cons_init; 124 platform.iointr = dec_maxine_intr; 125 platform.intr_establish = dec_maxine_intr_establish; 126 platform.memsize = memsize_bitmap; 127 platform.clkread = kn02ca_clkread; 128 /* MAXINE has 1 microsec. free-running high resolution timer */ 129 130 /* clear any memory errors */ 131 *(u_int32_t *)MIPS_PHYS_TO_KSEG1(XINE_REG_TIMEOUT) = 0; 132 kn02ca_wbflush(); 133 134 ioasic_base = MIPS_PHYS_TO_KSEG1(XINE_SYS_ASIC); 135 136 /* 137 * MAXINE IOASIC interrupts come through INT 3, while 138 * clock interrupt does via INT 1. splclock and splstatclock 139 * should block IOASIC activities. 140 */ 141 splvec.splbio = MIPS_SPL3; 142 splvec.splnet = MIPS_SPL3; 143 splvec.spltty = MIPS_SPL3; 144 splvec.splvm = MIPS_SPL3; 145 splvec.splclock = MIPS_SPL_0_1_3; 146 splvec.splstatclock = MIPS_SPL_0_1_3; 147 148 /* calibrate cpu_mhz value */ 149 mc_cpuspeed(ioasic_base+IOASIC_SLOT_8_START, MIPS_INT_MASK_1); 150 151 *(u_int32_t *)(ioasic_base + IOASIC_LANCE_DECODE) = 0x3; 152 *(u_int32_t *)(ioasic_base + IOASIC_SCSI_DECODE) = 0xe; 153 #if 0 154 *(u_int32_t *)(ioasic_base + IOASIC_SCC0_DECODE) = (0x10|4); 155 *(u_int32_t *)(ioasic_base + IOASIC_DTOP_DECODE) = 10; 156 *(u_int32_t *)(ioasic_base + IOASIC_FLOPPY_DECODE) = 13; 157 *(u_int32_t *)(ioasic_base + IOASIC_CSR) = 0x00001fc1; 158 #endif 159 160 /* sanitize interrupt mask */ 161 xine_tc3_imask = 0; 162 *(u_int32_t *)(ioasic_base + IOASIC_INTR) = 0; 163 *(u_int32_t *)(ioasic_base + IOASIC_IMSK) = xine_tc3_imask; 164 kn02ca_wbflush(); 165 166 sprintf(cpu_model, "Personal DECstation 5000/%d (MAXINE)", cpu_mhz); 167 } 168 169 /* 170 * Initialize the memory system and I/O buses. 171 */ 172 static void 173 dec_maxine_bus_reset() 174 { 175 /* 176 * Reset interrupts, clear any errors from newconf probes 177 */ 178 179 *(u_int32_t *)MIPS_PHYS_TO_KSEG1(XINE_REG_TIMEOUT) = 0; 180 kn02ca_wbflush(); 181 182 *(u_int32_t *)(ioasic_base + IOASIC_INTR) = 0; 183 kn02ca_wbflush(); 184 } 185 186 187 static void 188 dec_maxine_cons_init() 189 { 190 int kbd, crt, screen; 191 extern int tcfb_cnattach __P((int)); /* XXX */ 192 193 kbd = crt = screen = 0; 194 prom_findcons(&kbd, &crt, &screen); 195 196 if (screen > 0) { 197 #if NRASTERCONSOLE > 0 198 if (crt == 3) { 199 #if NXCFB > 0 200 xcfb_cnattach(); 201 dtikbd_cnattach(); 202 return; 203 #endif 204 } 205 else if (tcfb_cnattach(crt) > 0) { 206 dtikbd_cnattach(); 207 return; 208 } 209 #endif 210 printf("No framebuffer device configured for slot %d: ", crt); 211 printf("using serial console\n"); 212 } 213 /* 214 * Delay to allow PROM putchars to complete. 215 * FIFO depth * character time, 216 * character time = (1000000 / (defaultrate / 10)) 217 */ 218 DELAY(160000000 / 9600); /* XXX */ 219 220 scc_cnattach(ioasic_base, 0x100000); 221 } 222 223 static void 224 dec_maxine_intr_establish(dev, cookie, level, handler, arg) 225 struct device *dev; 226 void *cookie; 227 int level; 228 int (*handler) __P((void *)); 229 void *arg; 230 { 231 unsigned mask; 232 233 switch ((int)cookie) { 234 case SYS_DEV_OPT0: 235 mask = XINE_INTR_TC_0; 236 break; 237 case SYS_DEV_OPT1: 238 mask = XINE_INTR_TC_1; 239 break; 240 case SYS_DEV_FDC: 241 mask = XINE_INTR_FLOPPY; 242 break; 243 case SYS_DEV_SCSI: 244 mask = (IOASIC_INTR_SCSI | IOASIC_INTR_SCSI_PTR_LOAD | 245 IOASIC_INTR_SCSI_OVRUN | IOASIC_INTR_SCSI_READ_E); 246 break; 247 case SYS_DEV_LANCE: 248 mask = IOASIC_INTR_LANCE; 249 break; 250 case SYS_DEV_SCC0: 251 mask = IOASIC_INTR_SCC_0; 252 break; 253 case SYS_DEV_DTOP: 254 mask = XINE_INTR_DTOP_RX; 255 break; 256 case SYS_DEV_ISDN: 257 mask = (IOASIC_INTR_ISDN_TXLOAD | IOASIC_INTR_ISDN_RXLOAD | 258 IOASIC_INTR_ISDN_OVRUN); 259 break; 260 default: 261 #ifdef DIAGNOSTIC 262 printf("warning: enabling unknown intr %x\n", (int)cookie); 263 #endif 264 return; 265 } 266 267 xine_tc3_imask |= mask; 268 intrtab[(int)cookie].ih_func = handler; 269 intrtab[(int)cookie].ih_arg = arg; 270 271 *(u_int32_t *)(ioasic_base + IOASIC_IMSK) = xine_tc3_imask; 272 kn02ca_wbflush(); 273 } 274 275 #define CHECKINTR(vvv, bits) \ 276 do { \ 277 if (can_serve & (bits)) { \ 278 ifound = 1; \ 279 intrcnt[vvv] += 1; \ 280 (*intrtab[vvv].ih_func)(intrtab[vvv].ih_arg); \ 281 } \ 282 } while (0) 283 284 static void 285 dec_maxine_intr(status, cause, pc, ipending) 286 unsigned ipending; 287 unsigned pc; 288 unsigned status; 289 unsigned cause; 290 { 291 if (ipending & MIPS_INT_MASK_4) 292 prom_haltbutton(); 293 294 /* handle clock interrupts ASAP */ 295 if (ipending & MIPS_INT_MASK_1) { 296 struct clockframe cf; 297 298 __asm __volatile("lbu $0,48(%0)" :: 299 "r"(ioasic_base + IOASIC_SLOT_8_START)); 300 latched_cycle_cnt = 301 *(u_int32_t *)MIPS_PHYS_TO_KSEG1(XINE_REG_FCTR); 302 cf.pc = pc; 303 cf.sr = status; 304 hardclock(&cf); 305 pmax_clock_evcnt.ev_count++; 306 /* keep clock interrupts enabled when we return */ 307 cause &= ~MIPS_INT_MASK_1; 308 } 309 310 /* If clock interrups were enabled, re-enable them ASAP. */ 311 _splset(MIPS_SR_INT_IE | (status & MIPS_INT_MASK_1)); 312 313 if (ipending & MIPS_INT_MASK_3) { 314 int ifound; 315 u_int32_t imsk, intr, can_serve, xxxintr; 316 317 do { 318 ifound = 0; 319 intr = *(u_int32_t *)(ioasic_base + IOASIC_INTR); 320 imsk = *(u_int32_t *)(ioasic_base + IOASIC_IMSK); 321 can_serve = intr & imsk; 322 323 CHECKINTR(SYS_DEV_DTOP, XINE_INTR_DTOP); 324 CHECKINTR(SYS_DEV_SCC0, IOASIC_INTR_SCC_0); 325 CHECKINTR(SYS_DEV_LANCE, IOASIC_INTR_LANCE); 326 CHECKINTR(SYS_DEV_SCSI, IOASIC_INTR_SCSI); 327 /* CHECKINTR(SYS_DEV_OPT2, XINE_INTR_VINT); */ 328 CHECKINTR(SYS_DEV_ISDN, (IOASIC_INTR_ISDN_TXLOAD | IOASIC_INTR_ISDN_RXLOAD)); 329 /* CHECKINTR(SYS_DEV_FDC, IOASIC_INTR_FDC); */ 330 CHECKINTR(SYS_DEV_OPT1, XINE_INTR_TC_1); 331 CHECKINTR(SYS_DEV_OPT0, XINE_INTR_TC_0); 332 333 #define ERRORS (IOASIC_INTR_ISDN_OVRUN|IOASIC_INTR_SCSI_OVRUN|IOASIC_INTR_SCSI_READ_E|IOASIC_INTR_LANCE_READ_E) 334 #define PTRLOAD (IOASIC_INTR_ISDN_TXLOAD|IOASIC_INTR_ISDN_RXLOAD|IOASIC_INTR_SCSI_PTR_LOAD) 335 336 /* 337 * XXX future project is here XXX 338 * IOASIC DMA completion interrupt (PTR_LOAD) should be checked 339 * here, and DMA pointers serviced as soon as possible. 340 */ 341 /* 342 * All of IOASIC device interrupts comes through a single service 343 * request line coupled with MIPS cpu INT 3. 344 * Disabling INT 3 makes entire IOASIC interrupt services blocked, 345 * and it's harmful because it causes DMA overruns during network 346 * disk I/O interrupts. 347 * So, Non-DMA interrupts should be selectively disabled by masking 348 * IOASIC_IMSK register, and INT 3 itself be reenabled immediately, 349 * and made available all the time. 350 * DMA interrupts can then be serviced whilst still servicing 351 * non-DMA interrupts from ioctl devices or TC options. 352 */ 353 xxxintr = can_serve & (ERRORS | PTRLOAD); 354 if (xxxintr) { 355 ifound = 1; 356 *(u_int32_t *)(ioasic_base + IOASIC_INTR) 357 = intr &~ xxxintr; 358 } 359 } while (ifound); 360 } 361 if (ipending & MIPS_INT_MASK_2) { 362 kn02ba_errintr(); 363 pmax_memerr_evcnt.ev_count++; 364 } 365 366 _splset(MIPS_SR_INT_IE | (status & ~cause & MIPS_HARD_INT_MASK)); 367 } 368 369 static void 370 kn02ca_wbflush() 371 { 372 /* read once IOASIC_IMSK */ 373 __asm __volatile("lw $0,%0" :: 374 "i"(MIPS_PHYS_TO_KSEG1(XINE_REG_IMSK))); 375 } 376 377 static unsigned 378 kn02ca_clkread() 379 { 380 u_int32_t cycles; 381 382 cycles = *(u_int32_t *)MIPS_PHYS_TO_KSEG1(XINE_REG_FCTR); 383 return cycles - latched_cycle_cnt; 384 } 385