dec_3min.c revision 1.50
1/* $NetBSD: dec_3min.c,v 1.50 2003/08/07 16:29:13 agc 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_3min.c,v 1.50 2003/08/07 16:29:13 agc Exp $");
110
111#include <sys/param.h>
112#include <sys/systm.h>
113#include <sys/device.h>
114
115#include <machine/cpu.h>
116#include <machine/intr.h>
117#include <machine/sysconf.h>
118
119#include <mips/mips/mips_mcclock.h>	/* mcclock CPUspeed estimation */
120
121/* all these to get ioasic_base */
122#include <dev/tc/tcvar.h>		/* tc type definitions for.. */
123#include <dev/tc/ioasicreg.h>		/* ioasic interrrupt masks */
124#include <dev/tc/ioasicvar.h>		/* ioasic_base */
125
126#include <pmax/pmax/machdep.h>
127#include <pmax/pmax/kmin.h>		/* 3min baseboard addresses */
128#include <pmax/pmax/memc.h>		/* 3min/maxine memory errors */
129#include <pmax/tc/sccvar.h>
130
131#include "rasterconsole.h"
132
133void		dec_3min_init __P((void));		/* XXX */
134static void	dec_3min_bus_reset __P((void));
135static void	dec_3min_cons_init __P((void));
136static void	dec_3min_intr __P((unsigned, unsigned, unsigned, unsigned));
137static void	dec_3min_intr_establish __P((struct device *, void *,
138		    int, int (*)(void *), void *));
139
140static void	kn02ba_wbflush __P((void));
141static unsigned	kn02ba_clkread __P((void));
142
143
144/*
145 * Local declarations.
146 */
147static u_int32_t kmin_tc3_imask;
148
149#ifdef MIPS3
150static unsigned latched_cycle_cnt;
151#endif
152
153
154void
155dec_3min_init()
156{
157	platform.iobus = "tcbus";
158	platform.bus_reset = dec_3min_bus_reset;
159	platform.cons_init = dec_3min_cons_init;
160	platform.iointr = dec_3min_intr;
161	platform.intr_establish = dec_3min_intr_establish;
162	platform.memsize = memsize_bitmap;
163	platform.clkread = kn02ba_clkread;
164
165	/* clear any memory errors */
166	*(u_int32_t *)MIPS_PHYS_TO_KSEG1(KMIN_REG_TIMEOUT) = 0;
167	kn02ba_wbflush();
168
169	ioasic_base = MIPS_PHYS_TO_KSEG1(KMIN_SYS_ASIC);
170
171	/*
172	 * Since all the motherboard interrupts come through the
173	 * IOASIC, it has to be turned off for all the spls and
174	 * since we don't know what kinds of devices are in the
175	 * TURBOchannel option slots, just splhigh().
176	 */
177	splvec.splbio = MIPS_SPL_0_1_2_3;
178	splvec.splnet = MIPS_SPL_0_1_2_3;
179	splvec.spltty = MIPS_SPL_0_1_2_3;
180	splvec.splvm = MIPS_SPL_0_1_2_3;
181	splvec.splclock = MIPS_SPL_0_1_2_3;
182	splvec.splstatclock = MIPS_SPL_0_1_2_3;
183
184	/* enable posting of MIPS_INT_MASK_3 to CAUSE register */
185	*(u_int32_t *)(ioasic_base + IOASIC_IMSK) = KMIN_INTR_CLOCK;
186	/* calibrate cpu_mhz value */
187	mc_cpuspeed(ioasic_base+IOASIC_SLOT_8_START, MIPS_INT_MASK_3);
188
189	*(u_int32_t *)(ioasic_base + IOASIC_LANCE_DECODE) = 0x3;
190	*(u_int32_t *)(ioasic_base + IOASIC_SCSI_DECODE) = 0xe;
191#if 0
192	*(u_int32_t *)(ioasic_base + IOASIC_SCC0_DECODE) = (0x10|4);
193	*(u_int32_t *)(ioasic_base + IOASIC_SCC1_DECODE) = (0x10|6);
194	*(u_int32_t *)(ioasic_base + IOASIC_CSR) = 0x00000f00;
195#endif
196
197	/* sanitize interrupt mask */
198	kmin_tc3_imask = (KMIN_INTR_CLOCK|KMIN_INTR_PSWARN|KMIN_INTR_TIMEOUT);
199	*(u_int32_t *)(ioasic_base + IOASIC_INTR) = 0;
200	*(u_int32_t *)(ioasic_base + IOASIC_IMSK) = kmin_tc3_imask;
201
202	/*
203	 * The kmin memory hardware seems to wrap memory addresses
204	 * with 4Mbyte SIMMs, which causes the physmem computation
205	 * to lose.  Find out how big the SIMMS are and set
206	 * max_ physmem accordingly.
207	 * XXX Do MAXINEs lose the same way?
208	 */
209	physmem_boardmax = KMIN_PHYS_MEMORY_END + 1;
210	if ((KMIN_MSR_SIZE_16Mb & *(int *)MIPS_PHYS_TO_KSEG1(KMIN_REG_MSR))
211			== 0)
212		physmem_boardmax = physmem_boardmax >> 2;
213	physmem_boardmax = MIPS_PHYS_TO_KSEG1(physmem_boardmax);
214
215	sprintf(cpu_model, "DECstation 5000/1%d (3MIN)", cpu_mhz);
216}
217
218/*
219 * Initialize the memory system and I/O buses.
220 */
221static void
222dec_3min_bus_reset()
223{
224
225	/*
226	 * Reset interrupts, clear any errors from newconf probes
227	 */
228
229	*(u_int32_t *)MIPS_PHYS_TO_KSEG1(KMIN_REG_TIMEOUT) = 0;
230	kn02ba_wbflush();
231
232	*(u_int32_t *)(ioasic_base + IOASIC_INTR) = 0;
233	kn02ba_wbflush();
234}
235
236static void
237dec_3min_cons_init()
238{
239	int kbd, crt, screen;
240	extern int tcfb_cnattach __P((int));		/* XXX */
241
242	kbd = crt = screen = 0;
243	prom_findcons(&kbd, &crt, &screen);
244
245	if (screen > 0) {
246#if NRASTERCONSOLE > 0
247		if (tcfb_cnattach(crt) > 0) {
248			scc_lk201_cnattach(ioasic_base, 0x180000);
249			return;
250		}
251#endif
252		printf("No framebuffer device configured for slot %d: ", crt);
253		printf("using serial console\n");
254	}
255	/*
256	 * Delay to allow PROM putchars to complete.
257	 * FIFO depth * character time,
258	 * character time = (1000000 / (defaultrate / 10))
259	 */
260	DELAY(160000000 / 9600);	/* XXX */
261
262	scc_cnattach(ioasic_base, 0x180000);
263}
264
265static void
266dec_3min_intr_establish(dev, cookie, level, handler, arg)
267	struct device *dev;
268	void *cookie;
269	int level;
270	int (*handler) __P((void *));
271	void *arg;
272{
273	unsigned mask;
274
275	switch ((int)cookie) {
276		/* slots 0-2 don't interrupt through the IOASIC. */
277	  case SYS_DEV_OPT0:
278		mask = MIPS_INT_MASK_0;
279		break;
280	  case SYS_DEV_OPT1:
281		mask = MIPS_INT_MASK_1;
282		break;
283	  case SYS_DEV_OPT2:
284		mask = MIPS_INT_MASK_2;
285		break;
286
287	  case SYS_DEV_SCSI:
288		mask = (IOASIC_INTR_SCSI | IOASIC_INTR_SCSI_PTR_LOAD |
289			IOASIC_INTR_SCSI_OVRUN | IOASIC_INTR_SCSI_READ_E);
290		break;
291	  case SYS_DEV_LANCE:
292		mask = KMIN_INTR_LANCE;
293		break;
294	  case SYS_DEV_SCC0:
295		mask = KMIN_INTR_SCC_0;
296		break;
297	  case SYS_DEV_SCC1:
298		mask = KMIN_INTR_SCC_1;
299		break;
300	  default:
301#ifdef DIAGNOSTIC
302		printf("warning: enabling unknown intr %x\n", (int)cookie);
303#endif
304		return;
305	}
306
307#if defined(DEBUG)
308	printf("3MIN: imask %x, enabling slot %d, dev %p handler %p\n",
309	    kmin_tc3_imask, (int)cookie, dev, handler);
310#endif
311
312	/*
313	 * Enable the interrupt  handler, and if it's an IOASIC
314	 * slot, set the IOASIC interrupt mask.
315	 * Otherwise, set the appropriate spl level in the R3000
316	 * register.
317	 * Be careful to set handlers before enabling, and disable
318	 * interrupts before clearing handlers.
319	 */
320
321	/* Set the interrupt handler and argument ... */
322	intrtab[(int)cookie].ih_func = handler;
323	intrtab[(int)cookie].ih_arg = arg;
324	/* ... and set the relevant mask */
325	switch ((int)cookie) {
326	case SYS_DEV_OPT0:
327	case SYS_DEV_OPT1:
328	case SYS_DEV_OPT2:
329		/* it's an option slot */
330		{
331		int s = splhigh();
332		s |= mask;
333		splx(s);
334		}
335		break;
336	default:
337		/* it's a baseboard device going via the IOASIC */
338		kmin_tc3_imask |= mask;
339		break;
340	}
341
342	*(u_int32_t *)(ioasic_base + IOASIC_IMSK) = kmin_tc3_imask;
343	kn02ba_wbflush();
344}
345
346
347#define CHECKINTR(slot, bits)					\
348    do {							\
349	if (can_serve & (bits)) {				\
350		intrcnt[slot] += 1;				\
351		(*intrtab[slot].ih_func)(intrtab[slot].ih_arg);	\
352	}							\
353    } while (0)
354
355static void
356dec_3min_intr(status, cause, pc, ipending)
357	unsigned status;
358	unsigned cause;
359	unsigned pc;
360	unsigned ipending;
361{
362	static int user_warned = 0;
363	static int intr_depth = 0;
364	u_int32_t old_mask;
365
366	intr_depth++;
367	old_mask = *(u_int32_t *)(ioasic_base + IOASIC_IMSK);
368
369	if (ipending & MIPS_INT_MASK_4)
370		prom_haltbutton();
371
372	if (ipending & MIPS_INT_MASK_3) {
373		/* NB: status & MIPS_INT_MASK3 must also be set */
374		/* masked interrupts are still observable */
375		u_int32_t intr, imsk, can_serve, turnoff;
376
377		turnoff = 0;
378		intr = *(u_int32_t *)(ioasic_base + IOASIC_INTR);
379		imsk = *(u_int32_t *)(ioasic_base + IOASIC_IMSK);
380		can_serve = intr & imsk;
381
382		if (intr & IOASIC_INTR_SCSI_PTR_LOAD) {
383			turnoff |= IOASIC_INTR_SCSI_PTR_LOAD;
384#ifdef notdef
385			asc_dma_intr();
386#endif
387		}
388
389		if (intr & (IOASIC_INTR_SCSI_OVRUN | IOASIC_INTR_SCSI_READ_E))
390			turnoff |= IOASIC_INTR_SCSI_OVRUN | IOASIC_INTR_SCSI_READ_E;
391
392		if (intr & IOASIC_INTR_LANCE_READ_E)
393			turnoff |= IOASIC_INTR_LANCE_READ_E;
394
395		if (turnoff)
396			*(u_int32_t *)(ioasic_base + IOASIC_INTR) = ~turnoff;
397
398		if (intr & KMIN_INTR_TIMEOUT) {
399			kn02ba_errintr();
400			pmax_memerr_evcnt.ev_count++;
401		}
402
403		if (intr & KMIN_INTR_CLOCK) {
404			struct clockframe cf;
405
406			__asm __volatile("lbu $0,48(%0)" ::
407				"r"(ioasic_base + IOASIC_SLOT_8_START));
408#ifdef MIPS3
409			if (CPUISMIPS3) {
410				latched_cycle_cnt = mips3_cp0_count_read();
411			}
412#endif
413			cf.pc = pc;
414			cf.sr = status;
415			hardclock(&cf);
416			pmax_clock_evcnt.ev_count++;
417		}
418
419		/* If clock interrups were enabled, re-enable them ASAP. */
420		if (old_mask & KMIN_INTR_CLOCK) {
421			/* ioctl interrupt mask to splclock and higher */
422			*(u_int32_t *)(ioasic_base + IOASIC_IMSK)
423				= old_mask &
424					~(KMIN_INTR_SCC_0|KMIN_INTR_SCC_1 |
425					  IOASIC_INTR_LANCE|IOASIC_INTR_SCSI);
426			kn02ba_wbflush();
427			_splset(MIPS_SR_INT_IE | (status & MIPS_INT_MASK_3));
428		}
429
430		if (intr_depth > 1)
431			 goto done;
432
433		CHECKINTR(SYS_DEV_SCC0, IOASIC_INTR_SCC_0);
434		CHECKINTR(SYS_DEV_SCC1, IOASIC_INTR_SCC_1);
435
436#ifdef notyet /* untested */
437		/* If tty interrupts were enabled, re-enable them ASAP. */
438		if ((old_mask & (KMIN_INTR_SCC_1|KMIN_INTR_SCC_0)) ==
439		     (KMIN_INTR_SCC_1|KMIN_INTR_SCC_0)) {
440			*imaskp = old_mask &
441			  ~(KMIN_INTR_SCC_0|KMIN_INTR_SCC_1 |
442			  IOASIC_INTR_LANCE|IOASIC_INTR_SCSI);
443			kn02ba_wbflush();
444		}
445
446		/* XXX until we know about SPLs of TC options. */
447		if (intr_depth > 1)
448			 goto done;
449#endif
450		CHECKINTR(SYS_DEV_LANCE, IOASIC_INTR_LANCE);
451		CHECKINTR(SYS_DEV_SCSI, IOASIC_INTR_SCSI);
452
453		if (user_warned && ((intr & KMIN_INTR_PSWARN) == 0)) {
454			printf("%s\n", "Power supply ok now.");
455			user_warned = 0;
456		}
457		if ((intr & KMIN_INTR_PSWARN) && (user_warned < 3)) {
458			user_warned++;
459			printf("%s\n", "Power supply overheating");
460		}
461	}
462	if ((ipending & MIPS_INT_MASK_0) && intrtab[SYS_DEV_OPT0].ih_func) {
463		(*intrtab[SYS_DEV_OPT0].ih_func)(intrtab[SYS_DEV_OPT0].ih_arg);
464		intrcnt[SYS_DEV_OPT0]++;
465 	}
466
467	if ((ipending & MIPS_INT_MASK_1) && intrtab[SYS_DEV_OPT1].ih_func) {
468		(*intrtab[SYS_DEV_OPT1].ih_func)(intrtab[SYS_DEV_OPT1].ih_arg);
469		intrcnt[SYS_DEV_OPT1]++;
470	}
471	if ((ipending & MIPS_INT_MASK_2) && intrtab[SYS_DEV_OPT2].ih_func) {
472		(*intrtab[SYS_DEV_OPT2].ih_func)(intrtab[SYS_DEV_OPT2].ih_arg);
473		intrcnt[SYS_DEV_OPT2]++;
474	}
475
476done:
477	/* restore entry state */
478	splhigh();
479	intr_depth--;
480	*(u_int32_t *)(ioasic_base + IOASIC_IMSK) = old_mask;
481
482	_splset(MIPS_SR_INT_IE | (status & ~cause & MIPS_HARD_INT_MASK));
483}
484
485
486
487/*
488 ************************************************************************
489 * Extra functions
490 ************************************************************************
491 */
492
493static void
494kn02ba_wbflush()
495{
496	/* read twice IOASIC_IMSK */
497	__asm __volatile("lw $0,%0; lw $0,%0" ::
498	    "i"(MIPS_PHYS_TO_KSEG1(KMIN_REG_IMSK)));
499}
500
501static unsigned
502kn02ba_clkread()
503{
504#ifdef MIPS3
505	if (CPUISMIPS3) {
506		u_int32_t mips3_cycles;
507
508		mips3_cycles = mips3_cp0_count_read() - latched_cycle_cnt;
509		/* XXX divides take 78 cycles: approximate with * 41/2048 */
510		return((mips3_cycles >> 6) + (mips3_cycles >> 8) +
511		       (mips3_cycles >> 11));
512	}
513#endif
514	return 0;
515}
516