news5000.c revision 1.1 1 /* $NetBSD: news5000.c,v 1.1 1999/12/22 05:53:21 tsubai Exp $ */
2
3 /*-
4 * Copyright (C) 1999 SHIMIZU Ryo. 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. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/kernel.h>
32
33 #include <machine/adrsmap.h>
34 #include <machine/cpu.h>
35 #include <machine/intr.h>
36
37 #include <newsmips/apbus/apbusvar.h>
38 #include <newsmips/newsmips/machid.h>
39
40 static void level5_interrupt __P((void));
41 static void level4_interrupt __P((void));
42 static void level3_interrupt __P((void));
43 static void level2_interrupt __P((unsigned int, unsigned int));
44 static void level1_interrupt __P((void));
45 static void level0_interrupt __P((void));
46
47 static void abif_error4 __P((void));
48
49 /*
50 * Handle news5000 interrupts.
51 */
52 int
53 news5000_intr(mask, pc, statusReg, causeReg)
54 u_int mask;
55 u_int pc; /* program counter where to continue */
56 u_int statusReg; /* status register at time of the exception */
57 u_int causeReg; /* cause register at time of exception */
58 {
59 if (mask & MIPS_INT_MASK_2) {
60 level2_interrupt(pc,statusReg);
61 apbus_wbflush();
62 causeReg &= ~MIPS_INT_MASK_2;
63 }
64 /* If clock interrupts were enabled, re-enable them ASAP. */
65 splx(MIPS_SR_INT_IE | (statusReg & MIPS_INT_MASK_2));
66
67 if (mask & MIPS_INT_MASK_5) {
68 level5_interrupt();
69 apbus_wbflush();
70 causeReg &= ~MIPS_INT_MASK_5;
71 }
72
73 if (mask & MIPS_INT_MASK_4) {
74 level4_interrupt();
75 apbus_wbflush();
76 causeReg &= ~MIPS_INT_MASK_4;
77 }
78
79 if (mask & MIPS_INT_MASK_3) {
80 level3_interrupt();
81 apbus_wbflush();
82 causeReg &= ~MIPS_INT_MASK_3;
83 }
84
85 if (mask & MIPS_INT_MASK_1) {
86 level1_interrupt();
87 apbus_wbflush();
88 causeReg &= ~MIPS_INT_MASK_1;
89 }
90
91 if (mask & MIPS_INT_MASK_0) {
92 level0_interrupt();
93 apbus_wbflush();
94 causeReg &= ~MIPS_INT_MASK_0;
95 }
96
97 return ((statusReg & ~causeReg & MIPS_HARD_INT_MASK) | MIPS_SR_INT_IE);
98 }
99
100 void
101 level5_interrupt()
102 {
103 printf("level5 interrupt\n");
104 }
105
106 void
107 level4_interrupt()
108 {
109 volatile int *intenp = (volatile int *)NEWS5000_INTMASK4;
110 int int4stat, saved_inten;
111
112 int4stat = *(volatile int *)NEWS5000_INTSTAT4;
113 saved_inten = *intenp;
114 *intenp = 0;
115 if (int4stat & NEWS5000_INT4_SBIF) {
116 printf("SBIF ERROR\n");
117 /* sbif_error4(); */
118 } else if (int4stat & NEWS5000_INT4_MFBIF) {
119 printf("MBIF ERROR\n");
120 /*
121 mbif_error4();
122 if (fxif_error4)
123 fxif_error4();
124 */
125 } else if (int4stat & NEWS5000_INT4_ABIF) {
126 /* printf("ABIF ERROR\n"); */
127 abif_error4();
128 }
129 *intenp = saved_inten;
130 }
131
132 static void
133 abif_error4()
134 {
135 #define AB_BERRADR 0xb4c00018
136 #define AB_BERRDATA 0xb4c00020
137 #define AB_BERRPARITY 0xb4c00028
138
139 int stat;
140
141 printf("abif_error4\n");
142
143 stat = *(volatile u_int *)NEWS5000_APBUS_INTSTAT &
144 *(volatile u_int *)NEWS5000_APBUS_INTMASK;
145
146 if (stat & NEWS5000_INTAPBUS_DMAADDRESS) {
147 printf("AB I/F: DMA address error\n");
148 }
149 if (stat & (NEWS5000_INTAPBUS_RDTIMEO|NEWS5000_INTAPBUS_WRTIMEO)) {
150 if (stat & NEWS5000_INTAPBUS_RDTIMEO)
151 printf("AB I/F: read timeout\n");
152 if (stat & NEWS5000_INTAPBUS_WRTIMEO)
153 printf("AB I/F: write timeout\n");
154
155 printf(" address = %x:%x\n",
156 *(volatile u_int *)AB_BERRADR, *(volatile u_int *)(AB_BERRADR + 4));
157 }
158 *(volatile u_int *)NEWS5000_APBUS_INTSTAT = stat;
159 }
160
161 void
162 level3_interrupt()
163 {
164 printf("level3 interrupt\n");
165 }
166
167 void
168 level2_interrupt(pc, statusReg)
169 unsigned int pc;
170 unsigned int statusReg;
171 {
172 #ifdef DEBUG
173 static int l2cnt = 0;
174 #endif
175 unsigned int int2stat;
176 struct clockframe cf;
177
178 int2stat = *(volatile unsigned int *)NEWS5000_INTSTAT2;
179
180 #ifdef DEBUG
181 l2cnt++;
182 if (l2cnt == 50) {
183 *(volatile unsigned int *)NEWS5000_LED3 = 1;
184 }
185 if (l2cnt == 100) {
186 *(volatile unsigned int *)NEWS5000_LED3 = 0;
187 l2cnt = 0;
188 }
189 #endif
190
191 if (int2stat & NEWS5000_INT2_TIMER0) {
192 *(volatile unsigned int *)NEWS5000_TIMER0 = 1;
193
194 cf.pc = pc;
195 cf.sr = statusReg;
196
197 hardclock(&cf);
198 intrcnt[HARDCLOCK_INTR]++;
199 }
200
201 if (int2stat & NEWS5000_INT2_TIMER1) {
202 *(volatile unsigned int *)NEWS5000_TIMER1 = 1;
203 }
204 }
205
206 void
207 level1_interrupt()
208 {
209 unsigned int int1stat;
210 int nintcall;
211
212 int1stat = *(volatile unsigned int *)NEWS5000_INTSTAT1;
213
214 if (int1stat) {
215 /* printf("level1 interrupt (%08x)\n", int1stat); */
216 nintcall = apbus_intr_call(1,int1stat);
217
218 if (!nintcall) {
219 printf("level1_interrupt: no match interrupt mask! %04x\n",int1stat);
220 }
221 } else {
222 printf("level1 stray interrupt?\n");
223 }
224
225 }
226
227 void
228 level0_interrupt()
229 {
230 unsigned int int0stat;
231 int nintcall;
232
233 int0stat = *(volatile unsigned int *)NEWS5000_INTSTAT0;
234
235 if (int0stat) {
236 /* printf("level0 interrupt (%08x)\n", int0stat); */
237 nintcall = apbus_intr_call(0, int0stat);
238
239 if (!nintcall) {
240 printf("level0_interrupt: no match interrupt mask! %04x\n",int0stat);
241 }
242
243 } else {
244 printf("level0 stray interrupt?\n");
245 }
246
247 }
248
249 void
250 enable_intr_5000()
251 {
252 /* APbus Interrupt (DMAC, SONIC, FIFO*, FDC) */
253 *(volatile unsigned int *)NEWS5000_INTMASK0 =
254 NEWS5000_INTSLOT_ALL|NEWS5000_INT0_ALL;
255
256 /* APbus Interrupt (KBD, SERIAL, AUDIO*, PARALLEL, FB */
257 *(volatile unsigned int *)NEWS5000_INTMASK1 =
258 NEWS5000_INTSLOT_ALL|NEWS5000_INT1_ALL;
259
260 *(volatile unsigned int *)NEWS5000_INTMASK4 =
261 NEWS5000_INT4_ALL;
262
263 *(volatile unsigned int *)NEWS5000_INTCLR5 = 0xffffffff;
264 *(volatile unsigned int *)NEWS5000_INTMASK5 =
265 NEWS5000_INT5_ABIF|NEWS5000_INT5_MBIF|NEWS5000_INT5_SBIF;
266 }
267
268 void
269 disable_intr_5000()
270 {
271 *(volatile unsigned int *)NEWS5000_INTMASK0 = 0;
272 *(volatile unsigned int *)NEWS5000_INTMASK1 = 0;
273 *(volatile unsigned int *)NEWS5000_INTMASK2 = 0;
274 *(volatile unsigned int *)NEWS5000_INTMASK3 = 0;
275 *(volatile unsigned int *)NEWS5000_INTMASK4 = 0;
276 *(volatile unsigned int *)NEWS5000_INTMASK5 = 0;
277 }
278
279 void
280 readidrom_5000(rom)
281 u_char *rom;
282 {
283 u_int32_t *p = (void *)NEWS5000_IDROM;
284 int i;
285
286 for (i = 0; i < sizeof (struct idrom); i++, p += 2)
287 *rom++ = ((*p & 0x0f) << 4) + (*(p + 1) & 0x0f);
288 }
289
290 extern struct idrom idrom;
291
292 void
293 news5000_init()
294 {
295 enable_intr = enable_intr_5000;
296 disable_intr = disable_intr_5000;
297
298 readidrom_5000((u_char *)&idrom);
299 }
300