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