1 /* $NetBSD: pci_kn300.c,v 1.43 2021/07/04 22:42:36 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1998 by Matthew Jacob
5 * NASA AMES Research Center.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice immediately at the beginning of the file, without modification,
13 * this list of conditions, and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
34
35 __KERNEL_RCSID(0, "$NetBSD: pci_kn300.c,v 1.43 2021/07/04 22:42:36 thorpej Exp $");
36
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <sys/time.h>
40 #include <sys/systm.h>
41 #include <sys/errno.h>
42 #include <sys/device.h>
43 #include <sys/cpu.h>
44 #include <sys/syslog.h>
45
46 #include <machine/autoconf.h>
47 #include <machine/rpb.h>
48
49 #include <dev/pci/pcireg.h>
50 #include <dev/pci/pcivar.h>
51
52 #include <alpha/mcbus/mcbusvar.h>
53 #include <alpha/mcbus/mcbusreg.h>
54 #include <alpha/pci/mcpciareg.h>
55 #include <alpha/pci/mcpciavar.h>
56
57 #include "sio.h"
58 #if NSIO > 0 || NPCEB > 0
59 #include <alpha/pci/siovar.h>
60 #endif
61
62 static int dec_kn300_intr_map(const struct pci_attach_args *,
63 pci_intr_handle_t *);
64 static const char *dec_kn300_intr_string(pci_chipset_tag_t, pci_intr_handle_t,
65 char *, size_t);
66 static const struct evcnt *dec_kn300_intr_evcnt(pci_chipset_tag_t,
67 pci_intr_handle_t);
68 static void *dec_kn300_intr_establish(pci_chipset_tag_t,
69 pci_intr_handle_t, int, int (*func)(void *), void *);
70 static void dec_kn300_intr_disestablish(pci_chipset_tag_t, void *);
71
72 #define KN300_PCEB_IRQ 16
73 #define KN300_STRAY_MAX 25
74 #define NPIN 4
75
76 #define NIRQ (MAX_MC_BUS * MCPCIA_PER_MCBUS * MCPCIA_MAXSLOT * NPIN)
77 static int savirqs[NIRQ];
78
79 static struct alpha_shared_intr *kn300_pci_intr;
80
81 static struct mcpcia_config *mcpcia_eisaccp = NULL;
82
83 static void kn300_iointr(void *, unsigned long);
84 static void kn300_enable_intr(struct mcpcia_config *, int);
85 static void kn300_disable_intr(struct mcpcia_config *, int);
86
87 static void
pci_kn300_pickintr(void * core,bus_space_tag_t iot,bus_space_tag_t memt,pci_chipset_tag_t pc)88 pci_kn300_pickintr(void *core, bus_space_tag_t iot, bus_space_tag_t memt,
89 pci_chipset_tag_t pc)
90 {
91 struct mcpcia_config *ccp = core;
92 struct evcnt *ev;
93 const char *cp;
94
95 if (kn300_pci_intr == NULL) {
96 int g;
97
98 kn300_pci_intr = alpha_shared_intr_alloc(NIRQ);
99 for (g = 0; g < NIRQ; g++) {
100 alpha_shared_intr_set_maxstrays(kn300_pci_intr, g,
101 KN300_STRAY_MAX);
102
103 ev = alpha_shared_intr_evcnt(kn300_pci_intr, g);
104 cp = alpha_shared_intr_string(kn300_pci_intr, g);
105
106 evcnt_attach_dynamic(ev, EVCNT_TYPE_INTR, NULL,
107 "kn300", cp);
108
109 savirqs[g] = (char) -1;
110 }
111 }
112
113 pc->pc_intr_v = core;
114 pc->pc_intr_map = dec_kn300_intr_map;
115 pc->pc_intr_string = dec_kn300_intr_string;
116 pc->pc_intr_evcnt = dec_kn300_intr_evcnt;
117 pc->pc_intr_establish = dec_kn300_intr_establish;
118 pc->pc_intr_disestablish = dec_kn300_intr_disestablish;
119
120 /* Not supported on KN300. */
121 pc->pc_pciide_compat_intr_establish = NULL;
122
123 if (EISA_PRESENT(REGVAL(MCPCIA_PCI_REV(ccp)))) {
124 mcpcia_eisaccp = ccp;
125 #if NSIO > 0 || NPCEB > 0
126 sio_intr_setup(pc, &ccp->cc_iot);
127 kn300_enable_intr(ccp, KN300_PCEB_IRQ);
128 #endif
129 }
130 }
ALPHA_PCI_INTR_INIT(ST_DEC_4100,pci_kn300_pickintr)131 ALPHA_PCI_INTR_INIT(ST_DEC_4100, pci_kn300_pickintr)
132
133 static int
134 dec_kn300_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp)
135 {
136 pcitag_t bustag = pa->pa_intrtag;
137 int buspin = pa->pa_intrpin;
138 pci_chipset_tag_t pc = pa->pa_pc;
139 struct mcpcia_config *ccp = (struct mcpcia_config *)pc->pc_intr_v;
140 int device;
141 int mcpcia_irq;
142
143 if (buspin == 0) {
144 /* No IRQ used. */
145 return 1;
146 }
147 if (buspin < 0 || buspin > 4) {
148 printf("dec_kn300_intr_map: bad interrupt pin %d\n", buspin);
149 return 1;
150 }
151
152 pci_decompose_tag(pc, bustag, NULL, &device, NULL);
153
154 /*
155 * On MID 5 device 1 is the internal NCR 53c810.
156 */
157 if (ccp->cc_mid == 5 && device == 1) {
158 mcpcia_irq = 16;
159 } else if (device >= 2 && device <= 5) {
160 mcpcia_irq = (device - 2) * 4 + buspin - 1;
161 } else {
162 printf("dec_kn300_intr_map: weird device number %d\n", device);
163 return(1);
164 }
165
166 /*
167 * handle layout:
168 *
169 * Determine kn300 IRQ (encoded in SCB vector):
170 * bits 0..1 buspin-1
171 * bits 2..4 PCI Slot (0..7- yes, some don't exist)
172 * bits 5..7 MID-4
173 * bits 8..10 7-GID
174 *
175 * Software only:
176 * bits 11-15 MCPCIA IRQ
177 */
178 const u_int irq =
179 (buspin - 1 ) |
180 ((device & 0x7) << 2) |
181 ((ccp->cc_mid - 4) << 5) |
182 ((7 - ccp->cc_gid) << 8) |
183 (mcpcia_irq << 11);
184 alpha_pci_intr_handle_init(ihp, irq, 0);
185 return (0);
186 }
187
188 static const char *
dec_kn300_intr_string(pci_chipset_tag_t const pc __unused,pci_intr_handle_t const ih,char * const buf,size_t const len)189 dec_kn300_intr_string(pci_chipset_tag_t const pc __unused,
190 pci_intr_handle_t const ih, char * const buf, size_t const len)
191 {
192 const u_int irq = alpha_pci_intr_handle_get_irq(&ih) & 0x3ff;
193
194 snprintf(buf, len, "kn300 irq %u", irq);
195 return buf;
196 }
197
198 static const struct evcnt *
dec_kn300_intr_evcnt(pci_chipset_tag_t const pc __unused,pci_intr_handle_t const ih)199 dec_kn300_intr_evcnt(pci_chipset_tag_t const pc __unused,
200 pci_intr_handle_t const ih)
201 {
202 const u_int irq = alpha_pci_intr_handle_get_irq(&ih) & 0x3ff;
203
204 return alpha_shared_intr_evcnt(kn300_pci_intr, irq);
205 }
206
207 static void *
dec_kn300_intr_establish(pci_chipset_tag_t const pc,pci_intr_handle_t const ih,int const level,int (* func)(void *),void * arg)208 dec_kn300_intr_establish(
209 pci_chipset_tag_t const pc,
210 pci_intr_handle_t const ih,
211 int const level,
212 int (*func)(void *),
213 void *arg)
214 {
215 struct mcpcia_config * const ccp = pc->pc_intr_v;
216 void *cookie;
217 const u_int ihv = alpha_pci_intr_handle_get_irq(&ih);
218 const u_int irq = ihv & 0x3ff;
219 const u_int flags = alpha_pci_intr_handle_get_flags(&ih);
220
221 cookie = alpha_shared_intr_alloc_intrhand(kn300_pci_intr, irq,
222 IST_LEVEL, level, flags, func, arg, "kn300");
223
224 if (cookie == NULL)
225 return NULL;
226
227 mutex_enter(&cpu_lock);
228
229 if (! alpha_shared_intr_link(kn300_pci_intr, cookie, "kn300")) {
230 mutex_exit(&cpu_lock);
231 alpha_shared_intr_free_intrhand(cookie);
232 return NULL;
233 }
234
235 if (alpha_shared_intr_firstactive(kn300_pci_intr, irq)) {
236 scb_set(MCPCIA_VEC_PCI + SCB_IDXTOVEC(irq), kn300_iointr, NULL);
237 alpha_shared_intr_set_private(kn300_pci_intr, irq, ccp);
238 savirqs[irq] = (ihv >> 11) & 0x1f;
239 alpha_mb();
240 kn300_enable_intr(ccp, savirqs[irq]);
241 }
242
243 mutex_exit(&cpu_lock);
244
245 return cookie;
246 }
247
248 static void
dec_kn300_intr_disestablish(pci_chipset_tag_t const pc __unused,void * const cookie __unused)249 dec_kn300_intr_disestablish(pci_chipset_tag_t const pc __unused,
250 void * const cookie __unused)
251 {
252 panic("dec_kn300_intr_disestablish not implemented");
253 }
254
255 static void
kn300_iointr(void * const arg __unused,unsigned long const vec)256 kn300_iointr(void * const arg __unused, unsigned long const vec)
257 {
258 struct mcpcia_softc *mcp;
259 u_long irq;
260
261 irq = SCB_VECTOIDX(vec - MCPCIA_VEC_PCI);
262
263 if (alpha_shared_intr_dispatch(kn300_pci_intr, irq)) {
264 /*
265 * Any claim of an interrupt at this level is a hint to
266 * reset the stray interrupt count- elsewise a slow leak
267 * over time will cause this level to be shutdown.
268 */
269 alpha_shared_intr_reset_strays(kn300_pci_intr, irq);
270 return;
271 }
272
273 /*
274 * If we haven't finished configuring yet, or there is no mcp
275 * registered for this level yet, just return.
276 */
277 mcp = alpha_shared_intr_get_private(kn300_pci_intr, irq);
278 if (mcp == NULL || mcp->mcpcia_cc == NULL)
279 return;
280
281 /*
282 * We're getting an interrupt for a device we haven't enabled.
283 * We had better not try and use -1 to find the right bit to disable.
284 */
285 if (savirqs[irq] == -1) {
286 printf("kn300_iointr: stray interrupt vector 0x%lx\n", vec);
287 return;
288 }
289
290 /*
291 * Stray interrupt; disable the IRQ on the appropriate MCPCIA
292 * if we've reached the limit.
293 */
294 alpha_shared_intr_stray(kn300_pci_intr, irq, "kn300");
295 if (ALPHA_SHARED_INTR_DISABLE(kn300_pci_intr, irq) == 0)
296 return;
297 kn300_disable_intr(mcp->mcpcia_cc, savirqs[irq]);
298 }
299
300 static void
kn300_enable_intr(struct mcpcia_config * const ccp,int const irq)301 kn300_enable_intr(struct mcpcia_config * const ccp, int const irq)
302 {
303 alpha_mb();
304 REGVAL(MCPCIA_INT_MASK0(ccp)) |= (1 << irq);
305 alpha_mb();
306 }
307
308 static void
kn300_disable_intr(struct mcpcia_config * const ccp,int const irq)309 kn300_disable_intr(struct mcpcia_config * const ccp, int const irq)
310 {
311 alpha_mb();
312 REGVAL(MCPCIA_INT_MASK0(ccp)) &= ~(1 << irq);
313 alpha_mb();
314 }
315