dec_3min.c revision 1.1
1/* $NetBSD: dec_3min.c,v 1.1 1998/03/25 03:57:54 jonathan 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.1 1998/03/25 03:57:54 jonathan 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/locore.h> /* wbflush() */ 87#include <machine/autoconf.h> /* intr_arg_t */ 88#include <machine/sysconf.h> 89 90#include <mips/mips_param.h> /* hokey spl()s */ 91#include <mips/mips/mips_mcclock.h> /* mcclock CPUspeed estimation */ 92 93#include <pmax/pmax/clockreg.h> 94#include <pmax/pmax/asic.h> 95#include <pmax/pmax/turbochannel.h> 96#include <pmax/pmax/pmaxtype.h> 97#include <pmax/pmax/trap.h> /* mboard-specific interrupt fns */ 98#include <pmax/pmax/cons.h> 99 100#include <pmax/pmax/machdep.h> /* XXXjrs replace with vectors */ 101 102#include <pmax/pmax/kmin.h> /* 3min baseboard addresses */ 103#include <pmax/pmax/dec_kn02_subr.h> /* 3min/maxine memory errors */ 104 105 106/* 107 * forward declarations 108 */ 109void dec_3min_init __P((void)); 110void dec_3min_os_init __P((void)); 111void dec_3min_bus_reset __P((void)); 112void dec_3maxplus_device_register __P((struct device *, void *)); 113 114void dec_3min_enable_intr 115 __P ((u_int slotno, int (*handler) __P((intr_arg_t sc)), 116 intr_arg_t sc, int onoff)); 117int dec_3min_intr __P((u_int mask, u_int pc, 118 u_int statusReg, u_int causeReg)); 119 120void dec_3min_device_register __P((struct device *, void *)); 121void dec_3min_cons_init __P((void)); 122const char* dec_3min_model_name __P((void)); 123 124 125/* 126 * Local declarations. 127 */ 128void dec_3min_mcclock_cpuspeed __P((volatile struct chiptime *mcclock_addr, 129 int clockmask)); 130u_long kmin_tc3_imask; 131 132 133/* 134 * Fill in platform struct. 135 */ 136void 137dec_3min_init() 138{ 139 140 platform.family = "Decstation 5000"; 141 142 platform.model = "5000/1xx"; 143 144 platform.iobus = "tcbus"; 145 146 platform.os_init = dec_3min_os_init; 147 platform.bus_reset = dec_3min_bus_reset; 148 platform.cons_init = dec_3min_cons_init; 149 platform.device_register = dec_3min_device_register; 150 151 dec_3min_os_init(); 152 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 wbflush(); 169 170 *(volatile u_int *)IOASIC_REG_INTR(ioasic_base) = 0; 171 wbflush(); 172 173} 174 175 176void 177dec_3min_os_init() 178{ 179 ioasic_base = MIPS_PHYS_TO_KSEG1(KMIN_SYS_ASIC); 180 mips_hardware_intr = dec_3min_intr; 181 tc_enable_interrupt = dec_3min_enable_intr; 182 kmin_tc3_imask = (KMIN_INTR_CLOCK | KMIN_INTR_PSWARN | 183 KMIN_INTR_TIMEOUT); 184 185 /* 186 * Since all the motherboard interrupts come through the 187 * I/O ASIC, it has to be turned off for all the spls and 188 * since we don't know what kinds of devices are in the 189 * turbochannel option slots, just splhigh(). 190 */ 191 Mach_splbio = splhigh; 192 Mach_splnet = splhigh; 193 Mach_spltty = splhigh; 194 Mach_splimp = splhigh; 195 Mach_splclock = splhigh; 196 Mach_splstatclock = splhigh; 197 mcclock_addr = (volatile struct chiptime *) 198 MIPS_PHYS_TO_KSEG1(KMIN_SYS_CLOCK); 199 dec_3min_mcclock_cpuspeed(mcclock_addr, MIPS_INT_MASK_3); 200 201 /* 202 * Initialize interrupts. 203 */ 204 *(u_int *)IOASIC_REG_IMSK(ioasic_base) = KMIN_IM0; 205 *(u_int *)IOASIC_REG_INTR(ioasic_base) = 0; 206 207 /* clear any memory errors from probes */ 208 209 *(volatile u_int *)MIPS_PHYS_TO_KSEG1(KMIN_REG_TIMEOUT) = 0; 210 wbflush(); 211 212 213 sprintf(cpu_model, "5000/1%d", cpu_mhz); 214 215 /* 216 * The kmin memory hardware seems to wrap memory addresses 217 * with 4Mbyte SIMMs, which causes the physmem computation 218 * to lose. Find out how big the SIMMS are and set 219 * max_ physmem accordingly. 220 * XXX Do MAXINEs lose the same way? 221 */ 222 physmem_boardmax = KMIN_PHYS_MEMORY_END + 1; 223 if ((*(int*)(MIPS_PHYS_TO_KSEG1(KMIN_REG_MSR)) & 224 KMIN_MSR_SIZE_16Mb) == 0) 225 physmem_boardmax = physmem_boardmax >> 2; 226 physmem_boardmax = MIPS_PHYS_TO_KSEG1(physmem_boardmax); 227} 228 229 230void 231dec_3min_cons_init() 232{ 233 /* notyet */ 234} 235 236 237const char* 238dec_3min_model_name() 239{ 240 return ("Decstation 5000/1xx"); 241} 242 243 244void 245dec_3min_device_register(dev, aux) 246 struct device *dev; 247 void *aux; 248{ 249 panic("dec_3min_device_register unimplemented"); 250} 251 252 253void 254dec_3min_enable_intr(slotno, handler, sc, on) 255 register unsigned int slotno; 256 int (*handler) __P((void* softc)); 257 void *sc; 258 int on; 259{ 260 register unsigned mask; 261 262 switch (slotno) { 263 /* slots 0-2 don't interrupt through the IOASIC. */ 264 case 0: 265 mask = MIPS_INT_MASK_0; break; 266 case 1: 267 mask = MIPS_INT_MASK_1; break; 268 case 2: 269 mask = MIPS_INT_MASK_2; break; 270 271 case KMIN_SCSI_SLOT: 272 mask = (KMIN_INTR_SCSI | KMIN_INTR_SCSI_PTR_LOAD | 273 KMIN_INTR_SCSI_OVRUN | KMIN_INTR_SCSI_READ_E); 274 break; 275 276 case KMIN_LANCE_SLOT: 277 mask = KMIN_INTR_LANCE; 278 break; 279 case KMIN_SCC0_SLOT: 280 mask = KMIN_INTR_SCC_0; 281 break; 282 case KMIN_SCC1_SLOT: 283 mask = KMIN_INTR_SCC_1; 284 break; 285 case KMIN_ASIC_SLOT: 286 mask = KMIN_INTR_ASIC; 287 break; 288 default: 289 return; 290 } 291 292#if defined(DEBUG) || defined(DIAGNOSTIC) 293 printf("3MIN: imask %lx, %sabling slot %d, sc %p handler %p\n", 294 kmin_tc3_imask, (on? "en" : "dis"), slotno, sc, handler); 295#endif 296 297 /* 298 * Enable the interrupt handler, and if it's an IOASIC 299 * slot, set the IOASIC interrupt mask. 300 * Otherwise, set the appropriate spl level in the R3000 301 * register. 302 * Be careful to set handlers before enabling, and disable 303 * interrupts before clearing handlers. 304 */ 305 306 if (on) { 307 /* Set the interrupt handler and argument ... */ 308 tc_slot_info[slotno].intr = handler; 309 tc_slot_info[slotno].sc = sc; 310 311 /* ... and set the relevant mask */ 312 if (slotno <= 2) { 313 /* it's an option slot */ 314 int s = splhigh(); 315 s |= mask; 316 splx(s); 317 } else { 318 /* it's a baseboard device going via the ASIC */ 319 kmin_tc3_imask |= mask; 320 } 321 } else { 322 /* Clear the relevant mask... */ 323 if (slotno <= 2) { 324 /* it's an option slot */ 325 int s = splhigh(); 326 printf("kmin_intr: cannot disable option slot %d\n", 327 slotno); 328 s &= ~mask; 329 splx(s); 330 } else { 331 /* it's a baseboard device going via the ASIC */ 332 kmin_tc3_imask &= ~mask; 333 } 334 /* ... and clear the handler */ 335 tc_slot_info[slotno].intr = 0; 336 tc_slot_info[slotno].sc = 0; 337 } 338} 339 340 341 342/* 343 * 3min hardware interrupts. (DECstation 5000/1xx) 344 */ 345int 346dec_3min_intr(mask, pc, statusReg, causeReg) 347 unsigned mask; 348 unsigned pc; 349 unsigned statusReg; 350 unsigned causeReg; 351{ 352 register u_int intr; 353 register volatile struct chiptime *c = 354 (volatile struct chiptime *) MIPS_PHYS_TO_KSEG1(KMIN_SYS_CLOCK); 355 volatile u_int *imaskp = 356 (volatile u_int *)MIPS_PHYS_TO_KSEG1(KMIN_REG_IMSK); 357 volatile u_int *intrp = 358 (volatile u_int *)MIPS_PHYS_TO_KSEG1(KMIN_REG_INTR); 359 unsigned int old_mask; 360 struct clockframe cf; 361 int temp; 362 static int user_warned = 0; 363 364 old_mask = *imaskp & kmin_tc3_imask; 365 *imaskp = kmin_tc3_imask | 366 (KMIN_IM0 & ~(KN03_INTR_TC_0|KN03_INTR_TC_1|KN03_INTR_TC_2)); 367 368 if (mask & MIPS_INT_MASK_4) 369 prom_haltbutton(); 370 371 if (mask & MIPS_INT_MASK_3) { 372 intr = *intrp; 373 374 /* masked interrupts are still observable */ 375 intr &= old_mask; 376 377 if (intr & KMIN_INTR_SCSI_PTR_LOAD) { 378 *intrp &= ~KMIN_INTR_SCSI_PTR_LOAD; 379#ifdef notdef 380 asc_dma_intr(); 381#endif 382 } 383 384 if (intr & (KMIN_INTR_SCSI_OVRUN | KMIN_INTR_SCSI_READ_E)) 385 *intrp &= ~(KMIN_INTR_SCSI_OVRUN | KMIN_INTR_SCSI_READ_E); 386 387 if (intr & KMIN_INTR_LANCE_READ_E) 388 *intrp &= ~KMIN_INTR_LANCE_READ_E; 389 390 if (intr & KMIN_INTR_TIMEOUT) 391 kn02ba_errintr(); 392 393 if (intr & KMIN_INTR_CLOCK) { 394 temp = c->regc; /* XXX clear interrupt bits */ 395 cf.pc = pc; 396 cf.sr = statusReg; 397 hardclock(&cf); 398 intrcnt[HARDCLOCK]++; 399 } 400 401 if ((intr & KMIN_INTR_SCC_0) && 402 tc_slot_info[KMIN_SCC0_SLOT].intr) { 403 (*(tc_slot_info[KMIN_SCC0_SLOT].intr)) 404 (tc_slot_info[KMIN_SCC0_SLOT].sc); 405 intrcnt[SERIAL0_INTR]++; 406 } 407 408 if ((intr & KMIN_INTR_SCC_1) && 409 tc_slot_info[KMIN_SCC1_SLOT].intr) { 410 (*(tc_slot_info[KMIN_SCC1_SLOT].intr)) 411 (tc_slot_info[KMIN_SCC1_SLOT].sc); 412 intrcnt[SERIAL1_INTR]++; 413 } 414 415 if ((intr & KMIN_INTR_SCSI) && 416 tc_slot_info[KMIN_SCSI_SLOT].intr) { 417 (*(tc_slot_info[KMIN_SCSI_SLOT].intr)) 418 (tc_slot_info[KMIN_SCSI_SLOT].sc); 419 intrcnt[SCSI_INTR]++; 420 } 421 422 if ((intr & KMIN_INTR_LANCE) && 423 tc_slot_info[KMIN_LANCE_SLOT].intr) { 424 (*(tc_slot_info[KMIN_LANCE_SLOT].intr)) 425 (tc_slot_info[KMIN_LANCE_SLOT].sc); 426 intrcnt[LANCE_INTR]++; 427 } 428 429 if (user_warned && ((intr & KMIN_INTR_PSWARN) == 0)) { 430 printf("%s\n", "Power supply ok now."); 431 user_warned = 0; 432 } 433 if ((intr & KMIN_INTR_PSWARN) && (user_warned < 3)) { 434 user_warned++; 435 printf("%s\n", "Power supply overheating"); 436 } 437 } 438 if ((mask & MIPS_INT_MASK_0) && tc_slot_info[0].intr) { 439 (*tc_slot_info[0].intr)(tc_slot_info[0].sc); 440 intrcnt[SLOT0_INTR]++; 441 } 442 443 if ((mask & MIPS_INT_MASK_1) && tc_slot_info[1].intr) { 444 (*tc_slot_info[1].intr)(tc_slot_info[1].sc); 445 intrcnt[SLOT1_INTR]++; 446 } 447 if ((mask & MIPS_INT_MASK_2) && tc_slot_info[2].intr) { 448 (*tc_slot_info[2].intr)(tc_slot_info[2].sc); 449 intrcnt[SLOT2_INTR]++; 450 } 451 452#if 0 /*XXX*/ 453 if (mask & (MIPS_INT_MASK_2|MIPS_INT_MASK_1|MIPS_INT_MASK_0)) 454 printf("kmin: slot intr, mask 0x%x\n", 455 mask & 456 (MIPS_INT_MASK_2|MIPS_INT_MASK_1|MIPS_INT_MASK_0)); 457#endif 458 459 return ((statusReg & ~causeReg & MIPS_HARD_INT_MASK) | 460 MIPS_SR_INT_ENA_CUR); 461} 462 463 464 465/* 466 ************************************************************************ 467 * Extra functions 468 ************************************************************************ 469 */ 470 471 472 473 474/* 475 * Count instructions between 4ms mcclock interrupt requests, 476 * using the ioasic clock-interrupt-pending bit to determine 477 * when clock ticks occur. 478 * Set up iosiac to allow only clock interrupts, then 479 * call 480 */ 481void 482dec_3min_mcclock_cpuspeed(mcclock_addr, clockmask) 483 volatile struct chiptime *mcclock_addr; 484 int clockmask; 485{ 486 register volatile u_int * ioasic_intrmaskp = 487 (volatile u_int *)MIPS_PHYS_TO_KSEG1(KMIN_REG_IMSK); 488 489 register int saved_imask = *ioasic_intrmaskp; 490 491 /* Allow only clock interrupts through ioasic. */ 492 *ioasic_intrmaskp = KMIN_INTR_CLOCK; 493 wbflush(); 494 495 mc_cpuspeed(mcclock_addr, clockmask); 496 497 *ioasic_intrmaskp = saved_imask; 498 wbflush(); 499} 500 501