xref: /netbsd/sys/arch/pmax/pmax/dec_maxine.c (revision bf9ec67e)
1 /* $NetBSD: dec_maxine.c,v 1.40 2001/09/18 16:15:20 tsutsui 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_maxine.c,v 1.40 2001/09/18 16:15:20 tsutsui Exp $");
77 
78 #include <sys/param.h>
79 #include <sys/systm.h>
80 #include <sys/device.h>
81 
82 #include <machine/cpu.h>
83 #include <machine/sysconf.h>
84 #include <mips/mips/mips_mcclock.h>
85 
86 #include <dev/tc/tcvar.h>
87 #include <dev/tc/ioasicvar.h>
88 #include <dev/tc/ioasicreg.h>
89 
90 #include <pmax/pmax/maxine.h>
91 #include <pmax/pmax/machdep.h>
92 #include <pmax/pmax/memc.h>
93 
94 #include <pmax/dev/xcfbvar.h>
95 #include <pmax/dev/dtopvar.h>
96 #include <pmax/tc/sccvar.h>
97 
98 #include "rasterconsole.h"
99 #include "xcfb.h"
100 
101 void		dec_maxine_init __P((void));		/* XXX */
102 static void	dec_maxine_bus_reset __P((void));
103 static void	dec_maxine_cons_init __P((void));
104 static void	dec_maxine_intr __P((unsigned, unsigned, unsigned, unsigned));
105 static void	dec_maxine_intr_establish __P((struct device *, void *,
106 		    int, int (*)(void *), void *));
107 
108 static void	kn02ca_wbflush __P((void));
109 static unsigned	kn02ca_clkread __P((void));
110 
111 /*
112  * local declarations
113  */
114 static u_int32_t xine_tc3_imask;
115 static unsigned latched_cycle_cnt;
116 
117 
118 void
119 dec_maxine_init()
120 {
121 	platform.iobus = "tcbus";
122 	platform.bus_reset = dec_maxine_bus_reset;
123 	platform.cons_init = dec_maxine_cons_init;
124 	platform.iointr = dec_maxine_intr;
125 	platform.intr_establish = dec_maxine_intr_establish;
126 	platform.memsize = memsize_bitmap;
127 	platform.clkread = kn02ca_clkread;
128 	/* MAXINE has 1 microsec. free-running high resolution timer */
129 
130 	/* clear any memory errors */
131 	*(u_int32_t *)MIPS_PHYS_TO_KSEG1(XINE_REG_TIMEOUT) = 0;
132 	kn02ca_wbflush();
133 
134 	ioasic_base = MIPS_PHYS_TO_KSEG1(XINE_SYS_ASIC);
135 
136 	/*
137 	 * MAXINE IOASIC interrupts come through INT 3, while
138 	 * clock interrupt does via INT 1.  splclock and splstatclock
139 	 * should block IOASIC activities.
140 	 */
141 	splvec.splbio = MIPS_SPL3;
142 	splvec.splnet = MIPS_SPL3;
143 	splvec.spltty = MIPS_SPL3;
144 	splvec.splvm = MIPS_SPL3;
145 	splvec.splclock = MIPS_SPL_0_1_3;
146 	splvec.splstatclock = MIPS_SPL_0_1_3;
147 
148 	/* calibrate cpu_mhz value */
149 	mc_cpuspeed(ioasic_base+IOASIC_SLOT_8_START, MIPS_INT_MASK_1);
150 
151 	*(u_int32_t *)(ioasic_base + IOASIC_LANCE_DECODE) = 0x3;
152 	*(u_int32_t *)(ioasic_base + IOASIC_SCSI_DECODE) = 0xe;
153 #if 0
154 	*(u_int32_t *)(ioasic_base + IOASIC_SCC0_DECODE) = (0x10|4);
155 	*(u_int32_t *)(ioasic_base + IOASIC_DTOP_DECODE) = 10;
156 	*(u_int32_t *)(ioasic_base + IOASIC_FLOPPY_DECODE) = 13;
157 	*(u_int32_t *)(ioasic_base + IOASIC_CSR) = 0x00001fc1;
158 #endif
159 
160 	/* sanitize interrupt mask */
161 	xine_tc3_imask = 0;
162 	*(u_int32_t *)(ioasic_base + IOASIC_INTR) = 0;
163 	*(u_int32_t *)(ioasic_base + IOASIC_IMSK) = xine_tc3_imask;
164 	kn02ca_wbflush();
165 
166 	sprintf(cpu_model, "Personal DECstation 5000/%d (MAXINE)", cpu_mhz);
167 }
168 
169 /*
170  * Initialize the memory system and I/O buses.
171  */
172 static void
173 dec_maxine_bus_reset()
174 {
175 	/*
176 	 * Reset interrupts, clear any errors from newconf probes
177 	 */
178 
179 	*(u_int32_t *)MIPS_PHYS_TO_KSEG1(XINE_REG_TIMEOUT) = 0;
180 	kn02ca_wbflush();
181 
182 	*(u_int32_t *)(ioasic_base + IOASIC_INTR) = 0;
183 	kn02ca_wbflush();
184 }
185 
186 
187 static void
188 dec_maxine_cons_init()
189 {
190 	int kbd, crt, screen;
191 	extern int tcfb_cnattach __P((int));		/* XXX */
192 
193 	kbd = crt = screen = 0;
194 	prom_findcons(&kbd, &crt, &screen);
195 
196 	if (screen > 0) {
197 #if NRASTERCONSOLE > 0
198 		if (crt == 3) {
199 #if NXCFB > 0
200 			xcfb_cnattach();
201 			dtikbd_cnattach();
202 			return;
203 #endif
204 		}
205 		else if (tcfb_cnattach(crt) > 0) {
206 			dtikbd_cnattach();
207 			return;
208 		}
209 #endif
210 		printf("No framebuffer device configured for slot %d: ", crt);
211 		printf("using serial console\n");
212 	}
213 	/*
214 	 * Delay to allow PROM putchars to complete.
215 	 * FIFO depth * character time,
216 	 * character time = (1000000 / (defaultrate / 10))
217 	 */
218 	DELAY(160000000 / 9600);        /* XXX */
219 
220 	scc_cnattach(ioasic_base, 0x100000);
221 }
222 
223 static void
224 dec_maxine_intr_establish(dev, cookie, level, handler, arg)
225 	struct device *dev;
226 	void *cookie;
227 	int level;
228 	int (*handler) __P((void *));
229 	void *arg;
230 {
231 	unsigned mask;
232 
233 	switch ((int)cookie) {
234 	  case SYS_DEV_OPT0:
235 		mask = XINE_INTR_TC_0;
236 		break;
237 	  case SYS_DEV_OPT1:
238 		mask = XINE_INTR_TC_1;
239 		break;
240 	  case SYS_DEV_FDC:
241 		mask = XINE_INTR_FLOPPY;
242 		break;
243 	  case SYS_DEV_SCSI:
244 		mask = (IOASIC_INTR_SCSI | IOASIC_INTR_SCSI_PTR_LOAD |
245 			IOASIC_INTR_SCSI_OVRUN | IOASIC_INTR_SCSI_READ_E);
246 		break;
247 	  case SYS_DEV_LANCE:
248 		mask = IOASIC_INTR_LANCE;
249 		break;
250 	  case SYS_DEV_SCC0:
251 		mask = IOASIC_INTR_SCC_0;
252 		break;
253 	  case SYS_DEV_DTOP:
254 		mask = XINE_INTR_DTOP_RX;
255 		break;
256 	  case SYS_DEV_ISDN:
257 		mask = (IOASIC_INTR_ISDN_TXLOAD | IOASIC_INTR_ISDN_RXLOAD |
258 			IOASIC_INTR_ISDN_OVRUN);
259 		break;
260 	  default:
261 #ifdef DIAGNOSTIC
262 		printf("warning: enabling unknown intr %x\n", (int)cookie);
263 #endif
264 		return;
265 	}
266 
267 	xine_tc3_imask |= mask;
268 	intrtab[(int)cookie].ih_func = handler;
269 	intrtab[(int)cookie].ih_arg = arg;
270 
271 	*(u_int32_t *)(ioasic_base + IOASIC_IMSK) = xine_tc3_imask;
272 	kn02ca_wbflush();
273 }
274 
275 #define CHECKINTR(vvv, bits)					\
276     do {							\
277 	if (can_serve & (bits)) {				\
278 		ifound = 1;					\
279 		intrcnt[vvv] += 1;				\
280 		(*intrtab[vvv].ih_func)(intrtab[vvv].ih_arg);	\
281 	}							\
282     } while (0)
283 
284 static void
285 dec_maxine_intr(status, cause, pc, ipending)
286 	unsigned ipending;
287 	unsigned pc;
288 	unsigned status;
289 	unsigned cause;
290 {
291 	if (ipending & MIPS_INT_MASK_4)
292 		prom_haltbutton();
293 
294 	/* handle clock interrupts ASAP */
295 	if (ipending & MIPS_INT_MASK_1) {
296 		struct clockframe cf;
297 
298 		__asm __volatile("lbu $0,48(%0)" ::
299 			"r"(ioasic_base + IOASIC_SLOT_8_START));
300 		latched_cycle_cnt =
301 		    *(u_int32_t *)MIPS_PHYS_TO_KSEG1(XINE_REG_FCTR);
302 		cf.pc = pc;
303 		cf.sr = status;
304 		hardclock(&cf);
305 		pmax_clock_evcnt.ev_count++;
306 		/* keep clock interrupts enabled when we return */
307 		cause &= ~MIPS_INT_MASK_1;
308 	}
309 
310 	/* If clock interrups were enabled, re-enable them ASAP. */
311 	_splset(MIPS_SR_INT_IE | (status & MIPS_INT_MASK_1));
312 
313 	if (ipending & MIPS_INT_MASK_3) {
314 		int ifound;
315 		u_int32_t imsk, intr, can_serve, xxxintr;
316 
317 		do {
318 			ifound = 0;
319 			intr = *(u_int32_t *)(ioasic_base + IOASIC_INTR);
320 			imsk = *(u_int32_t *)(ioasic_base + IOASIC_IMSK);
321 			can_serve = intr & imsk;
322 
323 			CHECKINTR(SYS_DEV_DTOP, XINE_INTR_DTOP);
324 			CHECKINTR(SYS_DEV_SCC0, IOASIC_INTR_SCC_0);
325 			CHECKINTR(SYS_DEV_LANCE, IOASIC_INTR_LANCE);
326 			CHECKINTR(SYS_DEV_SCSI, IOASIC_INTR_SCSI);
327 			/* CHECKINTR(SYS_DEV_OPT2, XINE_INTR_VINT);	*/
328 			CHECKINTR(SYS_DEV_ISDN, (IOASIC_INTR_ISDN_TXLOAD | IOASIC_INTR_ISDN_RXLOAD));
329 			/* CHECKINTR(SYS_DEV_FDC, IOASIC_INTR_FDC);	*/
330 			CHECKINTR(SYS_DEV_OPT1, XINE_INTR_TC_1);
331 			CHECKINTR(SYS_DEV_OPT0, XINE_INTR_TC_0);
332 
333 #define ERRORS	(IOASIC_INTR_ISDN_OVRUN|IOASIC_INTR_SCSI_OVRUN|IOASIC_INTR_SCSI_READ_E|IOASIC_INTR_LANCE_READ_E)
334 #define PTRLOAD (IOASIC_INTR_ISDN_TXLOAD|IOASIC_INTR_ISDN_RXLOAD|IOASIC_INTR_SCSI_PTR_LOAD)
335 
336 	/*
337 	 * XXX future project is here XXX
338 	 * IOASIC DMA completion interrupt (PTR_LOAD) should be checked
339 	 * here, and DMA pointers serviced as soon as possible.
340 	 */
341 	/*
342 	 * All of IOASIC device interrupts comes through a single service
343 	 * request line coupled with MIPS cpu INT 3.
344 	 * Disabling INT 3 makes entire IOASIC interrupt services blocked,
345 	 * and it's harmful because it causes DMA overruns during network
346 	 * disk I/O interrupts.
347 	 * So, Non-DMA interrupts should be selectively disabled by masking
348 	 * IOASIC_IMSK register, and INT 3 itself be reenabled immediately,
349 	 * and made available all the time.
350 	 * DMA interrupts can then be serviced whilst still servicing
351 	 * non-DMA interrupts from ioctl devices or TC options.
352 	 */
353 			xxxintr = can_serve & (ERRORS | PTRLOAD);
354 			if (xxxintr) {
355 				ifound = 1;
356 				*(u_int32_t *)(ioasic_base + IOASIC_INTR)
357 					= intr &~ xxxintr;
358 			}
359 		} while (ifound);
360 	}
361 	if (ipending & MIPS_INT_MASK_2) {
362 		kn02ba_errintr();
363 		pmax_memerr_evcnt.ev_count++;
364 	}
365 
366 	_splset(MIPS_SR_INT_IE | (status & ~cause & MIPS_HARD_INT_MASK));
367 }
368 
369 static void
370 kn02ca_wbflush()
371 {
372 	/* read once IOASIC_IMSK */
373 	__asm __volatile("lw $0,%0" ::
374 	    "i"(MIPS_PHYS_TO_KSEG1(XINE_REG_IMSK)));
375 }
376 
377 static unsigned
378 kn02ca_clkread()
379 {
380 	u_int32_t cycles;
381 
382 	cycles = *(u_int32_t *)MIPS_PHYS_TO_KSEG1(XINE_REG_FCTR);
383 	return cycles - latched_cycle_cnt;
384 }
385