xref: /netbsd/sys/arch/alpha/pci/pci_2100_a500.c (revision c4a72b64)
1 /* $NetBSD: pci_2100_a500.c,v 1.5 2002/09/27 15:35:37 provos Exp $ */
2 
3 /*-
4  * Copyright (c) 1999 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  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the NetBSD
21  *	Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
40 
41 __KERNEL_RCSID(0, "$NetBSD: pci_2100_a500.c,v 1.5 2002/09/27 15:35:37 provos Exp $");
42 
43 #include <sys/types.h>
44 #include <sys/param.h>
45 #include <sys/time.h>
46 #include <sys/systm.h>
47 #include <sys/errno.h>
48 #include <sys/malloc.h>
49 #include <sys/device.h>
50 #include <sys/syslog.h>
51 
52 #include <machine/autoconf.h>
53 
54 #include <dev/eisa/eisavar.h>
55 
56 #include <dev/pci/pcireg.h>
57 #include <dev/pci/pcivar.h>
58 
59 #include <alpha/pci/ttwogareg.h>
60 #include <alpha/pci/ttwogavar.h>
61 #include <alpha/pci/pci_2100_a500.h>
62 
63 static bus_space_tag_t pic_iot;
64 static bus_space_handle_t pic_master_ioh;
65 static bus_space_handle_t pic_slave_ioh[4];
66 static bus_space_handle_t pic_elcr_ioh;
67 
68 static const int pic_slave_to_master[4] = { 1, 3, 4, 5 };
69 
70 int	dec_2100_a500_pic_intr_map(struct pci_attach_args *,
71 	    pci_intr_handle_t *);
72 
73 int	dec_2100_a500_icic_intr_map(struct pci_attach_args *,
74 	    pci_intr_handle_t *);
75 
76 const char *dec_2100_a500_intr_string(void *, pci_intr_handle_t);
77 const struct evcnt *dec_2100_a500_intr_evcnt(void *, pci_intr_handle_t);
78 void	*dec_2100_a500_intr_establish(void *, pci_intr_handle_t,
79 	    int, int (*)(void *), void *);
80 void	dec_2100_a500_intr_disestablish(void *, void *);
81 
82 int	dec_2100_a500_eisa_intr_map(void *, u_int, eisa_intr_handle_t *);
83 const char *dec_2100_a500_eisa_intr_string(void *, int);
84 const struct evcnt *dec_2100_a500_eisa_intr_evcnt(void *, int);
85 void	*dec_2100_a500_eisa_intr_establish(void *, int, int, int,
86 	    int (*)(void *), void *);
87 void	dec_2100_a500_eisa_intr_disestablish(void *, void *);
88 int	dec_2100_a500_eisa_intr_alloc(void *, int, int, int *);
89 
90 #define	PCI_STRAY_MAX	5
91 
92 /*
93  * On systems with cascaded 8259s, it's actually 32.  Systems which
94  * use the ICIC interrupt logic have 64, however.
95  */
96 #define	SABLE_MAX_IRQ		64
97 #define	SABLE_8259_MAX_IRQ	32
98 
99 void	dec_2100_a500_iointr(void *, u_long);
100 
101 void	dec_2100_a500_pic_enable_intr(struct ttwoga_config *, int, int);
102 void	dec_2100_a500_pic_init_intr(struct ttwoga_config *);
103 void	dec_2100_a500_pic_setlevel(struct ttwoga_config *, int, int);
104 void	dec_2100_a500_pic_eoi(struct ttwoga_config *, int);
105 
106 void	dec_2100_a500_icic_enable_intr(struct ttwoga_config *, int, int);
107 void	dec_2100_a500_icic_init_intr(struct ttwoga_config *);
108 void	dec_2100_a500_icic_setlevel(struct ttwoga_config *, int, int);
109 void	dec_2100_a500_icic_eoi(struct ttwoga_config *, int);
110 
111 #define	T2_IRQ_EISA_START	7
112 #define	T2_IRQ_EISA_COUNT	16
113 
114 #define	T2_IRQ_IS_EISA(irq)						\
115 	((irq) >= T2_IRQ_EISA_START &&					\
116 	 (irq) < (T2_IRQ_EISA_START + T2_IRQ_EISA_COUNT))
117 
118 const int dec_2100_a500_intr_deftype[SABLE_MAX_IRQ] = {
119 	IST_LEVEL,		/* PCI slot 0 A */
120 	IST_LEVEL,		/* on-board SCSI */
121 	IST_LEVEL,		/* on-board Ethernet */
122 	IST_EDGE,		/* mouse */
123 	IST_LEVEL,		/* PCI slot 1 A */
124 	IST_LEVEL,		/* PCI slot 2 A */
125 	IST_EDGE,		/* keyboard */
126 	IST_EDGE,		/* floppy (EISA IRQ 0) */
127 	IST_EDGE,		/* serial port 1 (EISA IRQ 1) */
128 	IST_EDGE,		/* parallel port (EISA IRQ 2) */
129 	IST_NONE,		/* EISA IRQ 3 (edge/level) */
130 	IST_NONE,		/* EISA IRQ 4 (edge/level) */
131 	IST_NONE,		/* EISA IRQ 5 (edge/level) */
132 	IST_NONE,		/* EISA IRQ 6 (edge/level) */
133 	IST_NONE,		/* EISA IRQ 7 (edge/level) */
134 	IST_EDGE,		/* serial port 0 (EISA IRQ 8) */
135 	IST_NONE,		/* EISA IRQ 9 (edge/level) */
136 	IST_NONE,		/* EISA IRQ 10 (edge/level) */
137 	IST_NONE,		/* EISA IRQ 11 (edge/level) */
138 	IST_NONE,		/* EISA IRQ 12 (edge/level) */
139 	IST_LEVEL,		/* PCI slot 2 B (EISA IRQ 13 n/c) */
140 	IST_NONE,		/* EISA IRQ 14 (edge/level) */
141 	IST_NONE,		/* EISA IRQ 15 (edge/level) */
142 	IST_LEVEL,		/* I2C (XXX double-check this) */
143 	IST_LEVEL,		/* PCI slot 0 B */
144 	IST_LEVEL,		/* PCI slot 1 B */
145 	IST_LEVEL,		/* PCI slot 0 C */
146 	IST_LEVEL,		/* PCI slot 1 C */
147 	IST_LEVEL,		/* PCI slot 2 C */
148 	IST_LEVEL,		/* PCI slot 0 D */
149 	IST_LEVEL,		/* PCI slot 1 D */
150 	IST_LEVEL,		/* PCI slot 2 D */
151 
152 	/*
153 	 * These are the PCI interrupts on the T3/T4 systems.  See
154 	 * dec_2100_a500_icic_intr_map() for the mapping.
155 	 */
156 	IST_LEVEL,
157 	IST_LEVEL,
158 	IST_LEVEL,
159 	IST_LEVEL,
160 	IST_LEVEL,
161 	IST_LEVEL,
162 	IST_LEVEL,
163 	IST_LEVEL,
164 	IST_LEVEL,
165 	IST_LEVEL,
166 	IST_LEVEL,
167 	IST_LEVEL,
168 	IST_LEVEL,
169 	IST_LEVEL,
170 	IST_LEVEL,
171 	IST_LEVEL,
172 	IST_LEVEL,
173 	IST_LEVEL,
174 	IST_LEVEL,
175 	IST_LEVEL,
176 	IST_LEVEL,
177 	IST_LEVEL,
178 	IST_LEVEL,
179 	IST_LEVEL,
180 	IST_LEVEL,
181 	IST_LEVEL,
182 	IST_LEVEL,
183 	IST_LEVEL,
184 	IST_LEVEL,
185 	IST_LEVEL,
186 	IST_LEVEL,
187 	IST_LEVEL,
188 };
189 
190 void
191 pci_2100_a500_pickintr(struct ttwoga_config *tcp)
192 {
193 	pci_chipset_tag_t pc = &tcp->tc_pc;
194 	char *cp;
195 	int i;
196 
197 	pic_iot = &tcp->tc_iot;
198 
199 	pc->pc_intr_v = tcp;
200 	pc->pc_intr_string = dec_2100_a500_intr_string;
201 	pc->pc_intr_evcnt = dec_2100_a500_intr_evcnt;
202 	pc->pc_intr_establish = dec_2100_a500_intr_establish;
203 	pc->pc_intr_disestablish = dec_2100_a500_intr_disestablish;
204 
205 	/* Not supported on T2. */
206 	pc->pc_pciide_compat_intr_establish = NULL;
207 
208 	tcp->tc_intrtab = alpha_shared_intr_alloc(SABLE_MAX_IRQ, 8);
209 	for (i = 0; i < SABLE_MAX_IRQ; i++) {
210 		alpha_shared_intr_set_dfltsharetype(tcp->tc_intrtab,
211 		    i, tcp->tc_hose == 0 ?
212 		    dec_2100_a500_intr_deftype[i] : IST_LEVEL);
213 		alpha_shared_intr_set_maxstrays(tcp->tc_intrtab,
214 		    i, PCI_STRAY_MAX);
215 
216 		cp = alpha_shared_intr_string(tcp->tc_intrtab, i);
217 		sprintf(cp, "irq %d", T2_IRQ_IS_EISA(i) ?
218 		    i - T2_IRQ_EISA_START : i);
219 		evcnt_attach_dynamic(alpha_shared_intr_evcnt(
220 		    tcp->tc_intrtab, i), EVCNT_TYPE_INTR, NULL,
221 		    T2_IRQ_IS_EISA(i) ? "eisa" : "T2", cp);
222 	}
223 
224 	/* 64 16-byte vectors per hose. */
225 	tcp->tc_vecbase = 0x800 + ((64 * 16) * tcp->tc_hose);
226 
227 	/*
228 	 * T2 uses a custom layout of cascaded 8259 PICs for interrupt
229 	 * control.  T3 and T4 use a built-in interrupt controller.
230 	 *
231 	 * Note that the external PCI bus (Hose 1) always uses
232 	 * the new interrupt controller.
233 	 */
234 	if (tcp->tc_rev < TRN_T3 && tcp->tc_hose == 0) {
235 		pc->pc_intr_map = dec_2100_a500_pic_intr_map;
236 		tcp->tc_enable_intr = dec_2100_a500_pic_enable_intr;
237 		tcp->tc_setlevel = dec_2100_a500_pic_setlevel;
238 		tcp->tc_eoi = dec_2100_a500_pic_eoi;
239 		dec_2100_a500_pic_init_intr(tcp);
240 	} else {
241 		pc->pc_intr_map = dec_2100_a500_icic_intr_map;
242 		tcp->tc_enable_intr = dec_2100_a500_icic_enable_intr;
243 		tcp->tc_setlevel = dec_2100_a500_icic_setlevel;
244 		tcp->tc_eoi = dec_2100_a500_icic_eoi;
245 		dec_2100_a500_icic_init_intr(tcp);
246 	}
247 }
248 
249 void
250 pci_2100_a500_eisa_pickintr(pci_chipset_tag_t pc, eisa_chipset_tag_t ec)
251 {
252 
253 	ec->ec_v = pc->pc_intr_v;
254 	ec->ec_intr_map = dec_2100_a500_eisa_intr_map;
255 	ec->ec_intr_string = dec_2100_a500_eisa_intr_string;
256 	ec->ec_intr_evcnt = dec_2100_a500_eisa_intr_evcnt;
257 	ec->ec_intr_establish = dec_2100_a500_eisa_intr_establish;
258 	ec->ec_intr_disestablish = dec_2100_a500_eisa_intr_disestablish;
259 }
260 
261 void
262 pci_2100_a500_isa_pickintr(pci_chipset_tag_t pc, isa_chipset_tag_t ic)
263 {
264 
265 	ic->ic_v = pc->pc_intr_v;
266 	ic->ic_intr_evcnt = dec_2100_a500_eisa_intr_evcnt;
267 	ic->ic_intr_establish = dec_2100_a500_eisa_intr_establish;
268 	ic->ic_intr_disestablish = dec_2100_a500_eisa_intr_disestablish;
269 	ic->ic_intr_alloc = dec_2100_a500_eisa_intr_alloc;
270 }
271 
272 /*****************************************************************************
273  * PCI interrupt support.
274  *****************************************************************************/
275 
276 int
277 dec_2100_a500_pic_intr_map(struct pci_attach_args *pa,
278     pci_intr_handle_t *ihp)
279 {
280 	/*
281 	 * Interrupts in the Sable are even more of a pain than other
282 	 * Alpha systems.  The interrupt logic is made up of 5 8259
283 	 * PICs, arranged as follows:
284 	 *
285 	 *	Slave 0 --------------------------------+
286 	 *	0 PCI slot 0 A				|
287 	 *	1 on-board SCSI				|
288 	 *	2 on-board Ethernet			|
289 	 *	3 mouse					|
290 	 *	4 PCI slot 1 A				|
291 	 *	5 PCI slot 2 A				|
292 	 *	6 keyboard				|
293 	 *	7 floppy (EISA IRQ 0)			|
294 	 *						|
295 	 *	Slave 1	------------------------+	|   Master
296 	 *	0 serial port 1 (EISA IRQ 1)	|	|   0 ESC interrupt
297 	 *	1 parallel port (EISA IRQ 2)	|	+-- 1 Slave 0
298 	 *	2 EISA IRQ 3			|	    2 reserved
299 	 *	3 EISA IRQ 4			+---------- 3 Slave 1
300 	 *	4 EISA IRQ 5			+---------- 4 Slave 2
301 	 *	5 EISA IRQ 6			|	+-- 5 Slave 3
302 	 *	6 EISA IRQ 7			|	|   6 reserved
303 	 *	7 serial port 0 (EISA IRQ 8)	|	|   7 n/c
304 	 *					|	|
305 	 *	Slave 2 ------------------------+	|
306 	 *	0 EISA IRQ 9				|
307 	 *	1 EISA IRQ 10				|
308 	 *	2 EISA IRQ 11				|
309 	 *	3 EISA IRQ 12				|
310 	 *	4 PCI slot 2 B (EISA IRQ 13 n/c)	|
311 	 *	5 EISA IRQ 14				|
312 	 *	6 EISA IRQ 15				|
313 	 *	7 I2C					|
314 	 *						|
315 	 *	Slave 3 --------------------------------+
316 	 *	0 PCI slot 0 B
317 	 *	1 PCI slot 1 B
318 	 *	2 PCI slot 0 C
319 	 *	3 PCI slot 1 C
320 	 *	4 PCI slot 2 C
321 	 *	5 PCI slot 0 D
322 	 *	6 PCI slot 1 D
323 	 *	7 PCI slot 2 D
324 	 *
325 	 * Careful readers will note that the PCEB does not handle ISA
326 	 * interrupts at all; when ISA interrupts are established, they
327 	 * must be mapped to Sable interrupts.  Thankfully, this is easy
328 	 * to do.
329 	 *
330 	 * The T3 and T4, generally found on Lynx, use a totally different
331 	 * scheme because they have more PCI interrupts to handle; see below.
332 	 */
333 	static const int irqmap[9/*device*/][4/*pin*/] = {
334 		{ 0x02, -1, -1, -1 },		/* 0: on-board Ethernet */
335 		{ 0x01, -1, -1, -1 },		/* 1: on-board SCSI */
336 		{ -1, -1, -1, -1 },		/* 2: invalid */
337 		{ -1, -1, -1, -1 },		/* 3: invalid */
338 		{ -1, -1, -1, -1 },		/* 4: invalid */
339 		{ -1, -1, -1, -1 },		/* 5: invalid */
340 		{ 0x00, 0x18, 0x1a, 0x1d },	/* 6: PCI slot 0 */
341 		{ 0x04, 0x19, 0x1b, 0x1e },	/* 7: PCI slot 1 */
342 		{ 0x05, 0x14, 0x1c, 0x1f },	/* 8: PCI slot 2 */
343 	};
344 	pcitag_t bustag = pa->pa_intrtag;
345 	int buspin = pa->pa_intrpin;
346 	pci_chipset_tag_t pc = pa->pa_pc;
347 	int device, irq;
348 
349 	if (buspin == 0) {
350 		/* No IRQ used. */
351 		return (1);
352 	}
353 
354 	if (buspin > 4) {
355 		printf("dec_2100_a500_pic_intr_map: bad interrupt pin %d\n",
356 		    buspin);
357 		return (1);
358 	}
359 
360 	pci_decompose_tag(pc, bustag, NULL, &device, NULL);
361 	if (device > 8) {
362 		printf("dec_2100_a500_pic_intr_map: bad device %d\n",
363 		    device);
364 		return (1);
365 	}
366 
367 	irq = irqmap[device][buspin - 1];
368 	if (irq == -1) {
369 		printf("dec_2100_a500_pic_intr_map: no mapping for "
370 		    "device %d pin %d\n", device, buspin);
371 		return (1);
372 	}
373 	*ihp = irq;
374 	return (0);
375 }
376 
377 int
378 dec_2100_a500_icic_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
379 {
380 	pcitag_t bustag = pa->pa_intrtag;
381 	int buspin = pa->pa_intrpin;
382 	pci_chipset_tag_t pc = pa->pa_pc;
383 	int device, irq;
384 
385 	if (buspin == 0) {
386 		/* No IRQ used. */
387 		return (1);
388 	}
389 
390 	if (buspin > 4) {
391 		printf("dec_2100_a500_icic_intr_map: bad interrupt in %d\n",
392 		    buspin);
393 		return (1);
394 	}
395 
396 	pci_decompose_tag(pc, bustag, NULL, &device, NULL);
397 	switch (device) {
398 	case 0:		/* on-board Ethernet */
399 		irq = 24;
400 		break;
401 
402 	case 1:		/* on-board SCSI */
403 		irq = 28;
404 		break;
405 
406 	case 6:		/* PCI slots */
407 	case 7:
408 	case 8:
409 		irq = (32 + (4 * (device - 6))) + (buspin - 1);
410 		break;
411 
412 	default:
413 		printf("dec_2100_a500_icic_intr_map: bad device %d\n",
414 		    device);
415 		return (1);
416 	}
417 
418 	*ihp = irq;
419 	return (0);
420 }
421 
422 const char *
423 dec_2100_a500_intr_string(void *v, pci_intr_handle_t ih)
424 {
425 	static char irqstr[15];		/* 11 + 2 + NULL + sanity */
426 
427 	if (ih >= SABLE_MAX_IRQ)
428 		panic("dec_2100_a500_intr_string: bogus T2 IRQ 0x%lx", ih);
429 
430 	sprintf(irqstr, "T2 irq %ld", ih);
431 	return (irqstr);
432 }
433 
434 const struct evcnt *
435 dec_2100_a500_intr_evcnt(void *v, pci_intr_handle_t ih)
436 {
437 	struct ttwoga_config *tcp = v;
438 
439 	if (ih >= SABLE_MAX_IRQ)
440 		panic("dec_2100_a500_intr_evcnt: bogus T2 IRQ 0x%lx", ih);
441 
442 	return (alpha_shared_intr_evcnt(tcp->tc_intrtab, ih));
443 }
444 
445 void *
446 dec_2100_a500_intr_establish(void *v, pci_intr_handle_t ih, int level,
447     int (*func)(void *), void *arg)
448 {
449 	struct ttwoga_config *tcp = v;
450 	void *cookie;
451 
452 	if (ih >= SABLE_MAX_IRQ)
453 		panic("dec_2100_a500_intr_establish: bogus IRQ 0x%lx",
454 		    ih);
455 
456 	cookie = alpha_shared_intr_establish(tcp->tc_intrtab, ih,
457 	    dec_2100_a500_intr_deftype[ih], level, func, arg, "T2 irq");
458 
459 	if (cookie != NULL &&
460 	    alpha_shared_intr_firstactive(tcp->tc_intrtab, ih)) {
461 		scb_set(tcp->tc_vecbase + SCB_IDXTOVEC(ih),
462 		    dec_2100_a500_iointr, tcp);
463 		(*tcp->tc_enable_intr)(tcp, ih, 1);
464 	}
465 
466 	return (cookie);
467 }
468 
469 void
470 dec_2100_a500_intr_disestablish(void *v, void *cookie)
471 {
472 	struct ttwoga_config *tcp = v;
473 	struct alpha_shared_intrhand *ih = cookie;
474 	unsigned int irq = ih->ih_num;
475 	int s;
476 
477 	s = splhigh();
478 
479 	alpha_shared_intr_disestablish(tcp->tc_intrtab, cookie,
480 	    "T2 irq");
481 	if (alpha_shared_intr_isactive(tcp->tc_intrtab, irq) == 0) {
482 		(*tcp->tc_enable_intr)(tcp, irq, 0);
483 		alpha_shared_intr_set_dfltsharetype(tcp->tc_intrtab,
484 		    irq, dec_2100_a500_intr_deftype[irq]);
485 		scb_free(tcp->tc_vecbase + SCB_IDXTOVEC(irq));
486 	}
487 
488 	splx(s);
489 }
490 
491 /*****************************************************************************
492  * EISA interrupt support.
493  *****************************************************************************/
494 
495 int
496 dec_2100_a500_eisa_intr_map(void *v, u_int eirq, eisa_intr_handle_t *ihp)
497 {
498 
499 	if (eirq > 15) {
500 		printf("dec_2100_a500_eisa_intr_map: bad EISA IRQ %d\n",
501 		    eirq);
502 		*ihp = -1;
503 		return (1);
504 	}
505 
506 	/*
507 	 * EISA IRQ 13 is not connected.
508 	 */
509 	if (eirq == 13) {
510 		printf("dec_2100_a500_eisa_intr_map: EISA IRQ 13 not "
511 		    "connected\n");
512 		*ihp = -1;
513 		return (1);
514 	}
515 
516 	/*
517 	 * Don't map to a T2 IRQ here; we must do this when we hook the
518 	 * interrupt up, since ISA interrupts aren't explicitly translated.
519 	 */
520 
521 	*ihp = eirq;
522 	return (0);
523 }
524 
525 const char *
526 dec_2100_a500_eisa_intr_string(void *v, int eirq)
527 {
528 	static char irqstr[32];
529 
530 	if (eirq > 15 || eirq == 13)
531 		panic("dec_2100_a500_eisa_intr_string: bogus EISA IRQ 0x%x",
532 		    eirq);
533 
534 	sprintf(irqstr, "eisa irq %d (T2 irq %d)", eirq,
535 	    eirq + T2_IRQ_EISA_START);
536 	return (irqstr);
537 }
538 
539 const struct evcnt *
540 dec_2100_a500_eisa_intr_evcnt(void *v, int eirq)
541 {
542 	struct ttwoga_config *tcp = v;
543 
544 	if (eirq > 15 || eirq == 13)
545 		panic("dec_2100_a500_eisa_intr_evcnt: bogus EISA IRQ 0x%x",
546 		    eirq);
547 
548 	return (alpha_shared_intr_evcnt(tcp->tc_intrtab,
549 	    eirq + T2_IRQ_EISA_START));
550 }
551 
552 void *
553 dec_2100_a500_eisa_intr_establish(void *v, int eirq, int type, int level,
554     int (*fn)(void *), void *arg)
555 {
556 	struct ttwoga_config *tcp = v;
557 	void *cookie;
558 	int irq;
559 
560 	if (eirq > 15 || type == IST_NONE)
561 		panic("dec_2100_a500_eisa_intr_establish: bogus irq or type");
562 
563 	if (eirq == 13) {
564 		printf("dec_2100_a500_eisa_intr_establish: EISA IRQ 13 not "
565 		    "connected\n");
566 		return (NULL);
567 	}
568 
569 	irq = eirq + T2_IRQ_EISA_START;
570 
571 	/*
572 	 * We can't change the trigger type of some interrupts.  Don't allow
573 	 * level triggers to be hooked up to non-changeable edge triggers.
574 	 */
575 	if (dec_2100_a500_intr_deftype[irq] == IST_EDGE && type == IST_LEVEL) {
576 		printf("dec_2100_a500_eisa_intr_establish: non-EDGE on EDGE\n");
577 		return (NULL);
578 	}
579 
580 	cookie = alpha_shared_intr_establish(tcp->tc_intrtab, irq,
581 	    type, level, fn, arg, "T2 irq");
582 
583 	if (cookie != NULL &&
584 	    alpha_shared_intr_firstactive(tcp->tc_intrtab, irq)) {
585 		scb_set(tcp->tc_vecbase + SCB_IDXTOVEC(irq),
586 		    dec_2100_a500_iointr, tcp);
587 		(*tcp->tc_setlevel)(tcp, eirq,
588 		    alpha_shared_intr_get_sharetype(tcp->tc_intrtab,
589 						    irq) == IST_LEVEL);
590 		(*tcp->tc_enable_intr)(tcp, irq, 1);
591 	}
592 
593 	return (cookie);
594 }
595 
596 void
597 dec_2100_a500_eisa_intr_disestablish(void *v, void *cookie)
598 {
599 	struct ttwoga_config *tcp = v;
600 	struct alpha_shared_intrhand *ih = cookie;
601 	int s, irq = ih->ih_num;
602 
603 	s = splhigh();
604 
605 	/* Remove it from the link. */
606 	alpha_shared_intr_disestablish(tcp->tc_intrtab, cookie,
607 	    "T2 irq");
608 
609 	if (alpha_shared_intr_isactive(tcp->tc_intrtab, irq) == 0) {
610 		(*tcp->tc_enable_intr)(tcp, irq, 0);
611 		alpha_shared_intr_set_dfltsharetype(tcp->tc_intrtab,
612 		    irq, dec_2100_a500_intr_deftype[irq]);
613 		scb_free(tcp->tc_vecbase + SCB_IDXTOVEC(irq));
614 	}
615 
616 	splx(s);
617 }
618 
619 int
620 dec_2100_a500_eisa_intr_alloc(void *v, int mask, int type, int *eirqp)
621 {
622 
623 	/* XXX Not supported right now. */
624 	return (1);
625 }
626 
627 /*****************************************************************************
628  * Interrupt support routines.
629  *****************************************************************************/
630 
631 #define	ICIC_ADDR(tcp, addr)						\
632 do {									\
633 	alpha_mb();							\
634 	T2GA((tcp), T2_AIR) = (addr);					\
635 	alpha_mb();							\
636 	alpha_mb();							\
637 	(void) T2GA((tcp), T2_AIR);					\
638 	alpha_mb();							\
639 	alpha_mb();							\
640 } while (0)
641 
642 #define	ICIC_READ(tcp)	T2GA((tcp), T2_DIR)
643 #define	ICIC_WRITE(tcp, val)						\
644 do {									\
645 	alpha_mb();							\
646 	T2GA((tcp), T2_DIR) = (val);					\
647 	alpha_mb();							\
648 	alpha_mb();							\
649 } while (0)
650 
651 void
652 dec_2100_a500_iointr(void *arg, u_long vec)
653 {
654 	struct ttwoga_config *tcp = arg;
655 	int irq, rv;
656 
657 	irq = SCB_VECTOIDX(vec - tcp->tc_vecbase);
658 
659 	rv = alpha_shared_intr_dispatch(tcp->tc_intrtab, irq);
660 	(*tcp->tc_eoi)(tcp, irq);
661 	if (rv == 0) {
662 		alpha_shared_intr_stray(tcp->tc_intrtab, irq, "T2 irq");
663 		if (ALPHA_SHARED_INTR_DISABLE(tcp->tc_intrtab, irq))
664 			(*tcp->tc_enable_intr)(tcp, irq, 0);
665 	}
666 }
667 
668 void
669 dec_2100_a500_pic_enable_intr(struct ttwoga_config *tcp, int irq, int onoff)
670 {
671 	int pic;
672 	u_int8_t bit, mask;
673 
674 	pic = irq >> 3;
675 	bit = 1 << (irq & 0x7);
676 
677 	mask = bus_space_read_1(pic_iot, pic_slave_ioh[pic], 1);
678 	if (onoff)
679 		mask &= ~bit;
680 	else
681 		mask |= bit;
682 	bus_space_write_1(pic_iot, pic_slave_ioh[pic], 1, mask);
683 }
684 
685 void
686 dec_2100_a500_icic_enable_intr(struct ttwoga_config *tcp, int irq, int onoff)
687 {
688 	u_int64_t bit, mask;
689 
690 	bit = 1UL << irq;
691 
692 	ICIC_ADDR(tcp, 0x40);
693 
694 	mask = ICIC_READ(tcp);
695 	if (onoff)
696 		mask &= ~bit;
697 	else
698 		mask |= bit;
699 	ICIC_WRITE(tcp, mask);
700 }
701 
702 void
703 dec_2100_a500_pic_init_intr(struct ttwoga_config *tcp)
704 {
705 	static const int picaddr[4] = {
706 		0x536, 0x53a, 0x53c, 0x53e
707 	};
708 	int pic;
709 
710 	/*
711 	 * Map the master PIC.
712 	 */
713 	if (bus_space_map(pic_iot, 0x534, 2, 0, &pic_master_ioh))
714 		panic("dec_2100_a500_pic_init_intr: unable to map master PIC");
715 
716 	/*
717 	 * Map all slave PICs and mask off the interrupts on them.
718 	 */
719 	for (pic = 0; pic < 4; pic++) {
720 		if (bus_space_map(pic_iot, picaddr[pic], 2, 0,
721 		    &pic_slave_ioh[pic]))
722 			panic("dec_2100_a500_pic_init_intr: unable to map "
723 			    "slave PIC %d", pic);
724 		bus_space_write_1(pic_iot, pic_slave_ioh[pic], 1, 0xff);
725 	}
726 
727 	/*
728 	 * Map the ELCR registers.
729 	 */
730 	if (bus_space_map(pic_iot, 0x26, 2, 0, &pic_elcr_ioh))
731 		panic("dec_2100_a500_pic_init_intr: unable to map ELCR "
732 		    "registers");
733 }
734 
735 void
736 dec_2100_a500_icic_init_intr(struct ttwoga_config *tcp)
737 {
738 
739 	ICIC_ADDR(tcp, 0x40);
740 	ICIC_WRITE(tcp, 0xffffffffffffffffUL);
741 }
742 
743 void
744 dec_2100_a500_pic_setlevel(struct ttwoga_config *tcp, int eirq, int level)
745 {
746 	int elcr;
747 	u_int8_t bit, mask;
748 
749 	switch (eirq) {		/* EISA IRQ */
750 	case 3:
751 	case 4:
752 	case 5:
753 	case 6:
754 	case 7:
755 		elcr = 0;
756 		bit = 1 << (eirq - 3);
757 		break;
758 
759 	case 9:
760 	case 10:
761 	case 11:
762 		elcr = 0;
763 		bit = 1 << (eirq - 4);
764 		break;
765 
766 	case 12:
767 		elcr = 1;
768 		bit = 1 << (eirq - 12);
769 		break;
770 
771 	case 14:
772 	case 15:
773 		elcr = 1;
774 		bit = 1 << (eirq - 13);
775 		break;
776 
777 	default:
778 		panic("dec_2100_a500_pic_setlevel: bogus EISA IRQ %d", eirq);
779 	}
780 
781 	mask = bus_space_read_1(pic_iot, pic_elcr_ioh, elcr);
782 	if (level)
783 		mask |= bit;
784 	else
785 		mask &= ~bit;
786 	bus_space_write_1(pic_iot, pic_elcr_ioh, elcr, mask);
787 }
788 
789 void
790 dec_2100_a500_icic_setlevel(struct ttwoga_config *tcp, int eirq, int level)
791 {
792 	u_int64_t bit, mask;
793 
794 	switch (eirq) {
795 	case 3:
796 	case 4:
797 	case 5:
798 	case 6:
799 	case 7:
800 	case 9:
801 	case 10:
802 	case 11:
803 	case 12:
804 	case 14:
805 	case 15:
806 		bit = 1UL << (eirq + T2_IRQ_EISA_START);
807 
808 		ICIC_ADDR(tcp, 0x50);
809 		mask = ICIC_READ(tcp);
810 		if (level)
811 			mask |= bit;
812 		else
813 			mask &= ~bit;
814 		ICIC_WRITE(tcp, mask);
815 		break;
816 
817 	default:
818 		panic("dec_2100_a500_icic_setlevel: bogus EISA IRQ %d", eirq);
819 	}
820 }
821 
822 void
823 dec_2100_a500_pic_eoi(struct ttwoga_config *tcp, int irq)
824 {
825 	int pic;
826 
827 	if (irq >= 0 && irq <= 7)
828 		pic = 0;
829 	else if (irq >= 8 && irq <= 15)
830 		pic = 1;
831 	else if (irq >= 16 && irq <= 23)
832 		pic = 2;
833 	else
834 		pic = 3;
835 
836 	bus_space_write_1(pic_iot, pic_slave_ioh[pic], 0,
837 	    0xe0 | (irq - (8 * pic)));
838 	bus_space_write_1(pic_iot, pic_master_ioh, 0,
839 	    0xe0 | pic_slave_to_master[pic]);
840 }
841 
842 void
843 dec_2100_a500_icic_eoi(struct ttwoga_config *tcp, int irq)
844 {
845 
846 	T2GA(tcp, T2_VAR) = irq;
847 	alpha_mb();
848 	alpha_mb();	/* MAGIC */
849 }
850