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