dec_3min.c revision 1.14
1/*	$NetBSD: dec_3min.c,v 1.14 1999/04/26 09:23:23 nisimura 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.14 1999/04/26 09:23:23 nisimura 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/autoconf.h>		/* intr_arg_t */
87#include <machine/sysconf.h>
88
89#include <mips/mips_param.h>		/* hokey spl()s */
90#include <mips/mips/mips_mcclock.h>	/* mcclock CPUspeed estimation */
91
92/* all these to get ioasic_base */
93#include <sys/device.h>			/* struct cfdata for.. */
94#include <dev/tc/tcvar.h>		/* tc type definitions for.. */
95#include <dev/tc/ioasicreg.h>		/* ioasic interrrupt masks */
96#include <dev/tc/ioasicvar.h>		/* ioasic_base */
97
98#include <pmax/pmax/clockreg.h>
99#include <pmax/pmax/turbochannel.h>
100#include <pmax/pmax/pmaxtype.h>
101
102#include <pmax/pmax/machdep.h>		/* XXXjrs replace with vectors */
103
104#include <pmax/pmax/kmin.h>		/* 3min baseboard addresses */
105#include <pmax/pmax/dec_kn02_subr.h>	/* 3min/maxine memory errors */
106
107
108/*
109 * forward declarations
110 */
111void		dec_3min_init __P((void));
112void		dec_3min_os_init __P((void));
113void		dec_3min_bus_reset __P((void));
114void		dec_3maxplus_device_register __P((struct device *, void *));
115
116void		dec_3min_enable_intr
117		   __P ((u_int slotno, int (*handler) __P((intr_arg_t sc)),
118			 intr_arg_t sc, int onoff));
119int		dec_3min_intr __P((u_int mask, u_int pc,
120			      u_int statusReg, u_int causeReg));
121
122void		dec_3min_device_register __P((struct device *, void *));
123void		dec_3min_cons_init __P((void));
124
125
126/*
127 * Local declarations.
128 */
129void dec_3min_mcclock_cpuspeed __P((volatile struct chiptime *mcclock_addr,
130			       int clockmask));
131u_long	kmin_tc3_imask;
132
133void kn02ba_wbflush __P((void));
134unsigned kn02ba_clkread __P((void));
135extern unsigned (*clkread) __P((void));
136
137/*
138 * Fill in platform struct.
139 */
140void
141dec_3min_init()
142{
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	sprintf(cpu_model, "DECstation 5000/1%d (3MIN)", cpu_mhz);
154}
155
156
157/*
158 * Initalize the memory system and I/O buses.
159 */
160void
161dec_3min_bus_reset()
162{
163
164	/*
165	 * Reset interrupts, clear any errors from newconf probes
166	 */
167
168	*(volatile u_int *)MIPS_PHYS_TO_KSEG1(KMIN_REG_TIMEOUT) = 0;
169	kn02ba_wbflush();
170
171	*(volatile u_int *)IOASIC_REG_INTR(ioasic_base) = 0;
172	kn02ba_wbflush();
173
174}
175
176
177void
178dec_3min_os_init()
179{
180	ioasic_base = MIPS_PHYS_TO_KSEG1(KMIN_SYS_ASIC);
181	mips_hardware_intr = dec_3min_intr;
182	tc_enable_interrupt = dec_3min_enable_intr;
183	kmin_tc3_imask = (KMIN_INTR_CLOCK | KMIN_INTR_PSWARN |
184		KMIN_INTR_TIMEOUT);
185
186	/*
187	 * All the baseboard interrupts come through the I/O ASIC
188	 * (at INT_MASK_3), so  it has to be turned off for all the spls.
189	 * Since we don't know what kinds of devices are in the
190	 * turbochannel option slots, just block them all.
191	 */
192	Mach_splbio = cpu_spl3;
193	Mach_splnet = cpu_spl3;
194	Mach_spltty = cpu_spl3;
195	Mach_splimp = cpu_spl3;
196	Mach_splclock = cpu_spl3;
197	Mach_splstatclock = cpu_spl3;
198	mcclock_addr = (volatile struct chiptime *)
199		MIPS_PHYS_TO_KSEG1(KMIN_SYS_CLOCK);
200	dec_3min_mcclock_cpuspeed(mcclock_addr, MIPS_INT_MASK_3);
201
202	*(volatile u_int *)(ioasic_base + IOASIC_LANCE_DECODE) = 0x3;
203	*(volatile u_int *)(ioasic_base + IOASIC_SCSI_DECODE) = 0xe;
204#if 0
205	*(volatile u_int *)(ioasic_base + IOASIC_SCC0_DECODE) = (0x10|4);
206	*(volatile u_int *)(ioasic_base + IOASIC_SCC1_DECODE) = (0x10|6);
207	*(volatile u_int *)(ioasic_base + IOASIC_CSR) = 0x00000f00;
208#endif
209	/*
210	 * Initialize interrupts.
211	 */
212	*(u_int *)IOASIC_REG_IMSK(ioasic_base) = KMIN_IM0;
213	*(u_int *)IOASIC_REG_INTR(ioasic_base) = 0;
214
215	/* clear any memory errors from probes */
216
217	*(volatile u_int *)MIPS_PHYS_TO_KSEG1(KMIN_REG_TIMEOUT) = 0;
218	kn02ba_wbflush();
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	 */
226	physmem_boardmax = KMIN_PHYS_MEMORY_END + 1;
227	if ((*(int*)(MIPS_PHYS_TO_KSEG1(KMIN_REG_MSR)) &
228	     KMIN_MSR_SIZE_16Mb) == 0)
229		physmem_boardmax = physmem_boardmax >> 2;
230	physmem_boardmax = MIPS_PHYS_TO_KSEG1(physmem_boardmax);
231
232	* (volatile u_int *)MIPS_PHYS_TO_KSEG1(KMIN_REG_IMSK) =
233	  kmin_tc3_imask |
234	  (KMIN_IM0 & ~(KN03_INTR_TC_0|KN03_INTR_TC_1|KN03_INTR_TC_2));
235
236	/* R4000 3MIN can ultilize on-chip counter */
237	clkread = kn02ba_clkread;
238}
239
240
241void
242dec_3min_cons_init()
243{
244	/* notyet */
245}
246
247
248void
249dec_3min_device_register(dev, aux)
250	struct device *dev;
251	void *aux;
252{
253	panic("dec_3min_device_register unimplemented");
254}
255
256
257void
258dec_3min_enable_intr(slotno, handler, sc, on)
259	unsigned int slotno;
260	int (*handler) __P((void* softc));
261	void *sc;
262	int on;
263{
264	unsigned mask;
265
266	switch (slotno) {
267		/* slots 0-2 don't interrupt through the IOASIC. */
268	case 0:
269		mask = MIPS_INT_MASK_0;	break;
270	case 1:
271		mask = MIPS_INT_MASK_1; break;
272	case 2:
273		mask = MIPS_INT_MASK_2; break;
274
275	case KMIN_SCSI_SLOT:
276		mask = (IOASIC_INTR_SCSI | IOASIC_INTR_SCSI_PTR_LOAD |
277			IOASIC_INTR_SCSI_OVRUN | IOASIC_INTR_SCSI_READ_E);
278		break;
279
280	case KMIN_LANCE_SLOT:
281		mask = KMIN_INTR_LANCE;
282		break;
283	case KMIN_SCC0_SLOT:
284		mask = KMIN_INTR_SCC_0;
285		break;
286	case KMIN_SCC1_SLOT:
287		mask = KMIN_INTR_SCC_1;
288		break;
289	case KMIN_ASIC_SLOT:
290		mask = KMIN_INTR_ASIC;
291		break;
292	default:
293		return;
294	}
295
296#if defined(DEBUG) || defined(DIAGNOSTIC)
297	printf("3MIN: imask %lx, %sabling slot %d, sc %p handler %p\n",
298	       kmin_tc3_imask, (on? "en" : "dis"), slotno, sc, handler);
299#endif
300
301	/*
302	 * Enable the interrupt  handler, and if it's an IOASIC
303	 * slot, set the IOASIC interrupt mask.
304	 * Otherwise, set the appropriate spl level in the R3000
305	 * register.
306	 * Be careful to set handlers  before enabling, and disable
307	 * interrupts before clearing handlers.
308	 */
309
310	if (on) {
311		/* Set the interrupt handler and argument ... */
312		tc_slot_info[slotno].intr = handler;
313		tc_slot_info[slotno].sc = sc;
314
315		/* ... and set the relevant mask */
316		if (slotno <= 2) {
317			/* it's an option slot */
318			int s = splhigh();
319			s  |= mask;
320			splx(s);
321		} else {
322			/* it's a baseboard device going via the ASIC */
323			kmin_tc3_imask |= mask;
324		}
325	} else {
326		/* Clear the relevant mask... */
327		if (slotno <= 2) {
328			/* it's an option slot */
329			int s = splhigh();
330			printf("kmin_intr: cannot disable option slot %d\n",
331			    slotno);
332			s &= ~mask;
333			splx(s);
334		} else {
335			/* it's a baseboard device going via the ASIC */
336			kmin_tc3_imask &= ~mask;
337		}
338		/* ... and clear the handler */
339		tc_slot_info[slotno].intr = 0;
340		tc_slot_info[slotno].sc = 0;
341	}
342}
343
344
345
346/*
347 * 3min hardware interrupts. (DECstation 5000/1xx)
348 */
349int
350dec_3min_intr(mask, pc, statusReg, causeReg)
351	unsigned mask;
352	unsigned pc;
353	unsigned statusReg;
354	unsigned causeReg;
355{
356	u_int intr;
357	volatile struct chiptime *c =
358	    (volatile struct chiptime *) MIPS_PHYS_TO_KSEG1(KMIN_SYS_CLOCK);
359	volatile u_int * const imaskp =
360		(volatile u_int *)MIPS_PHYS_TO_KSEG1(KMIN_REG_IMSK);
361	volatile u_int * const intrp =
362		(volatile u_int *)MIPS_PHYS_TO_KSEG1(KMIN_REG_INTR);
363	unsigned int old_mask;
364	struct clockframe cf;
365	int temp;
366	static int user_warned = 0;
367
368	static int intr_depth = 0;
369	intr_depth++;
370
371	old_mask = *imaskp;
372
373	if (mask & MIPS_INT_MASK_4)
374		prom_haltbutton();
375
376	if (mask & MIPS_INT_MASK_3) {
377		/* NB: status & MIPS_INT_MASK3 must also be set */
378		/* masked interrupts are still observable */
379		intr = *intrp & old_mask & kmin_tc3_imask;
380
381		if (intr & IOASIC_INTR_SCSI_PTR_LOAD) {
382			*intrp &= ~IOASIC_INTR_SCSI_PTR_LOAD;
383#ifdef notdef
384			asc_dma_intr();
385#endif
386		}
387
388		if (intr & (IOASIC_INTR_SCSI_OVRUN | IOASIC_INTR_SCSI_READ_E))
389			*intrp &= ~(IOASIC_INTR_SCSI_OVRUN | IOASIC_INTR_SCSI_READ_E);
390
391		if (intr & IOASIC_INTR_LANCE_READ_E)
392			*intrp &= ~IOASIC_INTR_LANCE_READ_E;
393
394		if (intr & KMIN_INTR_TIMEOUT)
395			kn02ba_errintr();
396
397		if (intr & KMIN_INTR_CLOCK) {
398			extern u_int32_t mips3_cycle_count __P((void));
399
400			temp = c->regc;	/* XXX clear interrupt bits */
401			cf.pc = pc;
402			cf.sr = statusReg;
403#ifdef MIPS3
404			if (CPUISMIPS3) {
405				latched_cycle_cnt = mips3_cycle_count();
406			}
407#endif
408			hardclock(&cf);
409			intrcnt[HARDCLOCK]++;
410		}
411
412		/* If clock interrups were enabled, re-enable them ASAP. */
413		if (old_mask & KMIN_INTR_CLOCK) {
414			/*  ioctl interrupt mask to splclock and higher */
415			*imaskp = old_mask &
416			  ~(KMIN_INTR_SCC_0|KMIN_INTR_SCC_1 |
417			  IOASIC_INTR_LANCE|IOASIC_INTR_SCSI);
418			kn02ba_wbflush();
419			splx(MIPS_SR_INT_IE | (statusReg & MIPS_INT_MASK_3));
420		}
421
422		if (intr_depth > 1)
423			 goto done;
424
425		if ((intr & KMIN_INTR_SCC_0) &&
426		    tc_slot_info[KMIN_SCC0_SLOT].intr) {
427			(*(tc_slot_info[KMIN_SCC0_SLOT].intr))
428			  (tc_slot_info[KMIN_SCC0_SLOT].sc);
429			intrcnt[SERIAL0_INTR]++;
430		}
431
432		if ((intr & KMIN_INTR_SCC_1) &&
433		    tc_slot_info[KMIN_SCC1_SLOT].intr) {
434			(*(tc_slot_info[KMIN_SCC1_SLOT].intr))
435			  (tc_slot_info[KMIN_SCC1_SLOT].sc);
436			intrcnt[SERIAL1_INTR]++;
437		}
438
439#ifdef notyet /* untested */
440		/* If tty interrupts were enabled, re-enable them ASAP. */
441		if ((old_mask & (KMIN_INTR_SCC_1|KMIN_INTR_SCC_0)) ==
442		     (KMIN_INTR_SCC_1|KMIN_INTR_SCC_0)) {
443			*imaskp = old_mask &
444			  ~(KMIN_INTR_SCC_0|KMIN_INTR_SCC_1 |
445			  IOASIC_INTR_LANCE|IOASIC_INTR_SCSI);
446			kn02ba_wbflush();
447		}
448
449		/* XXX until we know about SPLs of TC options. */
450		if (intr_depth > 1)
451			 goto done;
452#endif
453		if ((intr & IOASIC_INTR_LANCE) &&
454		    tc_slot_info[KMIN_LANCE_SLOT].intr) {
455			(*(tc_slot_info[KMIN_LANCE_SLOT].intr))
456			  (tc_slot_info[KMIN_LANCE_SLOT].sc);
457			intrcnt[LANCE_INTR]++;
458		}
459
460		if ((intr & IOASIC_INTR_SCSI) &&
461		    tc_slot_info[KMIN_SCSI_SLOT].intr) {
462			(*(tc_slot_info[KMIN_SCSI_SLOT].intr))
463			  (tc_slot_info[KMIN_SCSI_SLOT].sc);
464			intrcnt[SCSI_INTR]++;
465		}
466
467		if (user_warned && ((intr & KMIN_INTR_PSWARN) == 0)) {
468			printf("%s\n", "Power supply ok now.");
469			user_warned = 0;
470		}
471		if ((intr & KMIN_INTR_PSWARN) && (user_warned < 3)) {
472			user_warned++;
473			printf("%s\n", "Power supply overheating");
474		}
475	}
476	if ((mask & MIPS_INT_MASK_0) && tc_slot_info[0].intr) {
477		(*tc_slot_info[0].intr)(tc_slot_info[0].sc);
478		intrcnt[SLOT0_INTR]++;
479 	}
480
481	if ((mask & MIPS_INT_MASK_1) && tc_slot_info[1].intr) {
482		(*tc_slot_info[1].intr)(tc_slot_info[1].sc);
483		intrcnt[SLOT1_INTR]++;
484	}
485	if ((mask & MIPS_INT_MASK_2) && tc_slot_info[2].intr) {
486		(*tc_slot_info[2].intr)(tc_slot_info[2].sc);
487		intrcnt[SLOT2_INTR]++;
488	}
489
490done:
491	/* restore entry state */
492	splhigh();
493	intr_depth--;
494	*imaskp = old_mask;
495
496
497	return(MIPS_SR_INT_IE | (statusReg & ~causeReg & MIPS_HARD_INT_MASK));
498}
499
500
501
502/*
503 ************************************************************************
504 * Extra functions
505 ************************************************************************
506 */
507
508
509
510
511/*
512 * Count instructions between 4ms mcclock interrupt requests,
513 * using the ioasic clock-interrupt-pending bit to determine
514 * when clock ticks occur.
515 * Set up iosiac to allow only clock interrupts, then
516 * call
517 */
518void
519dec_3min_mcclock_cpuspeed(mcclock_addr, clockmask)
520	volatile struct chiptime *mcclock_addr;
521	int clockmask;
522{
523	volatile u_int * ioasic_intrmaskp =
524		(volatile u_int *)MIPS_PHYS_TO_KSEG1(KMIN_REG_IMSK);
525
526	int saved_imask = *ioasic_intrmaskp;
527
528	/* Allow only clock interrupts through ioasic. */
529	*ioasic_intrmaskp = KMIN_INTR_CLOCK;
530	kn02ba_wbflush();
531
532	mc_cpuspeed(mcclock_addr, clockmask);
533
534	*ioasic_intrmaskp = saved_imask;
535	kn02ba_wbflush();
536}
537
538void
539kn02ba_wbflush()
540{
541	/* read twice IOASIC_INTR register */
542	__asm __volatile("lw $0,0xbc040120; lw $0,0xbc040120");
543}
544
545unsigned
546kn02ba_clkread()
547{
548#ifdef MIPS3
549	extern u_int32_t mips3_cycle_count __P((void));
550	extern u_long latched_cycle_cnt;
551
552	if (CPUISMIPS3) {
553		u_int32_t mips3_cycles;
554
555		mips3_cycles = mips3_cycle_count() - latched_cycle_cnt;
556#if 0
557		/* XXX divides take 78 cycles: approximate with * 41/2048 */
558		return (mips3_cycles / cpu_mhz);
559#else
560		return((mips3_cycles >> 6) + (mips3_cycles >> 8) +
561		       (mips3_cycles >> 11));
562#endif
563	}
564#endif
565	return 0;
566}
567