1 /* $NetBSD: algor_p5064_intr.c,v 1.30 2020/11/14 02:23:04 thorpej Exp $ */
2
3 /*-
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * Platform-specific interrupt support for the Algorithmics P-5064.
34 *
35 * The Algorithmics P-5064 has an interrupt controller that is pretty
36 * flexible -- it can take an interrupt source and route it to an
37 * arbitrary MIPS CPU hardware interrupt pin.
38 */
39
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: algor_p5064_intr.c,v 1.30 2020/11/14 02:23:04 thorpej Exp $");
42
43 #include "opt_ddb.h"
44 #define __INTR_PRIVATE
45
46 #include <sys/param.h>
47 #include <sys/bus.h>
48 #include <sys/cpu.h>
49 #include <sys/device.h>
50 #include <sys/intr.h>
51 #include <sys/kernel.h>
52 #include <sys/kmem.h>
53 #include <sys/queue.h>
54 #include <sys/systm.h>
55
56 #include <algor/autoconf.h>
57
58 #include <mips/locore.h>
59
60 #include <dev/ic/mc146818reg.h>
61
62 #include <algor/algor/algor_p5064reg.h>
63 #include <algor/algor/algor_p5064var.h>
64
65 #include <dev/pci/pcireg.h>
66 #include <dev/pci/pcivar.h>
67 #include <dev/pci/pciidereg.h>
68 #include <dev/pci/pciidevar.h>
69
70 #include <dev/isa/isavar.h>
71
72 #define REGVAL(x) *((volatile uint32_t *)(MIPS_PHYS_TO_KSEG1((x))))
73
74 struct p5064_irqreg {
75 bus_addr_t addr;
76 uint32_t val;
77 };
78
79 #define IRQREG_LOCINT 0
80 #define IRQREG_PANIC 1
81 #define IRQREG_PCIINT 2
82 #define IRQREG_ISAINT 3
83 #define IRQREG_KBDINT 4
84 #define NIRQREG 5
85
86 struct p5064_irqreg p5064_irqregs[NIRQREG] = {
87 { P5064_LOCINT, 0 },
88 { P5064_PANIC, 0 },
89 { P5064_PCIINT, 0 },
90 { P5064_ISAINT, 0 },
91 { P5064_KBDINT, 0 },
92 };
93
94 #define NSTEERREG 5
95
96 struct p5064_irqreg p5064_irqsteer[NSTEERREG] = {
97 { P5064_XBAR0, 0 },
98 { P5064_XBAR1, 0 },
99 { P5064_XBAR2, 0 },
100 { P5064_XBAR3, 0 },
101 { P5064_XBAR4, 0 },
102 };
103
104 #define NPCIIRQS 7
105
106 #define NLOCIRQS 6
107
108 #define NISAIRQS 3
109
110 #define IRQMAP_PCIBASE 0
111 #define IRQMAP_LOCBASE NPCIIRQS
112 #define IRQMAP_ISABASE (IRQMAP_LOCBASE + NLOCIRQS)
113 #define NIRQMAPS (IRQMAP_ISABASE + NISAIRQS)
114
115 const char * const p5064_intrnames[NIRQMAPS] = {
116 /*
117 * PCI INTERRUPTS
118 */
119 "PCIIRQ 0",
120 "PCIIRQ 1",
121 "PCIIRQ 2",
122 "PCIIRQ 3",
123 "Ethernet IRQ",
124 "SCSI IRQ",
125 "USB IRQ",
126
127 /*
128 * LOCAL INTERRUPTS
129 */
130 "mkbd",
131 "com 1",
132 "com 2",
133 "floppy",
134 "centronics",
135 "mcclock",
136
137 /*
138 * ISA interrupts.
139 */
140 "bridge",
141 "IDE primary",
142 "IDE secondary",
143 };
144
145 struct p5064_irqmap {
146 int irqidx;
147 int cpuintr;
148 int irqreg;
149 int irqbit;
150 int xbarreg;
151 int xbarshift;
152 };
153
154 const struct p5064_irqmap p5064_irqmap[NIRQMAPS] = {
155 /*
156 * PCI INTERRUPTS
157 */
158 /* PCIIRQ 0 */
159 { 0, 1,
160 IRQREG_PCIINT, PCIINT_PCI0,
161 2, 0 },
162
163 /* PCIIRQ 1 */
164 { 1, 1,
165 IRQREG_PCIINT, PCIINT_PCI1,
166 2, 2 },
167
168 /* PCIIRQ 2 */
169 { 2, 1,
170 IRQREG_PCIINT, PCIINT_PCI2,
171 2, 4 },
172
173 /* PCIIRQ 3 */
174 { 3, 1,
175 IRQREG_PCIINT, PCIINT_PCI3,
176 2, 6 },
177
178 /* Ethernet */
179 { P5064_IRQ_ETHERNET, 1,
180 IRQREG_PCIINT, PCIINT_ETH,
181 4, 2 },
182
183 /* SCSI */
184 { P5064_IRQ_SCSI, 1,
185 IRQREG_PCIINT, PCIINT_SCSI,
186 4, 4 },
187
188 /* USB */
189 { P5064_IRQ_USB, 1,
190 IRQREG_PCIINT, PCIINT_USB,
191 4, 6 },
192
193 /*
194 * LOCAL INTERRUPTS
195 */
196 /* keyboard */
197 { P5064_IRQ_MKBD, 2,
198 IRQREG_LOCINT, LOCINT_MKBD,
199 0, 4 },
200
201 /* COM1 */
202 { P5064_IRQ_COM1, 2,
203 IRQREG_LOCINT, LOCINT_COM1,
204 0, 6 },
205
206 /* COM2 */
207 { P5064_IRQ_COM2, 2,
208 IRQREG_LOCINT, LOCINT_COM2,
209 1, 0 },
210
211 /* floppy controller */
212 { P5064_IRQ_FLOPPY, 2,
213 IRQREG_LOCINT, LOCINT_FLP,
214 0, 2 },
215
216 /* parallel port */
217 { P5064_IRQ_CENTRONICS, 2,
218 IRQREG_LOCINT, LOCINT_CENT,
219 1, 2 },
220
221 /* RTC */
222 { P5064_IRQ_RTC, 2,
223 IRQREG_LOCINT, LOCINT_RTC,
224 1, 6 },
225
226 /*
227 * ISA INTERRUPTS
228 */
229 /* ISA bridge */
230 { P5064_IRQ_ISABRIDGE, 0,
231 IRQREG_ISAINT, ISAINT_ISABR,
232 3, 0 },
233
234 /* IDE 0 */
235 { P5064_IRQ_IDE0, 0,
236 IRQREG_ISAINT, ISAINT_IDE0,
237 3, 2 },
238
239 /* IDE 1 */
240 { P5064_IRQ_IDE1, 0,
241 IRQREG_ISAINT, ISAINT_IDE1,
242 3, 4 },
243 };
244
245 const int p5064_isa_to_irqmap[16] = {
246 -1, /* 0 */
247 P5064_IRQ_MKBD, /* 1 */
248 -1, /* 2 */
249 P5064_IRQ_COM2, /* 3 */
250 P5064_IRQ_COM1, /* 4 */
251 -1, /* 5 */
252 P5064_IRQ_FLOPPY, /* 6 */
253 P5064_IRQ_CENTRONICS, /* 7 */
254 P5064_IRQ_RTC, /* 8 */
255 -1, /* 9 */
256 -1, /* 10 */
257 -1, /* 11 */
258 P5064_IRQ_MKBD, /* 12 */
259 -1, /* 13 */
260 P5064_IRQ_IDE0, /* 14 */
261 P5064_IRQ_IDE1, /* 15 */
262 };
263
264 struct p5064_intrhead {
265 struct evcnt intr_count;
266 int intr_refcnt;
267 };
268 struct p5064_intrhead p5064_intrtab[NIRQMAPS];
269
270 #define NINTRS 3 /* MIPS INT0 - INT2 */
271
272 struct p5064_cpuintr {
273 LIST_HEAD(, evbmips_intrhand) cintr_list;
274 struct evcnt cintr_count;
275 };
276
277 struct p5064_cpuintr p5064_cpuintrs[NINTRS];
278 const char * const p5064_cpuintrnames[NINTRS] = {
279 "int 0 (isa)",
280 "int 1 (pci)",
281 "int 2 (local)",
282 };
283
284 const char * const p5064_intrgroups[NINTRS] = {
285 "isa",
286 "pci",
287 "local",
288 };
289
290 void *algor_p5064_intr_establish(int, int (*)(void *), void *);
291 void algor_p5064_intr_disestablish(void *);
292
293 int algor_p5064_pci_intr_map(const struct pci_attach_args *,
294 pci_intr_handle_t *);
295 const char *algor_p5064_pci_intr_string(void *, pci_intr_handle_t, char *, size_t);
296 const struct evcnt *algor_p5064_pci_intr_evcnt(void *, pci_intr_handle_t);
297 void *algor_p5064_pci_intr_establish(void *, pci_intr_handle_t, int,
298 int (*)(void *), void *);
299 void algor_p5064_pci_intr_disestablish(void *, void *);
300 void *algor_p5064_pciide_compat_intr_establish(void *, device_t,
301 const struct pci_attach_args *, int, int (*)(void *), void *);
302 void algor_p5064_pci_conf_interrupt(void *, int, int, int, int, int *);
303
304 const struct evcnt *algor_p5064_isa_intr_evcnt(void *, int);
305 void *algor_p5064_isa_intr_establish(void *, int, int, int,
306 int (*)(void *), void *);
307 void algor_p5064_isa_intr_disestablish(void *, void *);
308 int algor_p5064_isa_intr_alloc(void *, int, int, int *);
309
310 void algor_p5064_iointr(int, vaddr_t, uint32_t);
311
312 void
algor_p5064_intr_init(struct p5064_config * acp)313 algor_p5064_intr_init(struct p5064_config *acp)
314 {
315 const struct p5064_irqmap *irqmap;
316 int i;
317
318 for (i = 0; i < NIRQREG; i++)
319 REGVAL(p5064_irqregs[i].addr) = p5064_irqregs[i].val;
320
321 for (i = 0; i < NINTRS; i++) {
322 LIST_INIT(&p5064_cpuintrs[i].cintr_list);
323 evcnt_attach_dynamic(&p5064_cpuintrs[i].cintr_count,
324 EVCNT_TYPE_INTR, NULL, "mips", p5064_cpuintrnames[i]);
325 }
326
327 for (i = 0; i < NIRQMAPS; i++) {
328 irqmap = &p5064_irqmap[i];
329
330 p5064_irqsteer[irqmap->xbarreg].val |=
331 irqmap->cpuintr << irqmap->xbarshift;
332
333 evcnt_attach_dynamic(&p5064_intrtab[i].intr_count,
334 EVCNT_TYPE_INTR, NULL, p5064_intrgroups[irqmap->cpuintr],
335 p5064_intrnames[i]);
336 }
337
338 for (i = 0; i < NSTEERREG; i++)
339 REGVAL(p5064_irqsteer[i].addr) = p5064_irqsteer[i].val;
340
341 acp->ac_pc.pc_intr_v = NULL;
342 acp->ac_pc.pc_intr_map = algor_p5064_pci_intr_map;
343 acp->ac_pc.pc_intr_string = algor_p5064_pci_intr_string;
344 acp->ac_pc.pc_intr_evcnt = algor_p5064_pci_intr_evcnt;
345 acp->ac_pc.pc_intr_establish = algor_p5064_pci_intr_establish;
346 acp->ac_pc.pc_intr_disestablish = algor_p5064_pci_intr_disestablish;
347 acp->ac_pc.pc_conf_interrupt = algor_p5064_pci_conf_interrupt;
348 acp->ac_pc.pc_pciide_compat_intr_establish =
349 algor_p5064_pciide_compat_intr_establish;
350
351 acp->ac_ic.ic_v = NULL;
352 acp->ac_ic.ic_intr_evcnt = algor_p5064_isa_intr_evcnt;
353 acp->ac_ic.ic_intr_establish = algor_p5064_isa_intr_establish;
354 acp->ac_ic.ic_intr_disestablish = algor_p5064_isa_intr_disestablish;
355 acp->ac_ic.ic_intr_alloc = algor_p5064_isa_intr_alloc;
356
357 algor_intr_establish = algor_p5064_intr_establish;
358 algor_intr_disestablish = algor_p5064_intr_disestablish;
359 algor_iointr = algor_p5064_iointr;
360 }
361
362 void
algor_p5064_cal_timer(bus_space_tag_t st,bus_space_handle_t sh)363 algor_p5064_cal_timer(bus_space_tag_t st, bus_space_handle_t sh)
364 {
365 u_long ctrdiff[4], startctr, endctr, cps;
366 uint32_t irr;
367 int i;
368
369 /* Disable interrupts first. */
370 bus_space_write_1(st, sh, 0, MC_REGB);
371 bus_space_write_1(st, sh, 1, MC_REGB_SQWE | MC_REGB_BINARY |
372 MC_REGB_24HR);
373
374 /* Initialize for 16Hz. */
375 bus_space_write_1(st, sh, 0, MC_REGA);
376 bus_space_write_1(st, sh, 1, MC_BASE_32_KHz | MC_RATE_16_Hz);
377
378 REGVAL(P5064_LOCINT) = LOCINT_RTC;
379
380 /* Run the loop an extra time to prime the cache. */
381 for (i = 0; i < 4; i++) {
382 led_display('h', 'z', '0' + i, ' ');
383
384 /* Enable the interrupt. */
385 bus_space_write_1(st, sh, 0, MC_REGB);
386 bus_space_write_1(st, sh, 1, MC_REGB_PIE | MC_REGB_SQWE |
387 MC_REGB_BINARY | MC_REGB_24HR);
388
389 /* Wait for it to happen. */
390 startctr = mips3_cp0_count_read();
391 do {
392 irr = REGVAL(P5064_LOCINT);
393 endctr = mips3_cp0_count_read();
394 } while ((irr & LOCINT_RTC) == 0);
395
396 /* ACK. */
397 bus_space_write_1(st, sh, 0, MC_REGC);
398 (void) bus_space_read_1(st, sh, 1);
399
400 /* Disable. */
401 bus_space_write_1(st, sh, 0, MC_REGB);
402 bus_space_write_1(st, sh, 1, MC_REGB_SQWE | MC_REGB_BINARY |
403 MC_REGB_24HR);
404
405 ctrdiff[i] = endctr - startctr;
406 }
407
408 REGVAL(P5064_LOCINT) = 0;
409
410 /* Update CPU frequency values */
411 cps = ((ctrdiff[2] + ctrdiff[3]) / 2) * 16;
412 #if 1
413 /* XXX for unaccurate emulators */
414 if (cps < 10 * 1000 * 1000) {
415 /* unlikely, use a reasonable value */
416 cps = 75 * 1000 * 1000;
417 }
418 #endif
419 /* XXX mips_cpu_flags isn't set here; assume CPU_MIPS_DOUBLE_COUNT */
420 curcpu()->ci_cpu_freq = cps * 2;
421 curcpu()->ci_cycles_per_hz = (curcpu()->ci_cpu_freq + hz / 2) / hz;
422 curcpu()->ci_divisor_delay =
423 ((curcpu()->ci_cpu_freq + (1000000 / 2)) / 1000000);
424 /* XXX assume CPU_MIPS_DOUBLE_COUNT */
425 curcpu()->ci_cycles_per_hz /= 2;
426 curcpu()->ci_divisor_delay /= 2;
427
428 printf("Timer calibration: %lu cycles/sec [(%lu, %lu) * 16]\n",
429 cps, ctrdiff[2], ctrdiff[3]);
430 printf("CPU clock speed = %lu.%02luMHz "
431 "(hz cycles = %lu, delay divisor = %lu)\n",
432 curcpu()->ci_cpu_freq / 1000000,
433 (curcpu()->ci_cpu_freq % 1000000) / 10000,
434 curcpu()->ci_cycles_per_hz, curcpu()->ci_divisor_delay);
435 }
436
437 void *
algor_p5064_intr_establish(int irq,int (* func)(void *),void * arg)438 algor_p5064_intr_establish(int irq, int (*func)(void *), void *arg)
439 {
440 const struct p5064_irqmap *irqmap;
441 struct evbmips_intrhand *ih;
442 int s;
443
444 irqmap = &p5064_irqmap[irq];
445
446 KASSERT(irq == irqmap->irqidx);
447
448 ih = kmem_alloc(sizeof(*ih), KM_SLEEP);
449 ih->ih_func = func;
450 ih->ih_arg = arg;
451 ih->ih_irq = 0;
452 ih->ih_irqmap = irqmap;
453
454 s = splhigh();
455
456 /*
457 * First, link it into the tables.
458 */
459 LIST_INSERT_HEAD(&p5064_cpuintrs[irqmap->cpuintr].cintr_list,
460 ih, ih_q);
461
462 /*
463 * Now enable it.
464 */
465 if (p5064_intrtab[irqmap->irqidx].intr_refcnt++ == 0) {
466 p5064_irqregs[irqmap->irqreg].val |= irqmap->irqbit;
467 REGVAL(p5064_irqregs[irqmap->irqreg].addr) =
468 p5064_irqregs[irqmap->irqreg].val;
469 }
470
471 splx(s);
472
473 return (ih);
474 }
475
476 void
algor_p5064_intr_disestablish(void * cookie)477 algor_p5064_intr_disestablish(void *cookie)
478 {
479 const struct p5064_irqmap *irqmap;
480 struct evbmips_intrhand *ih = cookie;
481 int s;
482
483 irqmap = ih->ih_irqmap;
484
485 s = splhigh();
486
487 /*
488 * First, remove it from the table.
489 */
490 LIST_REMOVE(ih, ih_q);
491
492 /*
493 * Now, disable it, if there is nothing remaining on the
494 * list.
495 */
496 if (p5064_intrtab[irqmap->irqidx].intr_refcnt-- == 1) {
497 p5064_irqregs[irqmap->irqreg].val &= ~irqmap->irqbit;
498 REGVAL(p5064_irqregs[irqmap->irqreg].addr) =
499 p5064_irqregs[irqmap->irqreg].val;
500 }
501
502 splx(s);
503
504 kmem_free(ih, sizeof(*ih));
505 }
506
507 void
algor_p5064_iointr(int ipl,vaddr_t pc,uint32_t ipending)508 algor_p5064_iointr(int ipl, vaddr_t pc, uint32_t ipending)
509 {
510 const struct p5064_irqmap *irqmap;
511 struct evbmips_intrhand *ih;
512 int level, i;
513 uint32_t irr[NIRQREG];
514
515 /* Check for PANIC interrupts. */
516 if (ipending & MIPS_INT_MASK_4) {
517 irr[IRQREG_PANIC] = REGVAL(p5064_irqregs[IRQREG_PANIC].addr);
518 if (irr[IRQREG_PANIC] & PANIC_IOPERR)
519 printf("WARNING: I/O parity error\n");
520 if (irr[IRQREG_PANIC] & PANIC_ISANMI)
521 printf("WARNING: ISA NMI\n");
522 if (irr[IRQREG_PANIC] & PANIC_BERR)
523 printf("WARNING: Bus error\n");
524 if (irr[IRQREG_PANIC] & PANIC_PFAIL)
525 printf("WARNING: Power failure\n");
526 if (irr[IRQREG_PANIC] & PANIC_DEBUG) {
527 #ifdef DDB
528 printf("Debug switch -- entering debugger\n");
529 led_display('D','D','B',' ');
530 Debugger();
531 led_display('N','B','S','D');
532 #else
533 printf("Debug switch ignored -- "
534 "no debugger configured\n");
535 #endif
536 }
537
538 /* Clear them. */
539 REGVAL(p5064_irqregs[IRQREG_PANIC].addr) = irr[IRQREG_PANIC];
540 }
541
542 /*
543 * Read the interrupt pending registers, mask them with the
544 * ones we have enabled, and service them in order of decreasing
545 * priority.
546 */
547 for (i = 0; i < NIRQREG; i++) {
548 if (i == IRQREG_PANIC)
549 continue;
550 irr[i] = REGVAL(p5064_irqregs[i].addr) & p5064_irqregs[i].val;
551 }
552
553 for (level = (NINTRS - 1); level >= 0; level--) {
554 if ((ipending & (MIPS_INT_MASK_0 << level)) == 0)
555 continue;
556 p5064_cpuintrs[level].cintr_count.ev_count++;
557 for (ih = LIST_FIRST(&p5064_cpuintrs[level].cintr_list);
558 ih != NULL; ih = LIST_NEXT(ih, ih_q)) {
559 irqmap = ih->ih_irqmap;
560 if (irr[irqmap->irqreg] & irqmap->irqbit) {
561 p5064_intrtab[
562 irqmap->irqidx].intr_count.ev_count++;
563 (*ih->ih_func)(ih->ih_arg);
564 }
565 }
566 }
567 }
568
569 /*****************************************************************************
570 * PCI interrupt support
571 *****************************************************************************/
572
573 int
algor_p5064_pci_intr_map(const struct pci_attach_args * pa,pci_intr_handle_t * ihp)574 algor_p5064_pci_intr_map(const struct pci_attach_args *pa,
575 pci_intr_handle_t *ihp)
576 {
577 static const int pciirqmap[6/*device*/][4/*pin*/] = {
578 { P5064_IRQ_ETHERNET, -1, -1, -1 }, /* 0: Ethernet */
579 { P5064_IRQ_SCSI, -1, -1, -1 }, /* 1: SCSI */
580 { -1, -1, -1, P5064_IRQ_USB }, /* 2: PCI-ISA bridge */
581 { 0, 1, 2, 3 }, /* 3: PCI slot 3 */
582 { 3, 0, 1, 2 }, /* 4: PCI slot 2 */
583 { 2, 3, 0, 1 }, /* 5: PCI slot 1 */
584 };
585 pcitag_t bustag = pa->pa_intrtag;
586 int buspin = pa->pa_intrpin;
587 pci_chipset_tag_t pc = pa->pa_pc;
588 int device, irq;
589
590 if (buspin == 0) {
591 /* No IRQ used. */
592 return (1);
593 }
594
595 if (buspin > 4) {
596 printf("algor_p5064_pci_intr_map: bad interrupt pin %d\n",
597 buspin);
598 return (1);
599 }
600
601 pci_decompose_tag(pc, bustag, NULL, &device, NULL);
602 if (device > 5) {
603 printf("algor_p5064_pci_intr_map: bad device %d\n",
604 device);
605 return (1);
606 }
607
608 irq = pciirqmap[device][buspin - 1];
609 if (irq == -1) {
610 printf("algor_p5064_pci_intr_map: no mapping for "
611 "device %d pin %d\n", device, buspin);
612 return (1);
613 }
614
615 *ihp = irq;
616 return (0);
617 }
618
619 const char *
algor_p5064_pci_intr_string(void * v,pci_intr_handle_t ih,char * buf,size_t len)620 algor_p5064_pci_intr_string(void *v, pci_intr_handle_t ih, char *buf, size_t len)
621 {
622
623 if (ih >= NPCIIRQS)
624 panic("algor_p5064_intr_string: bogus IRQ %ld", ih);
625
626 strlcpy(buf, p5064_intrnames[ih], len);
627 return buf;
628 }
629
630 const struct evcnt *
algor_p5064_pci_intr_evcnt(void * v,pci_intr_handle_t ih)631 algor_p5064_pci_intr_evcnt(void *v, pci_intr_handle_t ih)
632 {
633
634 return (&p5064_intrtab[ih].intr_count);
635 }
636
637 void *
algor_p5064_pci_intr_establish(void * v,pci_intr_handle_t ih,int level,int (* func)(void *),void * arg)638 algor_p5064_pci_intr_establish(void *v, pci_intr_handle_t ih, int level,
639 int (*func)(void *), void *arg)
640 {
641
642 if (ih >= NPCIIRQS)
643 panic("algor_p5064_intr_establish: bogus IRQ %ld", ih);
644
645 return (algor_p5064_intr_establish(ih, func, arg));
646 }
647
648 void
algor_p5064_pci_intr_disestablish(void * v,void * cookie)649 algor_p5064_pci_intr_disestablish(void *v, void *cookie)
650 {
651
652 return (algor_p5064_intr_disestablish(cookie));
653 }
654
655 void
algor_p5064_pci_conf_interrupt(void * v,int bus,int dev,int pin,int swiz,int * iline)656 algor_p5064_pci_conf_interrupt(void *v, int bus, int dev, int pin, int swiz,
657 int *iline)
658 {
659
660 /*
661 * We actually don't need to do anything; everything is handled
662 * in pci_intr_map().
663 */
664 *iline = 0;
665 }
666
667 void *
algor_p5064_pciide_compat_intr_establish(void * v,device_t dev,const struct pci_attach_args * pa,int chan,int (* func)(void *),void * arg)668 algor_p5064_pciide_compat_intr_establish(void *v, device_t dev,
669 const struct pci_attach_args *pa, int chan, int (*func)(void *), void *arg)
670 {
671 pci_chipset_tag_t pc = pa->pa_pc;
672 void *cookie;
673 int bus;
674
675 pci_decompose_tag(pc, pa->pa_tag, &bus, NULL, NULL);
676
677 /*
678 * If this isn't PCI bus #0, all bets are off.
679 */
680 if (bus != 0)
681 return (NULL);
682
683 cookie = algor_p5064_intr_establish(P5064_IRQ_IDE0 + chan, func, arg);
684 if (cookie == NULL)
685 return (NULL);
686 aprint_normal_dev(dev, "%s channel interrupting at on-board %s IRQ\n",
687 PCIIDE_CHANNEL_NAME(chan), p5064_intrnames[P5064_IRQ_IDE0 + chan]);
688 return (cookie);
689 }
690
691 /*****************************************************************************
692 * ISA interrupt support
693 *****************************************************************************/
694
695 const struct evcnt *
algor_p5064_isa_intr_evcnt(void * v,int iirq)696 algor_p5064_isa_intr_evcnt(void *v, int iirq)
697 {
698
699 /* XXX */
700 return (NULL);
701 }
702
703 void *
algor_p5064_isa_intr_establish(void * v,int iirq,int type,int level,int (* func)(void *),void * arg)704 algor_p5064_isa_intr_establish(void *v, int iirq, int type, int level,
705 int (*func)(void *), void *arg)
706 {
707 struct evbmips_intrhand *ih;
708 int irqidx;
709
710 if (iirq > 15 || type == IST_NONE)
711 panic("algor_p5064_isa_intr_establish: bad irq or type");
712
713 if ((irqidx = p5064_isa_to_irqmap[iirq]) == -1)
714 return (NULL);
715
716 ih = algor_p5064_intr_establish(irqidx, func, arg);
717 if (ih != NULL) {
718 /* Translate it to an ISA IRQ. */
719 ih->ih_irq = iirq;
720 }
721 return (ih);
722 }
723
724 void
algor_p5064_isa_intr_disestablish(void * v,void * cookie)725 algor_p5064_isa_intr_disestablish(void *v, void *cookie)
726 {
727 struct evbmips_intrhand *ih = cookie;
728
729 /* Translate the IRQ back to our domain. */
730 ih->ih_irq = p5064_isa_to_irqmap[ih->ih_irq];
731
732 algor_p5064_intr_disestablish(ih);
733 }
734
735 int
algor_p5064_isa_intr_alloc(void * v,int mask,int type,int * iirq)736 algor_p5064_isa_intr_alloc(void *v, int mask, int type, int *iirq)
737 {
738
739 /* XXX */
740 return (1);
741 }
742