pci_kn300.c revision 1.5 1 /* $NetBSD: pci_kn300.c,v 1.5 1998/04/25 00:12:45 thorpej 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.5 1998/04/25 00:12:45 thorpej 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 /* Not supported on KN300. */
134 pc->pc_pciide_compat_intr_establish = NULL;
135
136 #if NSIO
137 if (EISA_PRESENT(REGVAL(MCPCIA_PCI_REV(ccp->cc_sc)))) {
138 extern void dec_kn300_cons_init __P((void));
139 bus_space_tag_t iot = &ccp->cc_iot;
140 if (mcpcia_eisaccp) {
141 printf("Huh? There's only supposed to be one eisa!\n");
142 }
143 sio_intr_setup(pc, iot);
144 kn300_enable_intr(ccp, KN300_PCEB_IRQ);
145 mcpcia_eisaccp = ccp;
146 dec_kn300_cons_init(); /* XXXXXXXXXXXXXXXXXXX */
147 }
148 #endif
149 }
150
151 int
152 dec_kn300_intr_map(ccv, bustag, buspin, line, ihp)
153 void *ccv;
154 pcitag_t bustag;
155 int buspin, line;
156 pci_intr_handle_t *ihp;
157 {
158 struct mcpcia_config *ccp = ccv;
159 pci_chipset_tag_t pc = &ccp->cc_pc;
160 int device;
161 int kn300_irq;
162
163 if (buspin == 0) {
164 /* No IRQ used. */
165 return 1;
166 }
167 if (buspin > 4 || buspin < 0) {
168 printf("dec_kn300_intr_map: bad interrupt pin %d\n", buspin);
169 return 1;
170 }
171
172 alpha_pci_decompose_tag(pc, bustag, NULL, &device, NULL);
173
174 if (device == 1) {
175 /*
176 * This can only be the NCR810 SCSI.
177 * XXX: Do we need to check this more closely?
178 */
179 if (EISA_PRESENT(REGVAL(MCPCIA_PCI_REV(ccp->cc_sc)))) {
180 printf("XXXXX: How can you have an EISA in the spot "
181 "as an NCR 810?\n");
182 }
183 kn300_irq = 16;
184 } else if (device >= 2 && device <= 5) {
185 kn300_irq = (device - 2) * 4;
186 } else {
187 printf("dec_kn300_intr_map: weird device number %d\n", device);
188 return(1);
189 }
190 /*
191 * handle layout:
192 *
193 * bits 0..2 7-GID
194 * bits 3..5 MID-4
195 * bits 6..8 PCI Slot (0..7- yes, some don't exist)
196 * bits 9..10 buspin-1
197 * bits 11-15 IRQ
198 */
199 *ihp = (pci_intr_handle_t)
200 (7 - ccp->cc_sc->mcpcia_gid) |
201 ((ccp->cc_sc->mcpcia_mid - 4) << 3) |
202 (device << 6) |
203 ((buspin-1) << 9) |
204 (kn300_irq << 11);
205 return (0);
206 }
207
208 const char *
209 dec_kn300_intr_string(ccv, ih)
210 void *ccv;
211 pci_intr_handle_t ih;
212 {
213 static char irqstr[64];
214 sprintf(irqstr, "kn300 irq %d PCI Interrupt Pin %c",
215 (ih >> 11) & 0x1f, ((ih >> 9) & 0x3) + 'A');
216 return (irqstr);
217 }
218
219 void *
220 dec_kn300_intr_establish(ccv, ih, level, func, arg)
221 void *ccv;
222 pci_intr_handle_t ih;
223 int level;
224 int (*func) __P((void *));
225 void *arg;
226 {
227 struct vectab *vp;
228 int gidx, midx, slot, pidx, s;
229 void *cookie = NULL;
230
231 gidx = ih & 0x7;
232 midx = (ih >> 3) & 0x7;
233 slot = (ih >> 6) & 0x7;
234 pidx = (ih >> 9) & 0x3;
235
236 /*
237 * XXX: FIXME - for PCI bridges, the framework here is such that
238 * XXX: we're mapping the mapping for the bridge, not the
239 * XXX: device behind the bridge, so we're not cognizant of the
240 * XXX: pin swizzling that could go on. We really ought to fix
241 * XXX: this, but for a first cut, assuming all pins map to the
242 * XXX: same device and filling in all pin vectors is probably
243 * XXX: okay.
244 */
245
246 for (pidx = 0; pidx < 4; pidx++) {
247 vp = &vectab[gidx][midx][slot][pidx];
248 if (vp->func != kn300_spurious) {
249 printf("dec_kn300_intr_establish: vector cookie 0x%x "
250 "already used\n", ih);
251 return (cookie);
252 }
253 s = splhigh();
254 vp->func = func;
255 vp->arg = arg;
256 vp->irq = (ih >> 11) & 0x1f;
257 (void) splx(s);
258 }
259
260 kn300_enable_intr(ccv, (int)((ih >> 11) & 0x1f));
261 cookie = (void *) ih;
262 return (cookie);
263 }
264
265 void
266 dec_kn300_intr_disestablish(ccv, cookie)
267 void *ccv, *cookie;
268 {
269 pci_intr_handle_t ih = (pci_intr_handle_t) cookie;
270 int gidx, midx, slot, pidx, s;
271 struct vectab *vp;
272
273 gidx = ih & 0x7;
274 midx = (ih >> 3) & 0x7;
275 slot = (ih >> 6) & 0x7;
276 pidx = (ih >> 9) & 0x3;
277 vp = &vectab[gidx][midx][slot][pidx];
278 s = splhigh();
279 vp->func = kn300_spurious;
280 vp->arg = cookie;
281 vp->irq = -1;
282 (void) splx(s);
283 kn300_disable_intr(ccv, (int)((ih >> 11) & 0x1f));
284 }
285
286 int
287 kn300_spurious(arg)
288 void *arg;
289 {
290 pci_intr_handle_t ih = (pci_intr_handle_t) arg;
291 int gidx, midx, slot, pidx;
292
293 gidx = ih & 0x7;
294 midx = (ih >> 3) & 0x7;
295 slot = (ih >> 6) & 0x7;
296 pidx = (ih >> 9) & 0x3;
297 printf("Spurious Interrupt from mcbus%d MID %d Slot %d "
298 "PCI Interrupt Pin %c\n", gidx, midx + 4, slot, pidx + 'A');
299 /*
300 * XXX: We *could*, if we have recorded all the mcpcia softcs
301 * XXX: that we've configured, and this spurious interrupt
302 * XXX: falls within this range, disable this interrupt.
303 *
304 * XXX: Later.
305 */
306 return (-1);
307 }
308
309 void
310 kn300_iointr(framep, vec)
311 void *framep;
312 unsigned long vec;
313 {
314 int base, gidx, midx, slot, pidx;
315 struct vectab *vp;
316
317 if (vec >= MCPCIA_VEC_EISA && vec < MCPCIA_VEC_PCI) {
318 #if NSIO
319 sio_iointr(framep, vec);
320 return;
321 #else
322 printf("kn300_iointr: (E)ISA interrupt support not configured"
323 " for vector 0x%x", vec);
324 kn300_disable_intr(mcpcia_eisaccp, KN300_PCEB_IRQ);
325 #endif
326 }
327
328 base = (int) vec - MCPCIA_VEC_PCI;
329
330 midx = base / 0x200;
331 gidx = midx / 4;
332 midx = midx % 4;
333 slot = (base % 0x200) / 0x10;
334 pidx = ((slot / 4) & 0x3);
335 slot = slot / 4;
336
337 if (gidx >= MAX_MC_BUS || midx >= MCPCIA_PER_MCBUS ||
338 slot >= MCPCIA_MAXSLOT || pidx >= NPIN) {
339 panic("kn300_iointr: vec 0x%x (mcbus%d mid%d slot %d pin%d)",
340 vec, gidx, midx+4, slot, pidx);
341 }
342
343 #ifdef EVCNT_COUNTERS
344 kn300_intr_evcnt.ev_count++;
345 #endif
346 /*
347 * Check for i2c bus interrupts XXXXXXXXX
348 */
349 if (gidx == 0 && midx == 0 && vec == MCPCIA_I2C_CVEC) {
350 #ifndef EVCNT_COUNTERS
351 intrcnt[INTRCNT_KN300_I2C_CTRL]++;
352 #endif
353 printf("i2c: controller interrupt\n");
354 return;
355 }
356 if (gidx == 0 && midx == 0 && vec == MCPCIA_I2C_BVEC) {
357 #ifndef EVCNT_COUNTERS
358 intrcnt[INTRCNT_KN300_I2C_BUS]++;
359 #endif
360 printf("i2c: bus interrupt\n");
361 return;
362 }
363
364 /*
365 * Now, for the main stuff...
366 */
367 vp = &vectab[gidx][midx][slot][pidx];
368 #ifndef EVCNT_COUNTERS
369 if (vp->irq >= 0 && vp->irq <= INTRCNT_KN300_NCR810) {
370 intrcnt[INTRCNT_KN300_IRQ + vp->irq]++;
371 }
372 #endif
373 if ((*vp->func)(vp->arg) == 0) {
374 #if 0
375 printf("Unclaimed interrupt from mcbus%d MID %d Slot %d "
376 "PCI Interrupt Pin %c\n", gidx, midx + 4, slot, pidx + 'A');
377 #endif
378 }
379 }
380
381 void
382 kn300_enable_intr(ccp, irq)
383 struct mcpcia_config *ccp;
384 int irq;
385 {
386 alpha_mb();
387 REGVAL(MCPCIA_INT_MASK0(ccp->cc_sc)) |= (1 << irq);
388 alpha_mb();
389 }
390
391 void
392 kn300_disable_intr(ccp, irq)
393 struct mcpcia_config *ccp;
394 int irq;
395 {
396 alpha_mb();
397 REGVAL(MCPCIA_INT_MASK0(ccp->cc_sc)) &= ~(1 << irq);
398 alpha_mb();
399 }
400