1 /* $NetBSD: dec_maxine.c,v 1.59 2009/12/14 00:46:10 matt 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_maxine.c,v 1.59 2009/12/14 00:46:10 matt 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 #include <mips/mips/mips_mcclock.h> 119 120 #include <dev/tc/tcvar.h> 121 #include <dev/tc/ioasicvar.h> 122 #include <dev/tc/ioasicreg.h> 123 124 #include <pmax/pmax/maxine.h> 125 #include <pmax/pmax/machdep.h> 126 #include <pmax/pmax/memc.h> 127 128 #include <dev/ic/z8530sc.h> 129 #include <dev/tc/zs_ioasicvar.h> 130 #include <pmax/pmax/cons.h> 131 #include "wsdisplay.h" 132 #include "xcfb.h" 133 134 void dec_maxine_init(void); /* XXX */ 135 static void dec_maxine_bus_reset(void); 136 static void dec_maxine_cons_init(void); 137 static void dec_maxine_intr(unsigned, unsigned, unsigned, unsigned); 138 static void dec_maxine_intr_establish(struct device *, void *, 139 int, int (*)(void *), void *); 140 141 static void dec_maxine_tc_init(void); 142 143 static void kn02ca_wbflush(void); 144 145 /* 146 * local declarations 147 */ 148 static uint32_t xine_tc3_imask; 149 150 static const int dec_maxine_ipl2spl_table[] = { 151 [IPL_NONE] = 0, 152 [IPL_SOFTCLOCK] = _SPL_SOFTCLOCK, 153 [IPL_SOFTNET] = _SPL_SOFTNET, 154 /* 155 * MAXINE IOASIC interrupts come through INT 3, while 156 * clock interrupt does via INT 1. splclock and splstatclock 157 * should block IOASIC activities. 158 */ 159 [IPL_VM] = MIPS_SPL3, 160 [IPL_SCHED] = MIPS_SPL_0_1_3, 161 [IPL_HIGH] = MIPS_SPL_0_1_3, 162 }; 163 164 void 165 dec_maxine_init(void) 166 { 167 168 platform.iobus = "tcbus"; 169 platform.bus_reset = dec_maxine_bus_reset; 170 platform.cons_init = dec_maxine_cons_init; 171 platform.iointr = dec_maxine_intr; 172 platform.intr_establish = dec_maxine_intr_establish; 173 platform.memsize = memsize_bitmap; 174 platform.tc_init = dec_maxine_tc_init; 175 /* MAXINE has 1 microsec. free-running high resolution timer */ 176 177 /* clear any memory errors */ 178 *(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(XINE_REG_TIMEOUT) = 0; 179 kn02ca_wbflush(); 180 181 ioasic_base = MIPS_PHYS_TO_KSEG1(XINE_SYS_ASIC); 182 183 ipl2spl_table = dec_maxine_ipl2spl_table; 184 185 /* calibrate cpu_mhz value */ 186 mc_cpuspeed(ioasic_base+IOASIC_SLOT_8_START, MIPS_INT_MASK_1); 187 188 *(volatile uint32_t *)(ioasic_base + IOASIC_LANCE_DECODE) = 0x3; 189 *(volatile uint32_t *)(ioasic_base + IOASIC_SCSI_DECODE) = 0xe; 190 #if 0 191 *(volatile uint32_t *)(ioasic_base + IOASIC_SCC0_DECODE) = (0x10|4); 192 *(volatile uint32_t *)(ioasic_base + IOASIC_DTOP_DECODE) = 10; 193 *(volatile uint32_t *)(ioasic_base + IOASIC_FLOPPY_DECODE) = 13; 194 *(volatile uint32_t *)(ioasic_base + IOASIC_CSR) = 0x00001fc1; 195 #endif 196 197 /* sanitize interrupt mask */ 198 xine_tc3_imask = 0; 199 *(volatile uint32_t *)(ioasic_base + IOASIC_INTR) = 0; 200 *(volatile uint32_t *)(ioasic_base + IOASIC_IMSK) = xine_tc3_imask; 201 kn02ca_wbflush(); 202 203 sprintf(cpu_model, "Personal DECstation 5000/%d (MAXINE)", cpu_mhz); 204 } 205 206 /* 207 * Initialize the memory system and I/O buses. 208 */ 209 static void 210 dec_maxine_bus_reset(void) 211 { 212 213 /* 214 * Reset interrupts, clear any errors from newconf probes 215 */ 216 217 *(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(XINE_REG_TIMEOUT) = 0; 218 kn02ca_wbflush(); 219 220 *(volatile uint32_t *)(ioasic_base + IOASIC_INTR) = 0; 221 kn02ca_wbflush(); 222 } 223 224 225 static void 226 dec_maxine_cons_init(void) 227 { 228 int kbd, crt, screen; 229 230 kbd = crt = screen = 0; 231 prom_findcons(&kbd, &crt, &screen); 232 233 if (screen > 0) { 234 #if NWSDISPLAY > 0 235 #if NXCFB > 0 236 if (crt == 3) { 237 xcfb_cnattach((tc_addr_t)XINE_PHYS_CFB_START); 238 dtkbd_cnattach(); 239 return; 240 } 241 #endif 242 if (tcfb_cnattach(crt) > 0) { 243 dtkbd_cnattach(); 244 return; 245 } 246 #endif 247 printf("No framebuffer device configured for slot %d: ", crt); 248 printf("using serial console\n"); 249 } 250 /* 251 * Delay to allow PROM putchars to complete. 252 * FIFO depth * character time, 253 * character time = (1000000 / (defaultrate / 10)) 254 */ 255 DELAY(160000000 / 9600); /* XXX */ 256 257 zs_ioasic_cnattach(ioasic_base, 0x100000, 1); 258 } 259 260 static void 261 dec_maxine_intr_establish(struct device *dev, void *cookie, int level, 262 int (*handler)(void *), void *arg) 263 { 264 uint32_t mask; 265 266 switch ((uintptr_t)cookie) { 267 case SYS_DEV_OPT0: 268 mask = XINE_INTR_TC_0; 269 break; 270 case SYS_DEV_OPT1: 271 mask = XINE_INTR_TC_1; 272 break; 273 case SYS_DEV_FDC: 274 mask = XINE_INTR_FLOPPY; 275 break; 276 case SYS_DEV_SCSI: 277 mask = (IOASIC_INTR_SCSI | IOASIC_INTR_SCSI_PTR_LOAD | 278 IOASIC_INTR_SCSI_OVRUN | IOASIC_INTR_SCSI_READ_E); 279 break; 280 case SYS_DEV_LANCE: 281 mask = IOASIC_INTR_LANCE; 282 break; 283 case SYS_DEV_SCC0: 284 mask = IOASIC_INTR_SCC_0; 285 break; 286 case SYS_DEV_DTOP: 287 mask = XINE_INTR_DTOP_RX; 288 break; 289 case SYS_DEV_ISDN: 290 mask = (IOASIC_INTR_ISDN_TXLOAD | IOASIC_INTR_ISDN_RXLOAD | 291 IOASIC_INTR_ISDN_OVRUN); 292 break; 293 default: 294 #ifdef DIAGNOSTIC 295 printf("warning: enabling unknown intr %p\n", cookie); 296 #endif 297 return; 298 } 299 300 xine_tc3_imask |= mask; 301 intrtab[(uintptr_t)cookie].ih_func = handler; 302 intrtab[(uintptr_t)cookie].ih_arg = arg; 303 304 *(volatile uint32_t *)(ioasic_base + IOASIC_IMSK) = xine_tc3_imask; 305 kn02ca_wbflush(); 306 } 307 308 #define CHECKINTR(vvv, bits) \ 309 do { \ 310 if (can_serve & (bits)) { \ 311 ifound = 1; \ 312 intrtab[vvv].ih_count.ev_count++; \ 313 (*intrtab[vvv].ih_func)(intrtab[vvv].ih_arg); \ 314 } \ 315 } while (/*CONSTCOND*/0) 316 317 static void 318 dec_maxine_intr(uint32_t status, uint32_t cause, uint32_t pc, uint32_t ipending) 319 { 320 321 if (ipending & MIPS_INT_MASK_4) 322 prom_haltbutton(); 323 324 /* handle clock interrupts ASAP */ 325 if (ipending & MIPS_INT_MASK_1) { 326 struct clockframe cf; 327 328 __asm volatile("lbu $0,48(%0)" :: 329 "r"(ioasic_base + IOASIC_SLOT_8_START)); 330 cf.pc = pc; 331 cf.sr = status; 332 hardclock(&cf); 333 pmax_clock_evcnt.ev_count++; 334 /* keep clock interrupts enabled when we return */ 335 cause &= ~MIPS_INT_MASK_1; 336 } 337 338 /* If clock interrupts were enabled, re-enable them ASAP. */ 339 _splset(MIPS_SR_INT_IE | (status & MIPS_INT_MASK_1)); 340 341 if (ipending & MIPS_INT_MASK_3) { 342 int ifound; 343 uint32_t imsk, intr, can_serve, xxxintr; 344 345 do { 346 ifound = 0; 347 intr = 348 *(volatile uint32_t *)(ioasic_base + IOASIC_INTR); 349 imsk = 350 *(volatile uint32_t *)(ioasic_base + IOASIC_IMSK); 351 can_serve = intr & imsk; 352 353 CHECKINTR(SYS_DEV_DTOP, XINE_INTR_DTOP); 354 CHECKINTR(SYS_DEV_SCC0, IOASIC_INTR_SCC_0); 355 CHECKINTR(SYS_DEV_LANCE, IOASIC_INTR_LANCE); 356 CHECKINTR(SYS_DEV_SCSI, IOASIC_INTR_SCSI); 357 /* CHECKINTR(SYS_DEV_OPT2, XINE_INTR_VINT); */ 358 CHECKINTR(SYS_DEV_ISDN, 359 IOASIC_INTR_ISDN_TXLOAD | IOASIC_INTR_ISDN_RXLOAD); 360 /* CHECKINTR(SYS_DEV_FDC, IOASIC_INTR_FDC); */ 361 CHECKINTR(SYS_DEV_OPT1, XINE_INTR_TC_1); 362 CHECKINTR(SYS_DEV_OPT0, XINE_INTR_TC_0); 363 364 #define ERRORS (IOASIC_INTR_ISDN_OVRUN|IOASIC_INTR_SCSI_OVRUN|IOASIC_INTR_SCSI_READ_E|IOASIC_INTR_LANCE_READ_E) 365 #define PTRLOAD (IOASIC_INTR_ISDN_TXLOAD|IOASIC_INTR_ISDN_RXLOAD|IOASIC_INTR_SCSI_PTR_LOAD) 366 367 /* 368 * XXX future project is here XXX 369 * IOASIC DMA completion interrupt (PTR_LOAD) should be checked 370 * here, and DMA pointers serviced as soon as possible. 371 */ 372 /* 373 * All of IOASIC device interrupts comes through a single service 374 * request line coupled with MIPS CPU INT 3. 375 * Disabling INT 3 makes entire IOASIC interrupt services blocked, 376 * and it's harmful because it causes DMA overruns during network 377 * disk I/O interrupts. 378 * So, Non-DMA interrupts should be selectively disabled by masking 379 * IOASIC_IMSK register, and INT 3 itself be reenabled immediately, 380 * and made available all the time. 381 * DMA interrupts can then be serviced whilst still servicing 382 * non-DMA interrupts from ioctl devices or TC options. 383 */ 384 xxxintr = can_serve & (ERRORS | PTRLOAD); 385 if (xxxintr) { 386 ifound = 1; 387 *(volatile uint32_t *) 388 (ioasic_base + IOASIC_INTR) 389 = intr &~ xxxintr; 390 } 391 } while (ifound); 392 } 393 if (ipending & MIPS_INT_MASK_2) { 394 kn02ba_errintr(); 395 pmax_memerr_evcnt.ev_count++; 396 } 397 398 _splset(MIPS_SR_INT_IE | (status & ~cause & MIPS_HARD_INT_MASK)); 399 } 400 401 static void 402 kn02ca_wbflush(void) 403 { 404 405 /* read once IOASIC_IMSK */ 406 __asm volatile("lw $0,%0" :: 407 "i"(MIPS_PHYS_TO_KSEG1(XINE_REG_IMSK))); 408 } 409 410 static u_int 411 dec_maxine_get_timecount(struct timecounter *tc) 412 { 413 414 return *(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(XINE_REG_FCTR); 415 } 416 417 static void 418 dec_maxine_tc_init(void) 419 { 420 static struct timecounter tc = { 421 .tc_get_timecount = dec_maxine_get_timecount, 422 .tc_quality = 100, 423 .tc_frequency = 1000000, 424 .tc_counter_mask = ~0, 425 .tc_name = "maxine_fctr", 426 }; 427 428 tc_init(&tc); 429 } 430