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