pci_kn300.c revision 1.2 1 /* $NetBSD: pci_kn300.c,v 1.2 1998/04/15 01:18:17 mjacob Exp $ */
2
3 /*
4 * Copyright (c) 1998 by Matthew Jacob
5 * NASA AMES Research Center.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice immediately at the beginning of the file, without modification,
13 * this list of conditions, and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
34
35 __KERNEL_RCSID(0, "$NetBSD: pci_kn300.c,v 1.2 1998/04/15 01:18:17 mjacob Exp $");
36
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <sys/time.h>
40 #include <sys/systm.h>
41 #include <sys/errno.h>
42 #include <sys/malloc.h>
43 #include <sys/device.h>
44 #include <sys/syslog.h>
45
46 #include <vm/vm.h>
47
48 #include <machine/autoconf.h>
49
50 #include <dev/pci/pcireg.h>
51 #include <dev/pci/pcivar.h>
52
53 #include <alpha/mcbus/mcbusvar.h>
54 #include <alpha/mcbus/mcbusreg.h>
55 #include <alpha/pci/mcpciareg.h>
56 #include <alpha/pci/mcpciavar.h>
57 #include <alpha/pci/pci_kn300.h>
58
59 #ifndef EVCNT_COUNTERS
60 #include <machine/intrcnt.h>
61 #endif
62
63 #include "sio.h"
64 #if NSIO
65 #include <alpha/pci/siovar.h>
66 #endif
67
68 int
69 dec_kn300_intr_map __P((void *, pcitag_t, int, int, pci_intr_handle_t *));
70 const char *dec_kn300_intr_string __P((void *, pci_intr_handle_t));
71 void * dec_kn300_intr_establish __P((void *, pci_intr_handle_t,
72 int, int (*func)(void *), void *));
73 void dec_kn300_intr_disestablish __P((void *, void *));
74
75 #define KN300_PCEB_IRQ 16
76 #define NPIN 4
77
78 static struct vectab {
79 int (*func) __P((void *));
80 void *arg;
81 int irq;
82 } vectab[MAX_MC_BUS][MCPCIA_PER_MCBUS][MCPCIA_MAXSLOT][NPIN];
83
84 struct mcpcia_config *mcpcia_eisaccp = NULL;
85
86 #ifdef EVCNT_COUNTERS
87 struct evcnt kn300_intr_evcnt;
88 #endif
89
90 int kn300_spurious __P((void *));
91 void kn300_iointr __P((void *, unsigned long));
92 void kn300_enable_intr __P((struct mcpcia_config *, int));
93 void kn300_disable_intr __P((struct mcpcia_config *, int));
94
95 void
96 pci_kn300_pickintr(ccp, first)
97 struct mcpcia_config *ccp;
98 int first;
99 {
100 pci_chipset_tag_t pc = &ccp->cc_pc;
101
102 if (first) {
103 int g;
104 for (g = 0; g < MAX_MC_BUS; g++) {
105 int m;
106 for (m = 0; m < MCPCIA_PER_MCBUS; m++) {
107 int s;
108 for (s = 0; s < MCPCIA_MAXSLOT; s++) {
109 int p;
110 for (p = 0; p < NPIN; p++) {
111 struct vectab *vp;
112 vp = &vectab[g][m][s][p];
113 vp->func = kn300_spurious;
114 vp->arg = (void *) ((long)
115 (g << 0) |
116 (m << 3) |
117 (s << 6) |
118 (p << 9));
119 vp->irq = -1;
120 }
121 }
122 }
123 }
124 set_iointr(kn300_iointr);
125 }
126
127 pc->pc_intr_v = ccp;
128 pc->pc_intr_map = dec_kn300_intr_map;
129 pc->pc_intr_string = dec_kn300_intr_string;
130 pc->pc_intr_establish = dec_kn300_intr_establish;
131 pc->pc_intr_disestablish = dec_kn300_intr_disestablish;
132
133 #if NSIO
134 if (EISA_PRESENT(REGVAL(MCPCIA_PCI_REV(ccp->cc_sc)))) {
135 extern void dec_kn300_cons_init __P((void));
136 bus_space_tag_t iot = &ccp->cc_iot;
137 if (mcpcia_eisaccp) {
138 printf("Huh? There's only supposed to be one eisa!\n");
139 }
140 sio_intr_setup(pc, iot);
141 kn300_enable_intr(ccp, KN300_PCEB_IRQ);
142 mcpcia_eisaccp = ccp;
143 dec_kn300_cons_init(); /* XXXXXXXXXXXXXXXXXXX */
144 }
145 #endif
146 }
147
148 int
149 dec_kn300_intr_map(ccv, bustag, buspin, line, ihp)
150 void *ccv;
151 pcitag_t bustag;
152 int buspin, line;
153 pci_intr_handle_t *ihp;
154 {
155 struct mcpcia_config *ccp = ccv;
156 pci_chipset_tag_t pc = &ccp->cc_pc;
157 int device;
158 int kn300_irq;
159
160 if (buspin == 0) {
161 /* No IRQ used. */
162 return 1;
163 }
164 if (buspin > 4 || buspin < 0) {
165 printf("dec_kn300_intr_map: bad interrupt pin %d\n", buspin);
166 return 1;
167 }
168
169 alpha_pci_decompose_tag(pc, bustag, NULL, &device, NULL);
170
171 if (device == 1) {
172 /*
173 * This can only be the NCR810 SCSI.
174 * XXX: Do we need to check this more closely?
175 */
176 if (EISA_PRESENT(REGVAL(MCPCIA_PCI_REV(ccp->cc_sc)))) {
177 printf("XXXXX: How can you have an EISA in the spot "
178 "as an NCR 810?\n");
179 }
180 kn300_irq = 16;
181 } else if (device >= 2 && device <= 5) {
182 kn300_irq = (device - 2) * 4;
183 } else {
184 printf("dec_kn300_intr_map: weird device number %d\n", device);
185 return(1);
186 }
187 /*
188 * handle layout:
189 *
190 * bits 0..2 7-GID
191 * bits 3..5 MID-4
192 * bits 6..8 PCI Slot (0..7- yes, some don't exist)
193 * bits 9..10 buspin-1
194 * bits 11-15 IRQ
195 */
196 *ihp = (pci_intr_handle_t)
197 (7 - ccp->cc_sc->mcpcia_gid) |
198 ((ccp->cc_sc->mcpcia_mid - 4) << 3) |
199 (device << 6) |
200 ((buspin-1) << 9) |
201 (kn300_irq << 11);
202 return (0);
203 }
204
205 const char *
206 dec_kn300_intr_string(ccv, ih)
207 void *ccv;
208 pci_intr_handle_t ih;
209 {
210 static char irqstr[64];
211 sprintf(irqstr, "kn300 irq %d PCI Interrupt Pin %c",
212 (ih >> 11) & 0x1f, ((ih >> 9) & 0x3) + 'A');
213 return (irqstr);
214 }
215
216 void *
217 dec_kn300_intr_establish(ccv, ih, level, func, arg)
218 void *ccv;
219 pci_intr_handle_t ih;
220 int level;
221 int (*func) __P((void *));
222 void *arg;
223 {
224 struct vectab *vp;
225 int gidx, midx, slot, pidx, s;
226 void *cookie = NULL;
227
228 gidx = ih & 0x7;
229 midx = (ih >> 3) & 0x7;
230 slot = (ih >> 6) & 0x7;
231 pidx = (ih >> 9) & 0x3;
232
233 /*
234 * XXX: FIXME - for PCI bridges, the framework here is such that
235 * XXX: we're mapping the mapping for the bridge, not the
236 * XXX: device behind the bridge, so we're not cognizant of the
237 * XXX: pin swizzling that could go on. We really ought to fix
238 * XXX: this, but for a first cut, assuming all pins map to the
239 * XXX: same device and filling in all pin vectors is probably
240 * XXX: okay.
241 */
242
243 for (pidx = 0; pidx < 4; pidx++) {
244 vp = &vectab[gidx][midx][slot][pidx];
245 if (vp->func != kn300_spurious) {
246 printf("dec_kn300_intr_establish: vector cookie 0x%x "
247 "already used\n", ih);
248 return (cookie);
249 }
250 s = splhigh();
251 vp->func = func;
252 vp->arg = arg;
253 vp->irq = (ih >> 11) & 0x1f;
254 (void) splx(s);
255 }
256
257 kn300_enable_intr(ccv, (int)((ih >> 11) & 0x1f));
258 cookie = (void *) ih;
259 return (cookie);
260 }
261
262 void
263 dec_kn300_intr_disestablish(ccv, cookie)
264 void *ccv, *cookie;
265 {
266 pci_intr_handle_t ih = (pci_intr_handle_t) cookie;
267 int gidx, midx, slot, pidx, s;
268 struct vectab *vp;
269
270 gidx = ih & 0x7;
271 midx = (ih >> 3) & 0x7;
272 slot = (ih >> 6) & 0x7;
273 pidx = (ih >> 9) & 0x3;
274 vp = &vectab[gidx][midx][slot][pidx];
275 s = splhigh();
276 vp->func = kn300_spurious;
277 vp->arg = cookie;
278 vp->irq = -1;
279 (void) splx(s);
280 kn300_disable_intr(ccv, (int)((ih >> 11) & 0x1f));
281 }
282
283 int
284 kn300_spurious(arg)
285 void *arg;
286 {
287 pci_intr_handle_t ih = (pci_intr_handle_t) arg;
288 int gidx, midx, slot, pidx;
289
290 gidx = ih & 0x7;
291 midx = (ih >> 3) & 0x7;
292 slot = (ih >> 6) & 0x7;
293 pidx = (ih >> 9) & 0x3;
294 printf("Spurious Interrupt from mcbus%d MID %d Slot %d "
295 "PCI Interrupt Pin %c\n", gidx, midx + 4, slot, pidx + 'A');
296 /*
297 * XXX: We *could*, if we have recorded all the mcpcia softcs
298 * XXX: that we've configured, and this spurious interrupt
299 * XXX: falls within this range, disable this interrupt.
300 *
301 * XXX: Later.
302 */
303 return (-1);
304 }
305
306 void
307 kn300_iointr(framep, vec)
308 void *framep;
309 unsigned long vec;
310 {
311 int base, gidx, midx, slot, pidx;
312 struct vectab *vp;
313
314 if (vec >= MCPCIA_VEC_EISA && vec < MCPCIA_VEC_PCI) {
315 #if NSIO
316 sio_iointr(framep, vec);
317 return;
318 #else
319 printf("kn300_iointr: (E)ISA interrupt support not configured"
320 " for vector 0x%x", vec);
321 kn300_disable_intr(mcpcia_eisaccp, KN300_PCEB_IRQ);
322 #endif
323 }
324
325 base = (int) vec - MCPCIA_VEC_PCI;
326
327 midx = base / 0x200;
328 gidx = midx / 4;
329 midx = midx % 4;
330 slot = (base % 0x200) / 0x10;
331 pidx = ((slot / 4) & 0x3);
332 slot = slot / 4;
333
334 if (gidx >= MAX_MC_BUS || midx >= MCPCIA_PER_MCBUS ||
335 slot >= MCPCIA_MAXSLOT || pidx >= NPIN) {
336 panic("kn300_iointr: vec 0x%x (mcbus%d mid%d slot %d pin%d)",
337 vec, gidx, midx+4, slot, pidx);
338 }
339
340 #ifdef EVCNT_COUNTERS
341 kn300_intr_evcnt.ev_count++;
342 #endif
343 /*
344 * Check for i2c bus interrupts XXXXXXXXX
345 */
346 if (gidx == 0 && midx == 0 && vec == MCPCIA_I2C_CVEC) {
347 #ifndef EVCNT_COUNTERS
348 intrcnt[INTRCNT_KN300_I2C_CTRL]++;
349 #endif
350 printf("i2c: controller interrupt\n");
351 return;
352 }
353 if (gidx == 0 && midx == 0 && vec == MCPCIA_I2C_BVEC) {
354 #ifndef EVCNT_COUNTERS
355 intrcnt[INTRCNT_KN300_I2C_BUS]++;
356 #endif
357 printf("i2c: bus interrupt\n");
358 return;
359 }
360
361 /*
362 * Now, for the main stuff...
363 */
364 vp = &vectab[gidx][midx][slot][pidx];
365 #ifndef EVCNT_COUNTERS
366 if (vp->irq >= 0 && vp->irq <= INTRCNT_KN300_NCR810) {
367 intrcnt[INTRCNT_KN300_IRQ + vp->irq]++;
368 }
369 #endif
370 if ((*vp->func)(vp->arg) == 0) {
371 #if 0
372 printf("Unclaimed interrupt from mcbus%d MID %d Slot %d "
373 "PCI Interrupt Pin %c\n", gidx, midx + 4, slot, pidx + 'A');
374 #endif
375 }
376 }
377
378 void
379 kn300_enable_intr(ccp, irq)
380 struct mcpcia_config *ccp;
381 int irq;
382 {
383 alpha_mb();
384 REGVAL(MCPCIA_INT_MASK0(ccp->cc_sc)) |= (1 << irq);
385 alpha_mb();
386 }
387
388 void
389 kn300_disable_intr(ccp, irq)
390 struct mcpcia_config *ccp;
391 int irq;
392 {
393 alpha_mb();
394 REGVAL(MCPCIA_INT_MASK0(ccp->cc_sc)) &= ~(1 << irq);
395 alpha_mb();
396 }
397