xref: /openbsd/sys/arch/alpha/pci/sio_pic.c (revision cecf84d4)
1 /*	$OpenBSD: sio_pic.c,v 1.37 2014/04/04 20:00:12 miod Exp $	*/
2 /* $NetBSD: sio_pic.c,v 1.28 2000/06/06 03:10:13 thorpej Exp $ */
3 
4 /*-
5  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
10  * NASA Ames Research Center.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /*
35  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
36  * All rights reserved.
37  *
38  * Author: Chris G. Demetriou
39  *
40  * Permission to use, copy, modify and distribute this software and
41  * its documentation is hereby granted, provided that both the copyright
42  * notice and this permission notice appear in all copies of the
43  * software, derivative works or modified versions, and any portions
44  * thereof, and that both notices appear in supporting documentation.
45  *
46  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
47  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
48  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
49  *
50  * Carnegie Mellon requests users of this software to return to
51  *
52  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
53  *  School of Computer Science
54  *  Carnegie Mellon University
55  *  Pittsburgh PA 15213-3890
56  *
57  * any improvements or extensions that they make and grant Carnegie the
58  * rights to redistribute these changes.
59  */
60 
61 #include <sys/param.h>
62 #include <sys/systm.h>
63 
64 #include <sys/device.h>
65 #include <sys/malloc.h>
66 #include <sys/syslog.h>
67 
68 #include <machine/intr.h>
69 #include <machine/bus.h>
70 
71 #include <dev/pci/pcireg.h>
72 #include <dev/pci/pcivar.h>
73 #include <dev/pci/pcidevs.h>
74 
75 #include <dev/pci/cy82c693reg.h>
76 #include <dev/pci/cy82c693var.h>
77 
78 #include <dev/isa/isareg.h>
79 #include <dev/isa/isavar.h>
80 #include <alpha/pci/siovar.h>
81 
82 #include "sio.h"
83 
84 /*
85  * To add to the long history of wonderful PROM console traits,
86  * AlphaStation PROMs don't reset themselves completely on boot!
87  * Therefore, if an interrupt was turned on when the kernel was
88  * started, we're not going to EVER turn it off...  I don't know
89  * what will happen if new interrupts (that the PROM console doesn't
90  * want) are turned on.  I'll burn that bridge when I come to it.
91  */
92 #define	BROKEN_PROM_CONSOLE
93 
94 /*
95  * Private functions and variables.
96  */
97 
98 bus_space_tag_t sio_iot;
99 pci_chipset_tag_t sio_pc;
100 bus_space_handle_t sio_ioh_icu1, sio_ioh_icu2;
101 
102 #define	ICU_LEN		16		/* number of ISA IRQs */
103 
104 static struct alpha_shared_intr *sio_intr;
105 
106 #ifndef STRAY_MAX
107 #define	STRAY_MAX	5
108 #endif
109 
110 #ifdef BROKEN_PROM_CONSOLE
111 /*
112  * If prom console is broken, must remember the initial interrupt
113  * settings and enforce them.  WHEE!
114  */
115 u_int8_t initial_ocw1[2];
116 u_int8_t initial_elcr[2];
117 #endif
118 
119 /*
120  * Overrides for ELCR settings.
121  * These are used on ES40 and similar systems suffering from a PCI USB HCI
122  * interrupt being routed through the ISA logic with actual logic to
123  * make it behave an edge-triggered interrupt, although PCI interrupts are
124  * supposed to be level-triggered.
125  */
126 u_int8_t elcr_override[2] = { 0x00, 0x00 };
127 
128 void		sio_setirqstat(int, int, int);
129 int		sio_intr_alloc(void *, int, int, int *);
130 int		sio_intr_check(void *, int, int);
131 
132 u_int8_t	(*sio_read_elcr)(int);
133 void		(*sio_write_elcr)(int, u_int8_t);
134 static void	specific_eoi(int);
135 
136 /******************** i82378 SIO ELCR functions ********************/
137 
138 int		i82378_setup_elcr(void);
139 u_int8_t	i82378_read_elcr(int);
140 void		i82378_write_elcr(int, u_int8_t);
141 
142 bus_space_handle_t sio_ioh_elcr;
143 
144 int
145 i82378_setup_elcr()
146 {
147 	int device, maxndevs;
148 	pcitag_t tag;
149 	pcireg_t id;
150 	int rv;
151 
152 	/*
153 	 * We could probe configuration space to see that there's
154 	 * actually an SIO present, but we are using this as a
155 	 * fall-back in case nothing else matches.
156 	 */
157 
158 	rv = bus_space_map(sio_iot, 0x4d0, 2, 0, &sio_ioh_elcr);
159 
160 	if (rv != 0)
161 		return 0;
162 
163 	sio_read_elcr = i82378_read_elcr;
164 	sio_write_elcr = i82378_write_elcr;
165 
166 	/*
167 	 * Search PCI configuration space for an ALI M5237 USB controller
168 	 * on the first bus.
169 	 */
170 
171 	maxndevs = pci_bus_maxdevs(sio_pc, 0);
172 
173 	for (device = 0; device < maxndevs; device++) {
174 		tag = pci_make_tag(sio_pc, 0, device, 0);
175 		id = pci_conf_read(sio_pc, tag, PCI_ID_REG);
176 
177 		if (id == PCI_ID_CODE(PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M5237)) {
178 			elcr_override[10 / 8] |= 1 << (10 % 8);
179 			break;
180 		}
181 	}
182 
183 	return (0);
184 }
185 
186 u_int8_t
187 i82378_read_elcr(elcr)
188 	int elcr;
189 {
190 
191 	return (bus_space_read_1(sio_iot, sio_ioh_elcr, elcr));
192 }
193 
194 void
195 i82378_write_elcr(elcr, val)
196 	int elcr;
197 	u_int8_t val;
198 {
199 
200 	bus_space_write_1(sio_iot, sio_ioh_elcr, elcr, val);
201 }
202 
203 /******************** Cypress CY82C693 ELCR functions ********************/
204 
205 int		cy82c693_setup_elcr(void);
206 u_int8_t	cy82c693_read_elcr(int);
207 void		cy82c693_write_elcr(int, u_int8_t);
208 
209 const struct cy82c693_handle *sio_cy82c693_handle;
210 
211 int
212 cy82c693_setup_elcr()
213 {
214 	int device, maxndevs;
215 	pcitag_t tag;
216 	pcireg_t id;
217 
218 	/*
219 	 * Search PCI configuration space for a Cypress CY82C693.
220 	 *
221 	 * Note we can make some assumptions about our bus number
222 	 * here, because:
223 	 *
224 	 *	(1) there can be at most one ISA/EISA bridge per PCI bus, and
225 	 *
226 	 *	(2) any ISA/EISA bridges must be attached to primary PCI
227 	 *	    busses (i.e. bus zero).
228 	 */
229 
230 	maxndevs = pci_bus_maxdevs(sio_pc, 0);
231 
232 	for (device = 0; device < maxndevs; device++) {
233 		tag = pci_make_tag(sio_pc, 0, device, 0);
234 		id = pci_conf_read(sio_pc, tag, PCI_ID_REG);
235 
236 		if (id ==
237 		    PCI_ID_CODE(PCI_VENDOR_CONTAQ, PCI_PRODUCT_CONTAQ_82C693)) {
238 			sio_cy82c693_handle = cy82c693_init(sio_iot);
239 			sio_read_elcr = cy82c693_read_elcr;
240 			sio_write_elcr = cy82c693_write_elcr;
241 			return (0);
242 		}
243 	}
244 
245 	/*
246 	 * Didn't find a CY82C693.
247 	 */
248 	return (ENODEV);
249 }
250 
251 u_int8_t
252 cy82c693_read_elcr(elcr)
253 	int elcr;
254 {
255 
256 	return (cy82c693_read(sio_cy82c693_handle, CONFIG_ELCR1 + elcr));
257 }
258 
259 void
260 cy82c693_write_elcr(elcr, val)
261 	int elcr;
262 	u_int8_t val;
263 {
264 
265 	cy82c693_write(sio_cy82c693_handle, CONFIG_ELCR1 + elcr, val);
266 }
267 
268 /******************** ELCR access function configuration ********************/
269 
270 /*
271  * Put the Intel SIO at the end, so we fall back on it if we don't
272  * find anything else.  If any of the non-Intel functions find a
273  * matching device, but are unable to map it for whatever reason,
274  * they should panic.
275  */
276 
277 int (*sio_elcr_setup_funcs[])(void) = {
278 	cy82c693_setup_elcr,
279 	i82378_setup_elcr,
280 	NULL,
281 };
282 
283 /******************** Shared SIO/Cypress functions ********************/
284 
285 void
286 sio_setirqstat(irq, enabled, type)
287 	int irq, enabled;
288 	int type;
289 {
290 	u_int8_t ocw1[2], elcr[2];
291 	int icu, bit;
292 
293 #if 0
294 	printf("sio_setirqstat: irq %d: %s, %s\n", irq,
295 	    enabled ? "enabled" : "disabled", isa_intr_typename(type));
296 #endif
297 
298 	icu = irq / 8;
299 	bit = irq % 8;
300 
301 	ocw1[0] = bus_space_read_1(sio_iot, sio_ioh_icu1, 1);
302 	ocw1[1] = bus_space_read_1(sio_iot, sio_ioh_icu2, 1);
303 	elcr[0] = (*sio_read_elcr)(0);				/* XXX */
304 	elcr[1] = (*sio_read_elcr)(1);				/* XXX */
305 
306 	/*
307 	 * interrupt enable: set bit to mask (disable) interrupt.
308 	 */
309 	if (enabled)
310 		ocw1[icu] &= ~(1 << bit);
311 	else
312 		ocw1[icu] |= 1 << bit;
313 
314 	/*
315 	 * interrupt type select: set bit to get level-triggered...
316 	 */
317 	if (type == IST_LEVEL)
318 		elcr[icu] |= 1 << bit;
319 	else
320 		elcr[icu] &= ~(1 << bit);
321 
322 	/*
323 	 * ...unless we pretend to know better.
324 	 */
325 	elcr[icu] &= ~elcr_override[icu];
326 
327 #ifdef not_here
328 	/* see the init function... */
329 	ocw1[0] &= ~0x04;		/* always enable IRQ2 on first PIC */
330 	elcr[0] &= ~0x07;		/* IRQ[0-2] must be edge-triggered */
331 	elcr[1] &= ~0x21;		/* IRQ[13,8] must be edge-triggered */
332 #endif
333 
334 	bus_space_write_1(sio_iot, sio_ioh_icu1, 1, ocw1[0]);
335 	bus_space_write_1(sio_iot, sio_ioh_icu2, 1, ocw1[1]);
336 	(*sio_write_elcr)(0, elcr[0]);				/* XXX */
337 	(*sio_write_elcr)(1, elcr[1]);				/* XXX */
338 }
339 
340 void
341 sio_intr_setup(pc, iot)
342 	pci_chipset_tag_t pc;
343 	bus_space_tag_t iot;
344 {
345 	int i;
346 
347 	sio_iot = iot;
348 	sio_pc = pc;
349 
350 	if (bus_space_map(sio_iot, IO_ICU1, 2, 0, &sio_ioh_icu1) ||
351 	    bus_space_map(sio_iot, IO_ICU2, 2, 0, &sio_ioh_icu2))
352 		panic("sio_intr_setup: can't map ICU I/O ports");
353 
354 	for (i = 0; sio_elcr_setup_funcs[i] != NULL; i++)
355 		if ((*sio_elcr_setup_funcs[i])() == 0)
356 			break;
357 	if (sio_elcr_setup_funcs[i] == NULL)
358 		panic("sio_intr_setup: can't map ELCR");
359 
360 #ifdef BROKEN_PROM_CONSOLE
361 	/*
362 	 * Remember the initial values, so we can restore them later.
363 	 */
364 	initial_ocw1[0] = bus_space_read_1(sio_iot, sio_ioh_icu1, 1);
365 	initial_ocw1[1] = bus_space_read_1(sio_iot, sio_ioh_icu2, 1);
366 	initial_elcr[0] = (*sio_read_elcr)(0);			/* XXX */
367 	initial_elcr[1] = (*sio_read_elcr)(1);			/* XXX */
368 #endif
369 
370 	sio_intr = alpha_shared_intr_alloc(ICU_LEN);
371 
372 	/*
373 	 * set up initial values for interrupt enables.
374 	 */
375 	for (i = 0; i < ICU_LEN; i++) {
376 		alpha_shared_intr_set_maxstrays(sio_intr, i, STRAY_MAX);
377 
378 		switch (i) {
379 		case 0:
380 		case 1:
381 		case 8:
382 		case 13:
383 			/*
384 			 * IRQs 0, 1, 8, and 13 must always be
385 			 * edge-triggered.
386 			 */
387 			sio_setirqstat(i, 0, IST_EDGE);
388 			alpha_shared_intr_set_dfltsharetype(sio_intr, i,
389 			    IST_EDGE);
390 			specific_eoi(i);
391 			break;
392 
393 		case 2:
394 			/*
395 			 * IRQ 2 must be edge-triggered, and should be
396 			 * enabled (otherwise IRQs 8-15 are ignored).
397 			 */
398 			sio_setirqstat(i, 1, IST_EDGE);
399 			alpha_shared_intr_set_dfltsharetype(sio_intr, i,
400 			    IST_UNUSABLE);
401 			break;
402 
403 		default:
404 			/*
405 			 * Otherwise, disable the IRQ and set its
406 			 * type to (effectively) "unknown."
407 			 */
408 			sio_setirqstat(i, 0, IST_NONE);
409 			alpha_shared_intr_set_dfltsharetype(sio_intr, i,
410 			    IST_NONE);
411 			specific_eoi(i);
412 			break;
413 		}
414 	}
415 }
416 
417 void
418 sio_intr_shutdown()
419 {
420 #ifdef BROKEN_PROM_CONSOLE
421 	if (sio_write_elcr == NULL)
422 		return;
423 
424 	/*
425 	 * Restore the initial values, to make the PROM happy.
426 	 */
427 	bus_space_write_1(sio_iot, sio_ioh_icu1, 1, initial_ocw1[0]);
428 	bus_space_write_1(sio_iot, sio_ioh_icu2, 1, initial_ocw1[1]);
429 	(*sio_write_elcr)(0, initial_elcr[0]);			/* XXX */
430 	(*sio_write_elcr)(1, initial_elcr[1]);			/* XXX */
431 #endif
432 }
433 
434 const char *
435 sio_intr_string(v, irq)
436 	void *v;
437 	int irq;
438 {
439 	static char irqstr[12];		/* 8 + 2 + NULL + sanity */
440 
441 	if (irq == 0 || irq >= ICU_LEN || irq == 2)
442 		panic("sio_intr_string: bogus isa irq 0x%x", irq);
443 
444 	snprintf(irqstr, sizeof irqstr, "isa irq %d", irq);
445 	return (irqstr);
446 }
447 
448 int
449 sio_intr_line(v, irq)
450 	void *v;
451 	int irq;
452 {
453 	return (irq);
454 }
455 
456 void *
457 sio_intr_establish(v, irq, type, level, fn, arg, name)
458 	void *v, *arg;
459         int irq;
460         int type;
461         int level;
462         int (*fn)(void *);
463 	const char *name;
464 {
465 	void *cookie;
466 
467 	if (irq >= ICU_LEN || type == IST_NONE)
468 		panic("sio_intr_establish: bogus irq or type");
469 
470 	cookie = alpha_shared_intr_establish(sio_intr, irq, type, level, fn,
471 	    arg, name);
472 
473 	if (cookie != NULL &&
474 	    alpha_shared_intr_firstactive(sio_intr, irq)) {
475 		scb_set(0x800 + SCB_IDXTOVEC(irq), sio_iointr, NULL);
476 		sio_setirqstat(irq, 1,
477 		    alpha_shared_intr_get_sharetype(sio_intr, irq));
478 	}
479 
480 	return (cookie);
481 }
482 
483 void
484 sio_intr_disestablish(v, cookie)
485 	void *v;
486 	void *cookie;
487 {
488 	struct alpha_shared_intrhand *ih = cookie;
489 	int s, ist, irq = ih->ih_num;
490 
491 	s = splhigh();
492 
493 	/* Remove it from the link. */
494 	alpha_shared_intr_disestablish(sio_intr, cookie);
495 
496 	/*
497 	 * Decide if we should disable the interrupt.  We must ensure
498 	 * that:
499 	 *
500 	 *	- An initially-enabled interrupt is never disabled.
501 	 *	- An initially-LT interrupt is never untyped.
502 	 */
503 	if (alpha_shared_intr_isactive(sio_intr, irq) == 0) {
504 		/*
505 		 * IRQs 0, 1, 8, and 13 must always be edge-triggered
506 		 * (see setup).
507 		 */
508 		switch (irq) {
509 		case 0:
510 		case 1:
511 		case 8:
512 		case 13:
513 			/*
514 			 * If the interrupt was initially level-triggered
515 			 * a warning was printed in setup.
516 			 */
517 			ist = IST_EDGE;
518 			break;
519 
520 		default:
521 			ist = IST_NONE;
522 			break;
523 		}
524 		sio_setirqstat(irq, 0, ist);
525 		alpha_shared_intr_set_dfltsharetype(sio_intr, irq, ist);
526 
527 		/* Release our SCB vector. */
528 		scb_free(0x800 + SCB_IDXTOVEC(irq));
529 	}
530 
531 	splx(s);
532 }
533 
534 void
535 sio_iointr(arg, vec)
536 	void *arg;
537 	unsigned long vec;
538 {
539 	int irq;
540 
541 	irq = SCB_VECTOIDX(vec - 0x800);
542 
543 #ifdef DIAGNOSTIC
544 	if (irq >= ICU_LEN || irq < 0)
545 		panic("sio_iointr: irq out of range (%d)", irq);
546 #endif
547 
548 	if (!alpha_shared_intr_dispatch(sio_intr, irq))
549 		alpha_shared_intr_stray(sio_intr, irq, "isa irq");
550 	else
551 		alpha_shared_intr_reset_strays(sio_intr, irq);
552 
553 	/*
554 	 * Some versions of the machines which use the SIO
555 	 * (or is it some PALcode revisions on those machines?)
556 	 * require the non-specific EOI to be fed to the PIC(s)
557 	 * by the interrupt handler.
558 	 */
559 	specific_eoi(irq);
560 }
561 
562 #define	LEGAL_IRQ(x)	((x) >= 0 && (x) < ICU_LEN && (x) != 2)
563 
564 int
565 sio_intr_alloc(v, mask, type, irq)
566 	void *v;
567 	int mask;
568 	int type;
569 	int *irq;
570 {
571 	int i, tmp, bestirq, count;
572 	struct alpha_shared_intrhand **p, *q;
573 
574 	if (type == IST_NONE)
575 		panic("intr_alloc: bogus type");
576 
577 	bestirq = -1;
578 	count = -1;
579 
580 	/* some interrupts should never be dynamically allocated */
581 	mask &= 0xffff;
582 	mask &= ~((1 << 13) | (1 << 8) | (1 << 2) | (1 << 1) | (1 << 0));
583 
584 	/*
585 	 * XXX some interrupts will be used later (6 for fdc, 12 for pms).
586 	 * the right answer is to do "breadth-first" searching of devices.
587 	 */
588 	mask &= ~((1 << 12) | (1 << 6));
589 
590 	for (i = 0; i < ICU_LEN; i++) {
591 		if (LEGAL_IRQ(i) == 0 || (mask & (1<<i)) == 0)
592 			continue;
593 
594 		switch (sio_intr[i].intr_sharetype) {
595 		case IST_NONE:
596 			/*
597 			 * if nothing's using the irq, just return it
598 			 */
599 			*irq = i;
600 			return (0);
601 
602 		case IST_EDGE:
603 			intr_shared_edge = 1;
604 			/* FALLTHROUGH */
605 		case IST_LEVEL:
606 			if (type != sio_intr[i].intr_sharetype)
607 				continue;
608 			/*
609 			 * if the irq is shareable, count the number of other
610 			 * handlers, and if it's smaller than the last irq like
611 			 * this, remember it
612 			 *
613 			 * XXX We should probably also consider the
614 			 * interrupt level and stick IPL_TTY with other
615 			 * IPL_TTY, etc.
616 			 */
617 			for (p = &TAILQ_FIRST(&sio_intr[i].intr_q), tmp = 0;
618 			     (q = *p) != NULL; p = &TAILQ_NEXT(q, ih_q), tmp++)
619 				;
620 			if ((bestirq == -1) || (count > tmp)) {
621 				bestirq = i;
622 				count = tmp;
623 			}
624 			break;
625 
626 		case IST_PULSE:
627 			/* this just isn't shareable */
628 			continue;
629 		}
630 	}
631 
632 	if (bestirq == -1)
633 		return (1);
634 
635 	*irq = bestirq;
636 
637 	return (0);
638 }
639 
640 /*
641  * Just check to see if an IRQ is available/can be shared.
642  * 0 = interrupt not available
643  * 1 = interrupt shareable
644  * 2 = interrupt all to ourself
645  */
646 int
647 sio_intr_check(void *v, int irq, int type)
648 {
649 	if (type == IST_NONE)
650 		return (0);
651 
652 	switch (sio_intr[irq].intr_sharetype) {
653 	case IST_NONE:
654 		return (2);
655 	case IST_EDGE:
656 	case IST_LEVEL:
657 		if (type == sio_intr[irq].intr_sharetype)
658 			return (1);
659 		/* FALLTHROUGH */
660 	default:
661 	case IST_PULSE:
662 		return (0);
663 	}
664 }
665 
666 static void
667 specific_eoi(irq)
668 	int irq;
669 {
670 	if (irq > 7) {
671 		bus_space_write_1(sio_iot,
672 		    sio_ioh_icu2, 0, 0x60 | (irq & 0x07));	/* XXX */
673 		irq = 2;
674 	}
675 	bus_space_write_1(sio_iot, sio_ioh_icu1, 0, 0x60 | irq);
676 }
677