pci_eb164.c revision 1.1 1 /* $NetBSD: pci_eb164.c,v 1.1 1996/11/11 21:08:12 cgd Exp $ */
2
3 /*
4 * Copyright (c) 1995, 1996 Carnegie-Mellon University.
5 * All rights reserved.
6 *
7 * Author: Chris G. Demetriou
8 *
9 * Permission to use, copy, modify and distribute this software and
10 * its documentation is hereby granted, provided that both the copyright
11 * notice and this permission notice appear in all copies of the
12 * software, derivative works or modified versions, and any portions
13 * thereof, and that both notices appear in supporting documentation.
14 *
15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
17 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18 *
19 * Carnegie Mellon requests users of this software to return to
20 *
21 * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
22 * School of Computer Science
23 * Carnegie Mellon University
24 * Pittsburgh PA 15213-3890
25 *
26 * any improvements or extensions that they make and grant Carnegie the
27 * rights to redistribute these changes.
28 */
29
30 #include <sys/types.h>
31 #include <sys/param.h>
32 #include <sys/time.h>
33 #include <sys/systm.h>
34 #include <sys/errno.h>
35 #include <sys/malloc.h>
36 #include <sys/device.h>
37 #include <sys/syslog.h>
38
39 #include <vm/vm.h>
40
41 #include <machine/autoconf.h>
42
43 #include <dev/pci/pcireg.h>
44 #include <dev/pci/pcivar.h>
45
46 #include <alpha/pci/ciareg.h>
47 #include <alpha/pci/ciavar.h>
48
49 #include <alpha/pci/pci_eb164.h>
50
51 #ifndef EVCNT_COUNTERS
52 #include <machine/intrcnt.h>
53 #endif
54
55 #include "sio.h"
56 #if NSIO
57 #include <alpha/pci/siovar.h>
58 #endif
59
60 int dec_eb164_intr_map __P((void *, pcitag_t, int, int,
61 pci_intr_handle_t *));
62 const char *dec_eb164_intr_string __P((void *, pci_intr_handle_t));
63 void *dec_eb164_intr_establish __P((void *, pci_intr_handle_t,
64 int, int (*func)(void *), void *));
65 void dec_eb164_intr_disestablish __P((void *, void *));
66
67 #if 0 /* XXX */
68 #define KN20AA_PCEB_IRQ 31
69 #define KN20AA_MAX_IRQ 32
70 #define PCI_STRAY_MAX 5
71
72 struct eb164_intrhand {
73 TAILQ_ENTRY(eb164_intrhand) ih_q;
74 int (*ih_fun)();
75 void *ih_arg;
76 u_long ih_count;
77 int ih_level;
78 };
79 TAILQ_HEAD(eb164_intrchain, eb164_intrhand);
80
81 struct eb164_intrchain eb164_pci_intrs[KN20AA_MAX_IRQ];
82 int eb164_pci_strayintrcnt[KN20AA_MAX_IRQ];
83 #ifdef EVCNT_COUNTERS
84 struct evcnt eb164_intr_evcnt;
85 #endif
86 #endif /* 0 XXX */
87
88 void eb164_pci_strayintr __P((int irq));
89 void eb164_iointr __P((void *framep, unsigned long vec));
90 #if 0 /* XXX */
91 void eb164_enable_intr __P((int irq));
92 void eb164_disable_intr __P((int irq));
93 struct eb164_intrhand *eb164_attach_intr __P((struct eb164_intrchain *,
94 int, int (*) (void *), void *));
95 #endif /* 0 XXX */
96
97 void
98 pci_eb164_pickintr(ccp)
99 struct cia_config *ccp;
100 {
101 int i;
102 #if 0 /* XXX */
103 struct eb164_intrhand *nintrhand;
104 #endif /* 0 XXX */
105 bus_space_tag_t iot = ccp->cc_iot;
106 pci_chipset_tag_t pc = &ccp->cc_pc;
107
108 #if 0 /* XXX */
109 for (i = 0; i < KN20AA_MAX_IRQ; i++)
110 TAILQ_INIT(&eb164_pci_intrs[i]);
111 #endif /* 0 XXX */
112
113 pc->pc_intr_v = ccp;
114 pc->pc_intr_map = dec_eb164_intr_map;
115 pc->pc_intr_string = dec_eb164_intr_string;
116 pc->pc_intr_establish = dec_eb164_intr_establish;
117 pc->pc_intr_disestablish = dec_eb164_intr_disestablish;
118
119 #if NSIO
120 sio_intr_setup(iot);
121 #endif
122
123 set_iointr(eb164_iointr);
124
125 #if 0 /* XXX */
126 #if NSIO
127 eb164_enable_intr(KN20AA_PCEB_IRQ);
128 #if 0 /* XXX init PCEB interrupt handler? */
129 eb164_attach_intr(&eb164_pci_intrs[KN20AA_PCEB_IRQ], ???, ???, ???);
130 #endif
131 #endif
132 #endif /* 0 XXX */
133 }
134
135 int
136 dec_eb164_intr_map(ccv, bustag, buspin, line, ihp)
137 void *ccv;
138 pcitag_t bustag;
139 int buspin, line;
140 pci_intr_handle_t *ihp;
141 {
142
143 printf("dec_eb164_intr_map(0x%lx, %d, %d)\n", bustag, buspin, line);
144 return 0;
145
146 #if 0
147 struct cia_config *ccp = ccv;
148 pci_chipset_tag_t pc = &ccp->cc_pc;
149 int device;
150 int eb164_irq;
151 void *ih;
152
153 if (buspin == 0) {
154 /* No IRQ used. */
155 return 1;
156 }
157 if (buspin > 4) {
158 printf("pci_map_int: bad interrupt pin %d\n", buspin);
159 return 1;
160 }
161
162 /*
163 * Slot->interrupt translation. Appears to work, though it
164 * may not hold up forever.
165 *
166 * The DEC engineers who did this hardware obviously engaged
167 * in random drug testing.
168 */
169 pci_decompose_tag(pc, bustag, NULL, &device, NULL);
170 switch (device) {
171 case 11:
172 case 12:
173 eb164_irq = ((device - 11) + 0) * 4;
174 break;
175
176 case 7:
177 eb164_irq = 8;
178 break;
179
180 case 9:
181 eb164_irq = 12;
182 break;
183
184 case 6: /* 21040 on AlphaStation 500 */
185 eb164_irq = 13;
186 break;
187
188 case 8:
189 eb164_irq = 16;
190 break;
191
192 default:
193 #ifdef KN20AA_BOGUS_IRQ_FROB
194 *ihp = 0xdeadbeef;
195 printf("\n\n BOGUS INTERRUPT MAPPING: dev %d, pin %d\n",
196 device, buspin);
197 return (0);
198 #endif
199 panic("pci_eb164_map_int: invalid device number %d\n",
200 device);
201 }
202
203 eb164_irq += buspin - 1;
204 if (eb164_irq > KN20AA_MAX_IRQ)
205 panic("pci_eb164_map_int: eb164_irq too large (%d)\n",
206 eb164_irq);
207
208 *ihp = eb164_irq;
209 return (0);
210 #endif
211 }
212
213 const char *
214 dec_eb164_intr_string(ccv, ih)
215 void *ccv;
216 pci_intr_handle_t ih;
217 {
218 struct cia_config *ccp = ccv;
219 static char irqstr[15]; /* 11 + 2 + NULL + sanity */
220
221 sprintf(irqstr, "BOGUS");
222 return (irqstr);
223
224 #if 0 /* XXX */
225 #ifdef KN20AA_BOGUS_IRQ_FROB
226 if (ih == 0xdeadbeef) {
227 sprintf(irqstr, "BOGUS");
228 return (irqstr);
229 }
230 #endif
231 if (ih > KN20AA_MAX_IRQ)
232 panic("dec_eb164_a50_intr_string: bogus eb164 IRQ 0x%x\n",
233 ih);
234
235 sprintf(irqstr, "eb164 irq %d", ih);
236 return (irqstr);
237 #endif /* 0 XXX */
238 }
239
240 void *
241 dec_eb164_intr_establish(ccv, ih, level, func, arg)
242 void *ccv, *arg;
243 pci_intr_handle_t ih;
244 int level;
245 int (*func) __P((void *));
246 {
247
248 printf("dec_eb164_intr_establish(0x%lx, %d, %p, %p)\n", ih, level, func, arg);
249 return ((void *)0xbabefacedeadbeef);
250
251 #if 0 /* XXX */
252 struct cia_config *ccp = ccv;
253 void *cookie;
254
255 #ifdef KN20AA_BOGUS_IRQ_FROB
256 if (ih == 0xdeadbeef) {
257 int i;
258 char chars[10];
259
260 printf("dec_eb164_intr_establish: BOGUS IRQ\n");
261 do {
262 printf("IRQ to enable? ");
263 getstr(chars, 10);
264 i = atoi(chars);
265 } while (i < 0 || i > 32);
266 printf("ENABLING IRQ %d\n", i);
267 eb164_enable_intr(i);
268 return ((void *)0xbabefacedeadbeef);
269 }
270 #endif
271 if (ih > KN20AA_MAX_IRQ)
272 panic("dec_eb164_intr_establish: bogus eb164 IRQ 0x%x\n",
273 ih);
274
275 cookie = eb164_attach_intr(&eb164_pci_intrs[ih], level, func, arg);
276 eb164_enable_intr(ih);
277 return (cookie);
278 #endif /* XXX */
279 }
280
281 void
282 dec_eb164_intr_disestablish(ccv, cookie)
283 void *ccv, *cookie;
284 {
285 struct cia_config *ccp = ccv;
286
287 panic("dec_eb164_intr_disestablish not implemented"); /* XXX */
288 }
289
290 /*
291 * caught a stray interrupt; notify if not too many seen already.
292 */
293 void
294 eb164_pci_strayintr(irq)
295 int irq;
296 {
297
298 log(LOG_ERR, "stray eb164 irq %d\n", irq);
299
300 #if 0 /* XXX */
301 eb164_pci_strayintrcnt[irq]++;
302 if (eb164_pci_strayintrcnt[irq] == PCI_STRAY_MAX)
303 eb164_disable_intr(irq);
304
305 log(LOG_ERR, "stray eb164 irq %d\n", irq);
306 if (eb164_pci_strayintrcnt[irq] == PCI_STRAY_MAX)
307 log(LOG_ERR, "disabling interrupts on eb164 irq %d\n", irq);
308 #endif /* 0 XXX */
309 }
310
311 void
312 eb164_iointr(framep, vec)
313 void *framep;
314 unsigned long vec;
315 {
316 struct eb164_intrhand *ih;
317 int irq, handled;
318
319 #if 0 /* XXX */
320 if (vec >= 0x900) {
321 if (vec >= 0x900 + (KN20AA_MAX_IRQ << 4))
322 panic("eb164_iointr: vec 0x%x out of range\n", vec);
323 irq = (vec - 0x900) >> 4;
324
325 #ifdef EVCNT_COUNTERS
326 eb164_intr_evcnt.ev_count++;
327 #else
328 if (KN20AA_MAX_IRQ != INTRCNT_KN20AA_IRQ_LEN)
329 panic("eb164 interrupt counter sizes inconsistent");
330 intrcnt[INTRCNT_KN20AA_IRQ + irq]++;
331 #endif
332
333 for (ih = eb164_pci_intrs[irq].tqh_first, handled = 0;
334 ih != NULL; ih = ih->ih_q.tqe_next) {
335 int rv;
336
337 rv = (*ih->ih_fun)(ih->ih_arg);
338
339 ih->ih_count++;
340 handled = handled || (rv != 0);
341 }
342 if (!handled)
343 eb164_pci_strayintr(irq);
344 return;
345 }
346 if (vec >= 0x800) {
347 #if NSIO
348 sio_iointr(framep, vec);
349 #endif
350 return;
351 }
352 #endif /* 0 XXX */
353 panic("eb164_iointr: weird vec 0x%x\n", vec);
354 }
355
356 #if 0 /* XXX */
357 void
358 eb164_enable_intr(irq)
359 int irq;
360 {
361
362 /*
363 * From disassembling small bits of the OSF/1 kernel:
364 * the following appears to enable a given interrupt request.
365 * "blech." I'd give valuable body parts for better docs or
366 * for a good decompiler.
367 */
368 alpha_mb();
369 REGVAL(0x8780000000L + 0x40L) |= (1 << irq); /* XXX */
370 alpha_mb();
371 }
372
373 void
374 eb164_disable_intr(irq)
375 int irq;
376 {
377
378 alpha_mb();
379 REGVAL(0x8780000000L + 0x40L) &= ~(1 << irq); /* XXX */
380 alpha_mb();
381 }
382
383 struct eb164_intrhand *
384 eb164_attach_intr(chain, level, func, arg)
385 struct eb164_intrchain *chain;
386 int level;
387 int (*func) __P((void *));
388 void *arg;
389 {
390 struct eb164_intrhand *nintrhand;
391
392 nintrhand = (struct eb164_intrhand *)
393 malloc(sizeof *nintrhand, M_DEVBUF, M_WAITOK);
394
395 nintrhand->ih_fun = func;
396 nintrhand->ih_arg = arg;
397 nintrhand->ih_count = 0;
398 nintrhand->ih_level = level;
399 TAILQ_INSERT_TAIL(chain, nintrhand, ih_q);
400
401 return (nintrhand);
402 }
403 #endif /* 0 XXX */
404