xref: /netbsd/sys/arch/algor/algor/algor_p5064_intr.c (revision 7498b2ef)
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