1 /* $NetBSD: dec_3maxplus.c,v 1.58 2008/01/03 23:02:24 joerg 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) 1992, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * This code is derived from software contributed to Berkeley by 38 * the Systems Programming Group of the University of Utah Computer 39 * Science Department, The Mach Operating System project at 40 * Carnegie-Mellon University and Ralph Campbell. 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above copyright 48 * notice, this list of conditions and the following disclaimer in the 49 * documentation and/or other materials provided with the distribution. 50 * 3. Neither the name of the University nor the names of its contributors 51 * may be used to endorse or promote products derived from this software 52 * without specific prior written permission. 53 * 54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 64 * SUCH DAMAGE. 65 * 66 * @(#)machdep.c 8.3 (Berkeley) 1/12/94 67 */ 68 /* 69 * Copyright (c) 1988 University of Utah. 70 * 71 * This code is derived from software contributed to Berkeley by 72 * the Systems Programming Group of the University of Utah Computer 73 * Science Department, The Mach Operating System project at 74 * Carnegie-Mellon University and Ralph Campbell. 75 * 76 * Redistribution and use in source and binary forms, with or without 77 * modification, are permitted provided that the following conditions 78 * are met: 79 * 1. Redistributions of source code must retain the above copyright 80 * notice, this list of conditions and the following disclaimer. 81 * 2. Redistributions in binary form must reproduce the above copyright 82 * notice, this list of conditions and the following disclaimer in the 83 * documentation and/or other materials provided with the distribution. 84 * 3. All advertising materials mentioning features or use of this software 85 * must display the following acknowledgement: 86 * This product includes software developed by the University of 87 * California, Berkeley and its contributors. 88 * 4. Neither the name of the University nor the names of its contributors 89 * may be used to endorse or promote products derived from this software 90 * without specific prior written permission. 91 * 92 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 93 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 94 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 95 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 96 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 97 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 98 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 99 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 100 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 101 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 102 * SUCH DAMAGE. 103 * 104 * @(#)machdep.c 8.3 (Berkeley) 1/12/94 105 */ 106 107 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 108 109 __KERNEL_RCSID(0, "$NetBSD: dec_3maxplus.c,v 1.58 2008/01/03 23:02:24 joerg Exp $"); 110 111 #include <sys/param.h> 112 #include <sys/systm.h> 113 #include <sys/device.h> 114 #include <sys/timetc.h> 115 116 #include <machine/cpu.h> 117 #include <machine/sysconf.h> 118 119 #include <mips/mips/mips_mcclock.h> /* mclock CPUspeed estimation */ 120 121 /* all these to get ioasic_base */ 122 #include <dev/tc/tcvar.h> /* tc type definitions for.. */ 123 #include <dev/tc/ioasicreg.h> /* ioasic interrrupt masks */ 124 #include <dev/tc/ioasicvar.h> /* ioasic_base */ 125 126 #include <pmax/pmax/machdep.h> 127 #include <pmax/pmax/kn03.h> 128 #include <pmax/pmax/memc.h> 129 130 #include <dev/ic/z8530sc.h> 131 #include <dev/tc/zs_ioasicvar.h> 132 #include <pmax/pmax/cons.h> 133 #include "wsdisplay.h" 134 135 void dec_3maxplus_init __P((void)); /* XXX */ 136 static void dec_3maxplus_bus_reset __P((void)); 137 static void dec_3maxplus_cons_init __P((void)); 138 static void dec_3maxplus_errintr __P((void)); 139 static void dec_3maxplus_intr __P((unsigned, unsigned, unsigned, unsigned)); 140 static void dec_3maxplus_intr_establish __P((struct device *, void *, 141 int, int (*)(void *), void *)); 142 143 static void kn03_wbflush __P((void)); 144 145 static void dec_3maxplus_tc_init(void); 146 147 /* 148 * Local declarations 149 */ 150 static u_int32_t kn03_tc3_imask; 151 static unsigned latched_cycle_cnt; 152 153 static const int dec_3maxplus_ipl2spl_table[] = { 154 [IPL_NONE] = 0, 155 [IPL_SOFTCLOCK] = _SPL_SOFTCLOCK, 156 [IPL_SOFTNET] = _SPL_SOFTNET, 157 /* 158 * 3MAX+ IOASIC interrupts come through INT 0, while 159 * clock interrupt does via INT 1. splclock and splstatclock 160 * should block IOASIC activities. 161 */ 162 [IPL_VM] = MIPS_SPL0, 163 [IPL_SCHED] = MIPS_SPL_0_1, 164 [IPL_HIGH] = MIPS_SPL_0_1, 165 }; 166 167 void 168 dec_3maxplus_init() 169 { 170 u_int32_t prodtype; 171 172 platform.iobus = "tcbus"; 173 platform.bus_reset = dec_3maxplus_bus_reset; 174 platform.cons_init = dec_3maxplus_cons_init; 175 platform.iointr = dec_3maxplus_intr; 176 platform.intr_establish = dec_3maxplus_intr_establish; 177 platform.memsize = memsize_bitmap; 178 /* 3MAX+ has IOASIC free-running high resolution timer */ 179 platform.tc_init = dec_3maxplus_tc_init; 180 181 /* clear any memory errors */ 182 *(u_int32_t *)MIPS_PHYS_TO_KSEG1(KN03_SYS_ERRADR) = 0; 183 kn03_wbflush(); 184 185 ioasic_base = MIPS_PHYS_TO_KSEG1(KN03_SYS_ASIC); 186 187 ipl2spl_table = dec_3maxplus_ipl2spl_table; 188 189 /* calibrate cpu_mhz value */ 190 mc_cpuspeed(ioasic_base+IOASIC_SLOT_8_START, MIPS_INT_MASK_1); 191 192 *(u_int32_t *)(ioasic_base + IOASIC_LANCE_DECODE) = 0x3; 193 *(u_int32_t *)(ioasic_base + IOASIC_SCSI_DECODE) = 0xe; 194 #if 0 195 *(u_int32_t *)(ioasic_base + IOASIC_SCC0_DECODE) = (0x10|4); 196 *(u_int32_t *)(ioasic_base + IOASIC_SCC1_DECODE) = (0x10|6); 197 *(u_int32_t *)(ioasic_base + IOASIC_CSR) = 0x00000f00; 198 #endif 199 200 /* XXX hard-reset LANCE */ 201 *(u_int32_t *)(ioasic_base + IOASIC_CSR) |= 0x100; 202 203 /* sanitize interrupt mask */ 204 kn03_tc3_imask = KN03_INTR_PSWARN; 205 *(u_int32_t *)(ioasic_base + IOASIC_INTR) = 0; 206 *(u_int32_t *)(ioasic_base + IOASIC_IMSK) = kn03_tc3_imask; 207 kn03_wbflush(); 208 209 prodtype = *(u_int32_t *)MIPS_PHYS_TO_KSEG1(KN03_REG_INTR); 210 prodtype &= KN03_INTR_PROD_JUMPER; 211 /* the bit persists even if INTR register is assigned value 0 */ 212 if (prodtype) 213 sprintf(cpu_model, "DECstation 5000/%s (3MAXPLUS)", 214 (CPUISMIPS3) ? "260" : "240"); 215 else 216 sprintf(cpu_model, "DECsystem 5900%s (3MAXPLUS)", 217 (CPUISMIPS3) ? "-260" : ""); 218 } 219 220 /* 221 * Initialize the memory system and I/O buses. 222 */ 223 static void 224 dec_3maxplus_bus_reset() 225 { 226 /* 227 * Reset interrupts, clear any errors from newconf probes 228 */ 229 230 *(u_int32_t *)MIPS_PHYS_TO_KSEG1(KN03_SYS_ERRADR) = 0; 231 kn03_wbflush(); 232 233 *(u_int32_t *)(ioasic_base + IOASIC_INTR) = 0; 234 kn03_wbflush(); 235 } 236 237 static void 238 dec_3maxplus_cons_init() 239 { 240 int kbd, crt, screen; 241 242 kbd = crt = screen = 0; 243 prom_findcons(&kbd, &crt, &screen); 244 245 if (screen > 0) { 246 #if NWSDISPLAY > 0 247 if (tcfb_cnattach(crt) > 0) { 248 zs_ioasic_lk201_cnattach(ioasic_base, 0x180000, 0); 249 return; 250 } 251 #endif 252 printf("No framebuffer device configured for slot %d: ", crt); 253 printf("using serial console\n"); 254 } 255 /* 256 * Delay to allow PROM putchars to complete. 257 * FIFO depth * character time, 258 * character time = (1000000 / (defaultrate / 10)) 259 */ 260 DELAY(160000000 / 9600); /* XXX */ 261 262 zs_ioasic_cnattach(ioasic_base, 0x180000, 1); 263 } 264 265 static void 266 dec_3maxplus_intr_establish(dev, cookie, level, handler, arg) 267 struct device *dev; 268 void *cookie; 269 int level; 270 int (*handler) __P((void *)); 271 void *arg; 272 { 273 unsigned mask; 274 275 switch ((int)cookie) { 276 case SYS_DEV_OPT0: 277 mask = KN03_INTR_TC_0; 278 break; 279 case SYS_DEV_OPT1: 280 mask = KN03_INTR_TC_1; 281 break; 282 case SYS_DEV_OPT2: 283 mask = KN03_INTR_TC_2; 284 break; 285 case SYS_DEV_SCSI: 286 mask = (IOASIC_INTR_SCSI | IOASIC_INTR_SCSI_PTR_LOAD | 287 IOASIC_INTR_SCSI_OVRUN | IOASIC_INTR_SCSI_READ_E); 288 break; 289 case SYS_DEV_LANCE: 290 mask = KN03_INTR_LANCE | IOASIC_INTR_LANCE_READ_E; 291 break; 292 case SYS_DEV_SCC0: 293 mask = KN03_INTR_SCC_0; 294 break; 295 case SYS_DEV_SCC1: 296 mask = KN03_INTR_SCC_1; 297 break; 298 default: 299 #ifdef DIAGNOSTIC 300 printf("warning: enabling unknown intr %x\n", (int)cookie); 301 #endif 302 return; 303 } 304 305 kn03_tc3_imask |= mask; 306 intrtab[(int)cookie].ih_func = handler; 307 intrtab[(int)cookie].ih_arg = arg; 308 309 *(u_int32_t *)(ioasic_base + IOASIC_IMSK) = kn03_tc3_imask; 310 kn03_wbflush(); 311 } 312 313 #define CHECKINTR(vvv, bits) \ 314 do { \ 315 if (can_serve & (bits)) { \ 316 ifound = 1; \ 317 intrtab[vvv].ih_count.ev_count++; \ 318 (*intrtab[vvv].ih_func)(intrtab[vvv].ih_arg); \ 319 } \ 320 } while (0) 321 322 static void 323 dec_3maxplus_intr(status, cause, pc, ipending) 324 unsigned status; 325 unsigned cause; 326 unsigned pc; 327 unsigned ipending; 328 { 329 static int warned = 0; 330 unsigned old_buscycle; 331 332 if (ipending & MIPS_INT_MASK_4) 333 prom_haltbutton(); 334 335 /* handle clock interrupts ASAP */ 336 old_buscycle = latched_cycle_cnt; 337 if (ipending & MIPS_INT_MASK_1) { 338 struct clockframe cf; 339 340 __asm volatile("lbu $0,48(%0)" :: 341 "r"(ioasic_base + IOASIC_SLOT_8_START)); 342 cf.pc = pc; 343 cf.sr = status; 344 hardclock(&cf); 345 pmax_clock_evcnt.ev_count++; 346 old_buscycle = latched_cycle_cnt - old_buscycle; 347 /* keep clock interrupts enabled when we return */ 348 cause &= ~MIPS_INT_MASK_1; 349 } 350 351 /* If clock interrupts were enabled, re-enable them ASAP. */ 352 _splset(MIPS_SR_INT_IE | (status & MIPS_INT_MASK_1)); 353 354 #ifdef notdef 355 /* 356 * Check for late clock interrupts (allow 10% slop). Be careful 357 * to do so only after calling hardclock(), due to logging cost. 358 * Even then, logging dropped ticks just causes more clock 359 * ticks to be missed. 360 */ 361 if ((ipending & MIPS_INT_MASK_1) && old_buscycle > (tick+49) * 25) { 362 /* XXX need to include <sys/msgbug.h> for msgbufmapped */ 363 if (msgbufmapped && 0) 364 addlog("kn03: clock intr %d usec late\n", 365 old_buscycle/25); 366 } 367 #endif 368 if (ipending & MIPS_INT_MASK_0) { 369 int ifound; 370 u_int32_t imsk, intr, can_serve, xxxintr; 371 372 do { 373 ifound = 0; 374 imsk = *(u_int32_t *)(ioasic_base + IOASIC_IMSK); 375 intr = *(u_int32_t *)(ioasic_base + IOASIC_INTR); 376 can_serve = intr & imsk; 377 378 CHECKINTR(SYS_DEV_SCC0, IOASIC_INTR_SCC_0); 379 CHECKINTR(SYS_DEV_SCC1, IOASIC_INTR_SCC_1); 380 CHECKINTR(SYS_DEV_LANCE, IOASIC_INTR_LANCE); 381 CHECKINTR(SYS_DEV_SCSI, IOASIC_INTR_SCSI); 382 CHECKINTR(SYS_DEV_OPT2, KN03_INTR_TC_2); 383 CHECKINTR(SYS_DEV_OPT1, KN03_INTR_TC_1); 384 CHECKINTR(SYS_DEV_OPT0, KN03_INTR_TC_0); 385 386 if (warned > 0 && !(can_serve & KN03_INTR_PSWARN)) { 387 printf("%s\n", "Power supply ok now."); 388 warned = 0; 389 } 390 if ((can_serve & KN03_INTR_PSWARN) && (warned < 3)) { 391 warned++; 392 printf("%s\n", "Power supply overheating"); 393 } 394 395 #define ERRORS (IOASIC_INTR_SCSI_OVRUN|IOASIC_INTR_SCSI_READ_E|IOASIC_INTR_LANCE_READ_E) 396 #define PTRLOAD (IOASIC_INTR_SCSI_PTR_LOAD) 397 /* 398 * XXX future project is here XXX 399 * IOASIC DMA completion interrupt (PTR_LOAD) should be checked 400 * here, and DMA pointers serviced as soon as possible. 401 */ 402 /* 403 * All of IOASIC device interrupts comes through a single service 404 * request line coupled with MIPS CPU INT 0. 405 * Disabling INT 0 makes entire IOASIC interrupt services blocked, 406 * and it's harmful because it causes DMA overruns during network 407 * disk I/O interrupts. 408 * So, Non-DMA interrupts should be selectively disabled by masking 409 * IOASIC_IMSK register, and INT 3 itself be reenabled immediately, 410 * and made available all the time. 411 * DMA interrupts can then be serviced whilst still servicing 412 * non-DMA interrupts from ioctl devices or TC options. 413 */ 414 xxxintr = can_serve & (ERRORS | PTRLOAD); 415 if (xxxintr) { 416 ifound = 1; 417 *(u_int32_t *)(ioasic_base + IOASIC_INTR) 418 = intr &~ xxxintr; 419 } 420 } while (ifound); 421 } 422 if (ipending & MIPS_INT_MASK_3) { 423 dec_3maxplus_errintr(); 424 pmax_memerr_evcnt.ev_count++; 425 } 426 427 _splset(MIPS_SR_INT_IE | (status & ~cause & MIPS_HARD_INT_MASK)); 428 } 429 430 /* 431 * Handle Memory error. 3max, 3maxplus has ECC. 432 * Correct single-bit error, panic on double-bit error. 433 * XXX on double-error on clean user page, mark bad and reload frame? 434 */ 435 static void 436 dec_3maxplus_errintr() 437 { 438 u_int32_t erradr, errsyn, csr; 439 440 /* Fetch error address, ECC chk/syn bits, clear interrupt */ 441 erradr = *(u_int32_t *)MIPS_PHYS_TO_KSEG1(KN03_SYS_ERRADR); 442 errsyn = MIPS_PHYS_TO_KSEG1(KN03_SYS_ERRSYN); 443 *(u_int32_t *)MIPS_PHYS_TO_KSEG1(KN03_SYS_ERRADR) = 0; 444 kn03_wbflush(); 445 csr = *(u_int32_t *)MIPS_PHYS_TO_KSEG1(KN03_SYS_CSR); 446 447 /* Send to kn02/kn03 memory subsystem handler */ 448 dec_mtasic_err(erradr, errsyn, csr & KN03_CSR_BNK32M); 449 } 450 451 static void 452 kn03_wbflush() 453 { 454 /* read once IOASIC SLOT 0 */ 455 __asm volatile("lw $0,%0" :: "i"(0xbf840000)); 456 } 457 458 /* 459 * TURBOchannel bus-cycle counter provided by IOASIC; 25 MHz 460 */ 461 462 static unsigned 463 dec_3maxplus_get_timecount(struct timecounter *tc) 464 { 465 return *(u_int32_t*)(ioasic_base + IOASIC_CTR); 466 } 467 468 static void 469 dec_3maxplus_tc_init(void) 470 { 471 static struct timecounter tc = { 472 .tc_get_timecount = dec_3maxplus_get_timecount, 473 .tc_quality = 100, 474 .tc_frequency = 25000000, 475 .tc_counter_mask = ~0, 476 .tc_name = "turbochannel_counter", 477 }; 478 479 tc_init(&tc); 480 } 481