xref: /netbsd/sys/arch/mipsco/mipsco/mips_3x30.c (revision bf9ec67e)
1 /*	$NetBSD: mips_3x30.c,v 1.5 2001/03/30 23:51:14 wdk Exp $	*/
2 
3 /*
4  * Copyright (c) 2000 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Wayne Knowles
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by the NetBSD
21  *        Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/device.h>
42 #include <sys/proc.h>
43 #include <sys/kernel.h>
44 
45 #include <machine/trap.h>
46 #include <machine/psl.h>
47 #include <machine/cpu.h>
48 #include <machine/intr.h>
49 #include <machine/mainboard.h>
50 #include <machine/sysconf.h>
51 
52 extern void MachFPInterrupt (u_int, u_int, u_int, struct frame *);
53 
54 /* Local functions */
55 void pizazz_init (void);
56 void pizazz_intr (u_int, u_int, u_int, u_int);
57 int  pizazz_level0_intr (void *);
58 void pizazz_level5_intr (int, int, int);
59 void pizazz_intr_establish  (int, int (*)(void *), void *);
60 
61 #define INT_MASK_FPU MIPS_INT_MASK_3
62 
63 void
64 pizazz_init(void)
65 {
66 	platform.iobus = "obio";
67 	platform.cons_init = NULL;
68 	platform.iointr = pizazz_intr;
69 	platform.intr_establish = pizazz_intr_establish;
70 
71 	pizazz_intr_establish(SYS_INTR_LEVEL0, pizazz_level0_intr, NULL);
72 
73 	strcpy(cpu_model, "Mips 3230 Magnum (Pizazz)");
74 	cpuspeed = 25;
75 }
76 
77 #define	HANDLE_INTR(intr, mask)					\
78 	do {							\
79 		if (ipending & (mask)) {			\
80 			CALL_INTR(intr);			\
81 		}						\
82 	} while (0)
83 
84 void
85 pizazz_intr(status, cause, pc, ipending)
86 	u_int status;	/* status register at time of the exception */
87 	u_int cause;	/* cause register at time of exception */
88 	u_int pc;	/* program counter where to continue */
89 	u_int ipending;
90 {
91 	/* handle clock interrupts ASAP */
92 	if (ipending & MIPS_INT_MASK_2) {	        /* Timer Interrupt */
93 	        void rambo_clkintr (struct clockframe *);
94 	        struct clockframe cf;
95 
96 		cf.pc = pc;
97 		cf.sr = status;
98 
99 		rambo_clkintr(&cf);
100 
101 		/* keep clock interrupts enabled when we return */
102 		cause &= ~MIPS_INT_MASK_2;
103 	}
104 
105 	/* If clock interrupts were enabled, re-enable them ASAP. */
106 	_splset(MIPS_SR_INT_IE | (status & MIPS_INT_MASK_2));
107 
108 	if (ipending & MIPS_INT_MASK_5)		/* level 5 interrupt */
109 		pizazz_level5_intr(pc, cause, status);
110 
111 	HANDLE_INTR(SYS_INTR_FDC,	MIPS_INT_MASK_4);
112 	HANDLE_INTR(SYS_INTR_SCSI,	MIPS_INT_MASK_1);
113 	HANDLE_INTR(SYS_INTR_LEVEL0,	MIPS_INT_MASK_0);
114 
115 	/* XXX:  Keep FDC interrupt masked off */
116 	cause &= ~(MIPS_INT_MASK_0 | MIPS_INT_MASK_1 | MIPS_INT_MASK_5);
117 
118 	_splset((status & ~cause & MIPS_HARD_INT_MASK) | MIPS_SR_INT_IE);
119 
120 	/* FPU nofiticaition */
121 	if (ipending & INT_MASK_FPU) {
122 		if (!USERMODE(status))
123 			panic("kernel used FPU: PC %x, CR %x, SR %x",
124 			      pc, cause, status);
125 		MachFPInterrupt(status, cause, pc, curproc->p_md.md_regs);
126 	}
127 }
128 
129 /*
130  * Level 0 interrupt handler
131  *
132  * Pizazz shares Lance, SCC, Expansion slot and Keyboard on level 0
133  * A secondary interrupt status register shows the real interrupt source
134  */
135 int
136 pizazz_level0_intr(arg)
137 	void *arg;
138 {
139 	register int stat;
140 
141 	/* stat register is active low */
142 	stat = ~*(volatile u_char *)INTREG_0;
143 
144 	if (stat & INT_ExpSlot)
145 		CALL_INTR(SYS_INTR_ATBUS);
146 
147 	if (stat & INT_Lance)
148 		CALL_INTR(SYS_INTR_ETHER);
149 
150 	if (stat & INT_SCC)
151 		CALL_INTR(SYS_INTR_SCC0);
152 
153 	return 0;
154 }
155 
156 /*
157  * Motherboard Parity Error
158  */
159 void
160 pizazz_level5_intr(pc, cause, status)
161 	int pc;
162 	int cause;
163 	int status;
164 {
165 	u_int32_t ereg;
166 
167 	ereg = *(u_int32_t *)RAMBO_ERREG;
168 
169 	printf("interrupt: pc=%p cr=%x sr=%x\n", (void *)pc, cause, status);
170 	printf("parity error: %p mask: 0x%x\n", (void *)ereg, ereg & 0xf);
171 	panic("memory fault");
172 }
173 
174 void
175 pizazz_intr_establish(level, func, arg)
176 	int level;
177 	int (*func) (void *);
178 	void *arg;
179 {
180 	if (level < 0 || level >= MAX_INTR_COOKIES)
181 		panic("invalid interrupt level");
182 
183 	if (intrtab[level].ih_fun != NULL)
184 		panic("cannot share interrupt %d", level);
185 
186 	intrtab[level].ih_fun = func;
187 	intrtab[level].ih_arg = arg;
188 }
189