xref: /netbsd-src/sys/arch/alpha/pci/pci_kn20aa.c (revision b13f63840eeeaed6c9aab95a9f055101875df377)
1 /* $NetBSD: pci_kn20aa.c,v 1.59 2021/07/04 22:42:36 thorpej 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@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/cdefs.h>			/* RCS ID & Copyright macro defns */
31 
32 __KERNEL_RCSID(0, "$NetBSD: pci_kn20aa.c,v 1.59 2021/07/04 22:42:36 thorpej Exp $");
33 
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/time.h>
37 #include <sys/systm.h>
38 #include <sys/errno.h>
39 #include <sys/device.h>
40 #include <sys/syslog.h>
41 
42 #include <machine/autoconf.h>
43 #include <machine/rpb.h>
44 
45 #include <dev/pci/pcireg.h>
46 #include <dev/pci/pcivar.h>
47 
48 #include <alpha/pci/ciareg.h>
49 #include <alpha/pci/ciavar.h>
50 
51 #include "sio.h"
52 #if NSIO > 0 || NPCEB > 0
53 #include <alpha/pci/siovar.h>
54 #endif
55 
56 static int	dec_kn20aa_intr_map(const struct pci_attach_args *,
57 		    pci_intr_handle_t *);
58 
59 #define	KN20AA_PCEB_IRQ	31
60 #define	KN20AA_MAX_IRQ	32
61 #define	PCI_STRAY_MAX	5
62 
63 static void	kn20aa_enable_intr(pci_chipset_tag_t pc, int irq);
64 static void	kn20aa_disable_intr(pci_chipset_tag_t pc, int irq);
65 
66 static void
pci_kn20aa_pickintr(void * core,bus_space_tag_t iot,bus_space_tag_t memt,pci_chipset_tag_t pc)67 pci_kn20aa_pickintr(void *core, bus_space_tag_t iot, bus_space_tag_t memt,
68     pci_chipset_tag_t pc)
69 {
70 	int i;
71 
72 	pc->pc_intr_v = core;
73 	pc->pc_intr_map = dec_kn20aa_intr_map;
74 	pc->pc_intr_string = alpha_pci_generic_intr_string;
75 	pc->pc_intr_evcnt = alpha_pci_generic_intr_evcnt;
76 	pc->pc_intr_establish = alpha_pci_generic_intr_establish;
77 	pc->pc_intr_disestablish = alpha_pci_generic_intr_disestablish;
78 
79 	/* Not supported on KN20AA. */
80 	pc->pc_pciide_compat_intr_establish = NULL;
81 
82 	pc->pc_intr_desc = "kn20aa";
83 	pc->pc_vecbase = 0x900;
84 	pc->pc_nirq = KN20AA_MAX_IRQ;
85 
86 	pc->pc_intr_enable = kn20aa_enable_intr;
87 	pc->pc_intr_disable = kn20aa_disable_intr;
88 
89 	for (i = 0; i < KN20AA_MAX_IRQ; i++) {
90 		kn20aa_disable_intr(pc, i);
91 	}
92 
93 	alpha_pci_intr_alloc(pc, PCI_STRAY_MAX);
94 
95 #if NSIO > 0 || NPCEB > 0
96 	sio_intr_setup(pc, iot);
97 	kn20aa_enable_intr(pc, KN20AA_PCEB_IRQ);
98 #endif
99 }
ALPHA_PCI_INTR_INIT(ST_DEC_KN20AA,pci_kn20aa_pickintr)100 ALPHA_PCI_INTR_INIT(ST_DEC_KN20AA, pci_kn20aa_pickintr)
101 
102 static int
103 dec_kn20aa_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp)
104 {
105 	pcitag_t bustag = pa->pa_intrtag;
106 	int buspin = pa->pa_intrpin;
107 	pci_chipset_tag_t pc = pa->pa_pc;
108 	int device;
109 	int kn20aa_irq;
110 
111 	if (buspin == 0) {
112 		/* No IRQ used. */
113 		return 1;
114 	}
115 	if (buspin < 0 || buspin > 4) {
116 		printf("dec_kn20aa_intr_map: bad interrupt pin %d\n", buspin);
117 		return 1;
118 	}
119 
120 	/*
121 	 * Slot->interrupt translation.  Appears to work, though it
122 	 * may not hold up forever.
123 	 *
124 	 * The DEC engineers who did this hardware obviously engaged
125 	 * in random drug testing.
126 	 */
127 	pci_decompose_tag(pc, bustag, NULL, &device, NULL);
128 	switch (device) {
129 	case 11:
130 	case 12:
131 		kn20aa_irq = ((device - 11) + 0) * 4;
132 		break;
133 
134 	case 7:
135 		kn20aa_irq = 8;
136 		break;
137 
138 	case 9:
139 		kn20aa_irq = 12;
140 		break;
141 
142 	case 6:					/* 21040 on AlphaStation 500 */
143 		kn20aa_irq = 13;
144 		break;
145 
146 	case 8:
147 		kn20aa_irq = 16;
148 		break;
149 
150 	default:
151 	        printf("dec_kn20aa_intr_map: weird device number %d\n",
152 		    device);
153 	        return 1;
154 	}
155 
156 	kn20aa_irq += buspin - 1;
157 	if (kn20aa_irq > KN20AA_MAX_IRQ)
158 		panic("dec_kn20aa_intr_map: kn20aa_irq too large (%d)",
159 		    kn20aa_irq);
160 
161 	alpha_pci_intr_handle_init(ihp, kn20aa_irq, 0);
162 	return (0);
163 }
164 
165 static void
kn20aa_enable_intr(pci_chipset_tag_t pc __unused,int irq)166 kn20aa_enable_intr(pci_chipset_tag_t pc __unused, int irq)
167 {
168 
169 	/*
170 	 * From disassembling small bits of the OSF/1 kernel:
171 	 * the following appears to enable a given interrupt request.
172 	 * "blech."  I'd give valuable body parts for better docs or
173 	 * for a good decompiler.
174 	 */
175 	alpha_mb();
176 	REGVAL(0x8780000000L + 0x40L) |= (1 << irq);	/* XXX */
177 	alpha_mb();
178 }
179 
180 static void
kn20aa_disable_intr(pci_chipset_tag_t pc __unused,int irq)181 kn20aa_disable_intr(pci_chipset_tag_t pc __unused, int irq)
182 {
183 
184 	alpha_mb();
185 	REGVAL(0x8780000000L + 0x40L) &= ~(1 << irq);	/* XXX */
186 	alpha_mb();
187 }
188