dec_3min.c revision 1.16
1/* $NetBSD: dec_3min.c,v 1.16 1999/05/25 04:17:57 nisimura 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_3min.c,v 1.16 1999/05/25 04:17:57 nisimura Exp $"); 77 78 79#include <sys/types.h> 80#include <sys/systm.h> 81 82#include <machine/cpu.h> 83#include <machine/intr.h> 84#include <machine/reg.h> 85#include <machine/psl.h> 86#include <machine/autoconf.h> /* intr_arg_t */ 87#include <machine/sysconf.h> 88 89#include <mips/mips_param.h> /* hokey spl()s */ 90#include <mips/mips/mips_mcclock.h> /* mcclock CPUspeed estimation */ 91 92/* all these to get ioasic_base */ 93#include <sys/device.h> /* struct cfdata for.. */ 94#include <dev/tc/tcvar.h> /* tc type definitions for.. */ 95#include <dev/tc/ioasicreg.h> /* ioasic interrrupt masks */ 96#include <dev/tc/ioasicvar.h> /* ioasic_base */ 97 98#include <pmax/pmax/clockreg.h> 99#include <pmax/pmax/turbochannel.h> 100#include <pmax/pmax/pmaxtype.h> 101 102#include <pmax/pmax/machdep.h> /* XXXjrs replace with vectors */ 103 104#include <pmax/pmax/kmin.h> /* 3min baseboard addresses */ 105#include <pmax/pmax/memc.h> /* 3min/maxine memory errors */ 106 107 108/* 109 * forward declarations 110 */ 111void dec_3min_init __P((void)); 112void dec_3min_os_init __P((void)); 113void dec_3min_bus_reset __P((void)); 114void dec_3maxplus_device_register __P((struct device *, void *)); 115 116void dec_3min_enable_intr 117 __P ((u_int slotno, int (*handler) __P((intr_arg_t sc)), 118 intr_arg_t sc, int onoff)); 119int dec_3min_intr __P((u_int mask, u_int pc, 120 u_int statusReg, u_int causeReg)); 121 122void dec_3min_device_register __P((struct device *, void *)); 123void dec_3min_cons_init __P((void)); 124 125 126/* 127 * Local declarations. 128 */ 129void dec_3min_mcclock_cpuspeed __P((volatile struct chiptime *mcclock_addr, 130 int clockmask)); 131u_long kmin_tc3_imask; 132 133void kn02ba_wbflush __P((void)); 134unsigned kn02ba_clkread __P((void)); 135extern unsigned (*clkread) __P((void)); 136 137/* 138 * Fill in platform struct. 139 */ 140void 141dec_3min_init() 142{ 143 platform.iobus = "tc3min"; 144 145 platform.os_init = dec_3min_os_init; 146 platform.bus_reset = dec_3min_bus_reset; 147 platform.cons_init = dec_3min_cons_init; 148 platform.device_register = dec_3min_device_register; 149 150 dec_3min_os_init(); 151 152 sprintf(cpu_model, "DECstation 5000/1%d (3MIN)", cpu_mhz); 153} 154 155 156/* 157 * Initalize the memory system and I/O buses. 158 */ 159void 160dec_3min_bus_reset() 161{ 162 163 /* 164 * Reset interrupts, clear any errors from newconf probes 165 */ 166 167 *(volatile u_int *)MIPS_PHYS_TO_KSEG1(KMIN_REG_TIMEOUT) = 0; 168 kn02ba_wbflush(); 169 170 *(volatile u_int *)IOASIC_REG_INTR(ioasic_base) = 0; 171 kn02ba_wbflush(); 172} 173 174 175void 176dec_3min_os_init() 177{ 178 ioasic_base = MIPS_PHYS_TO_KSEG1(KMIN_SYS_ASIC); 179 mips_hardware_intr = dec_3min_intr; 180 tc_enable_interrupt = dec_3min_enable_intr; 181 kmin_tc3_imask = (KMIN_INTR_CLOCK | KMIN_INTR_PSWARN | 182 KMIN_INTR_TIMEOUT); 183 mcclock_addr = (volatile struct chiptime *) 184 MIPS_PHYS_TO_KSEG1(KMIN_SYS_CLOCK); 185 186 /* R4000 3MIN can ultilize on-chip counter */ 187 clkread = kn02ba_clkread; 188 189 /* 190 * All the baseboard interrupts come through the I/O ASIC 191 * (at INT_MASK_3), so it has to be turned off for all the spls. 192 * Since we don't know what kinds of devices are in the 193 * turbochannel option slots, just block them all. 194 */ 195 splvec.splbio = MIPS_SPL_0_1_2_3; 196 splvec.splnet = MIPS_SPL_0_1_2_3; 197 splvec.spltty = MIPS_SPL_0_1_2_3; 198 splvec.splimp = MIPS_SPL_0_1_2_3; 199 splvec.splclock = MIPS_SPL_0_1_2_3; 200 splvec.splstatclock = MIPS_SPL_0_1_2_3; 201 202 dec_3min_mcclock_cpuspeed(mcclock_addr, MIPS_INT_MASK_3); 203 204 *(volatile u_int *)(ioasic_base + IOASIC_LANCE_DECODE) = 0x3; 205 *(volatile u_int *)(ioasic_base + IOASIC_SCSI_DECODE) = 0xe; 206#if 0 207 *(volatile u_int *)(ioasic_base + IOASIC_SCC0_DECODE) = (0x10|4); 208 *(volatile u_int *)(ioasic_base + IOASIC_SCC1_DECODE) = (0x10|6); 209 *(volatile u_int *)(ioasic_base + IOASIC_CSR) = 0x00000f00; 210#endif 211 /* 212 * Initialize interrupts. 213 */ 214 *(volatile u_int *)IOASIC_REG_IMSK(ioasic_base) = KMIN_IM0; 215 *(volatile u_int *)IOASIC_REG_INTR(ioasic_base) = 0; 216 217 /* clear any memory errors from probes */ 218 219 *(volatile u_int *)MIPS_PHYS_TO_KSEG1(KMIN_REG_TIMEOUT) = 0; 220 kn02ba_wbflush(); 221 222 /* 223 * The kmin memory hardware seems to wrap memory addresses 224 * with 4Mbyte SIMMs, which causes the physmem computation 225 * to lose. Find out how big the SIMMS are and set 226 * max_ physmem accordingly. 227 */ 228 physmem_boardmax = KMIN_PHYS_MEMORY_END + 1; 229 if ((*(int*)(MIPS_PHYS_TO_KSEG1(KMIN_REG_MSR)) & 230 KMIN_MSR_SIZE_16Mb) == 0) 231 physmem_boardmax = physmem_boardmax >> 2; 232 physmem_boardmax = MIPS_PHYS_TO_KSEG1(physmem_boardmax); 233 234 *(volatile u_int *)MIPS_PHYS_TO_KSEG1(KMIN_REG_IMSK) = 235 kmin_tc3_imask | 236 (KMIN_IM0 & ~(KN03_INTR_TC_0|KN03_INTR_TC_1|KN03_INTR_TC_2)); 237} 238 239 240void 241dec_3min_cons_init() 242{ 243 /* notyet */ 244} 245 246 247void 248dec_3min_device_register(dev, aux) 249 struct device *dev; 250 void *aux; 251{ 252 panic("dec_3min_device_register unimplemented"); 253} 254 255 256void 257dec_3min_enable_intr(slotno, handler, sc, on) 258 unsigned int slotno; 259 int (*handler) __P((void* softc)); 260 void *sc; 261 int on; 262{ 263 unsigned mask; 264 265 switch (slotno) { 266 /* slots 0-2 don't interrupt through the IOASIC. */ 267 case 0: 268 mask = MIPS_INT_MASK_0; break; 269 case 1: 270 mask = MIPS_INT_MASK_1; break; 271 case 2: 272 mask = MIPS_INT_MASK_2; break; 273 274 case KMIN_SCSI_SLOT: 275 mask = (IOASIC_INTR_SCSI | IOASIC_INTR_SCSI_PTR_LOAD | 276 IOASIC_INTR_SCSI_OVRUN | IOASIC_INTR_SCSI_READ_E); 277 break; 278 279 case KMIN_LANCE_SLOT: 280 mask = KMIN_INTR_LANCE; 281 break; 282 case KMIN_SCC0_SLOT: 283 mask = KMIN_INTR_SCC_0; 284 break; 285 case KMIN_SCC1_SLOT: 286 mask = KMIN_INTR_SCC_1; 287 break; 288 case KMIN_ASIC_SLOT: 289 mask = KMIN_INTR_ASIC; 290 break; 291 default: 292 return; 293 } 294 295#if defined(DEBUG) || defined(DIAGNOSTIC) 296 printf("3MIN: imask %lx, %sabling slot %d, sc %p handler %p\n", 297 kmin_tc3_imask, (on? "en" : "dis"), slotno, sc, handler); 298#endif 299 300 /* 301 * Enable the interrupt handler, and if it's an IOASIC 302 * slot, set the IOASIC interrupt mask. 303 * Otherwise, set the appropriate spl level in the R3000 304 * register. 305 * Be careful to set handlers before enabling, and disable 306 * interrupts before clearing handlers. 307 */ 308 309 if (on) { 310 /* Set the interrupt handler and argument ... */ 311 tc_slot_info[slotno].intr = handler; 312 tc_slot_info[slotno].sc = sc; 313 314 /* ... and set the relevant mask */ 315 if (slotno <= 2) { 316 /* it's an option slot */ 317 int s = splhigh(); 318 s |= mask; 319 splx(s); 320 } else { 321 /* it's a baseboard device going via the ASIC */ 322 kmin_tc3_imask |= mask; 323 } 324 } else { 325 /* Clear the relevant mask... */ 326 if (slotno <= 2) { 327 /* it's an option slot */ 328 int s = splhigh(); 329 printf("kmin_intr: cannot disable option slot %d\n", 330 slotno); 331 s &= ~mask; 332 splx(s); 333 } else { 334 /* it's a baseboard device going via the ASIC */ 335 kmin_tc3_imask &= ~mask; 336 } 337 /* ... and clear the handler */ 338 tc_slot_info[slotno].intr = 0; 339 tc_slot_info[slotno].sc = 0; 340 } 341} 342 343 344 345/* 346 * 3min hardware interrupts. (DECstation 5000/1xx) 347 */ 348int 349dec_3min_intr(mask, pc, statusReg, causeReg) 350 unsigned mask; 351 unsigned pc; 352 unsigned statusReg; 353 unsigned causeReg; 354{ 355 u_int intr; 356 volatile struct chiptime *c = 357 (volatile struct chiptime *) MIPS_PHYS_TO_KSEG1(KMIN_SYS_CLOCK); 358 volatile u_int * const imaskp = 359 (volatile u_int *)MIPS_PHYS_TO_KSEG1(KMIN_REG_IMSK); 360 volatile u_int * const intrp = 361 (volatile u_int *)MIPS_PHYS_TO_KSEG1(KMIN_REG_INTR); 362 unsigned int old_mask; 363 struct clockframe cf; 364 int temp; 365 static int user_warned = 0; 366 367 static int intr_depth = 0; 368 intr_depth++; 369 370 old_mask = *imaskp; 371 372 if (mask & MIPS_INT_MASK_4) 373 prom_haltbutton(); 374 375 if (mask & MIPS_INT_MASK_3) { 376 /* NB: status & MIPS_INT_MASK3 must also be set */ 377 /* masked interrupts are still observable */ 378 intr = *intrp & old_mask & kmin_tc3_imask; 379 380 if (intr & IOASIC_INTR_SCSI_PTR_LOAD) { 381 *intrp &= ~IOASIC_INTR_SCSI_PTR_LOAD; 382#ifdef notdef 383 asc_dma_intr(); 384#endif 385 } 386 387 if (intr & (IOASIC_INTR_SCSI_OVRUN | IOASIC_INTR_SCSI_READ_E)) 388 *intrp &= ~(IOASIC_INTR_SCSI_OVRUN | IOASIC_INTR_SCSI_READ_E); 389 390 if (intr & IOASIC_INTR_LANCE_READ_E) 391 *intrp &= ~IOASIC_INTR_LANCE_READ_E; 392 393 if (intr & KMIN_INTR_TIMEOUT) 394 kn02ba_errintr(); 395 396 if (intr & KMIN_INTR_CLOCK) { 397 extern u_int32_t mips3_cycle_count __P((void)); 398 399 temp = c->regc; /* XXX clear interrupt bits */ 400 cf.pc = pc; 401 cf.sr = statusReg; 402#ifdef MIPS3 403 if (CPUISMIPS3) { 404 latched_cycle_cnt = mips3_cycle_count(); 405 } 406#endif 407 hardclock(&cf); 408 intrcnt[HARDCLOCK]++; 409 } 410 411 /* If clock interrups were enabled, re-enable them ASAP. */ 412 if (old_mask & KMIN_INTR_CLOCK) { 413 /* ioctl interrupt mask to splclock and higher */ 414 *imaskp = old_mask & 415 ~(KMIN_INTR_SCC_0|KMIN_INTR_SCC_1 | 416 IOASIC_INTR_LANCE|IOASIC_INTR_SCSI); 417 kn02ba_wbflush(); 418 _splset(MIPS_SR_INT_IE | (statusReg & MIPS_INT_MASK_3)); 419 } 420 421 if (intr_depth > 1) 422 goto done; 423 424 if ((intr & KMIN_INTR_SCC_0) && 425 tc_slot_info[KMIN_SCC0_SLOT].intr) { 426 (*(tc_slot_info[KMIN_SCC0_SLOT].intr)) 427 (tc_slot_info[KMIN_SCC0_SLOT].sc); 428 intrcnt[SERIAL0_INTR]++; 429 } 430 431 if ((intr & KMIN_INTR_SCC_1) && 432 tc_slot_info[KMIN_SCC1_SLOT].intr) { 433 (*(tc_slot_info[KMIN_SCC1_SLOT].intr)) 434 (tc_slot_info[KMIN_SCC1_SLOT].sc); 435 intrcnt[SERIAL1_INTR]++; 436 } 437 438#ifdef notyet /* untested */ 439 /* If tty interrupts were enabled, re-enable them ASAP. */ 440 if ((old_mask & (KMIN_INTR_SCC_1|KMIN_INTR_SCC_0)) == 441 (KMIN_INTR_SCC_1|KMIN_INTR_SCC_0)) { 442 *imaskp = old_mask & 443 ~(KMIN_INTR_SCC_0|KMIN_INTR_SCC_1 | 444 IOASIC_INTR_LANCE|IOASIC_INTR_SCSI); 445 kn02ba_wbflush(); 446 } 447 448 /* XXX until we know about SPLs of TC options. */ 449 if (intr_depth > 1) 450 goto done; 451#endif 452 if ((intr & IOASIC_INTR_LANCE) && 453 tc_slot_info[KMIN_LANCE_SLOT].intr) { 454 (*(tc_slot_info[KMIN_LANCE_SLOT].intr)) 455 (tc_slot_info[KMIN_LANCE_SLOT].sc); 456 intrcnt[LANCE_INTR]++; 457 } 458 459 if ((intr & IOASIC_INTR_SCSI) && 460 tc_slot_info[KMIN_SCSI_SLOT].intr) { 461 (*(tc_slot_info[KMIN_SCSI_SLOT].intr)) 462 (tc_slot_info[KMIN_SCSI_SLOT].sc); 463 intrcnt[SCSI_INTR]++; 464 } 465 466 if (user_warned && ((intr & KMIN_INTR_PSWARN) == 0)) { 467 printf("%s\n", "Power supply ok now."); 468 user_warned = 0; 469 } 470 if ((intr & KMIN_INTR_PSWARN) && (user_warned < 3)) { 471 user_warned++; 472 printf("%s\n", "Power supply overheating"); 473 } 474 } 475 if ((mask & MIPS_INT_MASK_0) && tc_slot_info[0].intr) { 476 (*tc_slot_info[0].intr)(tc_slot_info[0].sc); 477 intrcnt[SLOT0_INTR]++; 478 } 479 480 if ((mask & MIPS_INT_MASK_1) && tc_slot_info[1].intr) { 481 (*tc_slot_info[1].intr)(tc_slot_info[1].sc); 482 intrcnt[SLOT1_INTR]++; 483 } 484 if ((mask & MIPS_INT_MASK_2) && tc_slot_info[2].intr) { 485 (*tc_slot_info[2].intr)(tc_slot_info[2].sc); 486 intrcnt[SLOT2_INTR]++; 487 } 488 489done: 490 /* restore entry state */ 491 splhigh(); 492 intr_depth--; 493 *imaskp = old_mask; 494 495 496 return(MIPS_SR_INT_IE | (statusReg & ~causeReg & MIPS_HARD_INT_MASK)); 497} 498 499 500 501/* 502 ************************************************************************ 503 * Extra functions 504 ************************************************************************ 505 */ 506 507 508 509 510/* 511 * Count instructions between 4ms mcclock interrupt requests, 512 * using the ioasic clock-interrupt-pending bit to determine 513 * when clock ticks occur. 514 * Set up iosiac to allow only clock interrupts, then 515 * call 516 */ 517void 518dec_3min_mcclock_cpuspeed(mcclock_addr, clockmask) 519 volatile struct chiptime *mcclock_addr; 520 int clockmask; 521{ 522 volatile u_int * ioasic_intrmaskp = 523 (volatile u_int *)MIPS_PHYS_TO_KSEG1(KMIN_REG_IMSK); 524 525 int saved_imask = *ioasic_intrmaskp; 526 527 /* Allow only clock interrupts through ioasic. */ 528 *ioasic_intrmaskp = KMIN_INTR_CLOCK; 529 kn02ba_wbflush(); 530 531 mc_cpuspeed(mcclock_addr, clockmask); 532 533 *ioasic_intrmaskp = saved_imask; 534 kn02ba_wbflush(); 535} 536 537void 538kn02ba_wbflush() 539{ 540 /* read twice IOASIC_INTR register */ 541 __asm __volatile("lw $0,0xbc040120; lw $0,0xbc040120"); 542} 543 544unsigned 545kn02ba_clkread() 546{ 547#ifdef MIPS3 548 extern u_int32_t mips3_cycle_count __P((void)); 549 extern u_long latched_cycle_cnt; 550 551 if (CPUISMIPS3) { 552 u_int32_t mips3_cycles; 553 554 mips3_cycles = mips3_cycle_count() - latched_cycle_cnt; 555#if 0 556 /* XXX divides take 78 cycles: approximate with * 41/2048 */ 557 return (mips3_cycles / cpu_mhz); 558#else 559 return((mips3_cycles >> 6) + (mips3_cycles >> 8) + 560 (mips3_cycles >> 11)); 561#endif 562 } 563#endif 564 return 0; 565} 566