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