xref: /openbsd/sys/arch/alpha/pci/pci_1000.c (revision b27348b2)
1 /* $OpenBSD: pci_1000.c,v 1.12 2017/09/08 05:36:51 deraadt Exp $ */
2 /* $NetBSD: pci_1000.c,v 1.12 2001/07/27 00:25:20 thorpej Exp $ */
3 
4 /*
5  * Copyright (c) 1998 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is based on pci_kn20aa.c, written by Chris G. Demetriou at
9  * Carnegie-Mellon University. Platform support for Mikasa and Mikasa/Pinnacle
10  * (Pinkasa) by Ross Harvey with copyright assignment by permission of Avalon
11  * Computer Systems, Inc.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 /*
36  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
37  * All rights reserved.
38  *
39  * Author: Chris G. Demetriou
40  *
41  * Permission to use, copy, modify and distribute this software and
42  * its documentation is hereby granted, provided that both the copyright
43  * notice and this permission notice appear in all copies of the
44  * software, derivative works or modified versions, and any portions
45  * thereof, and that both notices appear in supporting documentation.
46  *
47  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
48  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
49  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
50  *
51  * Carnegie Mellon requests users of this software to return to
52  *
53  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
54  *  School of Computer Science
55  *  Carnegie Mellon University
56  *  Pittsburgh PA 15213-3890
57  *
58  * any improvements or extensions that they make and grant Carnegie the
59  * rights to redistribute these changes.
60  */
61 
62 #include <sys/param.h>
63 #include <sys/time.h>
64 #include <sys/systm.h>
65 #include <sys/errno.h>
66 #include <sys/malloc.h>
67 #include <sys/device.h>
68 
69 #include <uvm/uvm_extern.h>
70 
71 #include <machine/autoconf.h>
72 
73 #include <dev/pci/pcireg.h>
74 #include <dev/pci/pcivar.h>
75 #include <dev/pci/ppbreg.h>
76 
77 #include <alpha/pci/pci_1000.h>
78 
79 #include "sio.h"
80 #if NSIO > 0 || NPCEB > 0
81 #include <alpha/pci/siovar.h>
82 #endif
83 
84 static bus_space_tag_t another_mystery_icu_iot;
85 static bus_space_handle_t another_mystery_icu_ioh;
86 
87 int	dec_1000_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
88 const char *dec_1000_intr_string(void *, pci_intr_handle_t);
89 int	dec_1000_intr_line(void *, pci_intr_handle_t);
90 void	*dec_1000_intr_establish(void *, pci_intr_handle_t,
91 	    int, int (*func)(void *), void *, const char *);
92 void	dec_1000_intr_disestablish(void *, void *);
93 
94 #define	PCI_NIRQ	16
95 #define	PCI_STRAY_MAX	5
96 
97 struct alpha_shared_intr *dec_1000_pci_intr;
98 
99 void dec_1000_iointr(void *arg, unsigned long vec);
100 void dec_1000_enable_intr(int irq);
101 void dec_1000_disable_intr(int irq);
102 void pci_1000_imi(void);
103 
104 void
pci_1000_pickintr(core,iot,memt,pc)105 pci_1000_pickintr(core, iot, memt, pc)
106 	void *core;
107 	bus_space_tag_t iot, memt;
108 	pci_chipset_tag_t pc;
109 {
110 	int i;
111 
112 	another_mystery_icu_iot = iot;
113 
114 	if (bus_space_map(iot, 0x536, 2, 0, &another_mystery_icu_ioh))
115 		panic("pci_1000_pickintr");
116         pc->pc_intr_v = core;
117         pc->pc_intr_map = dec_1000_intr_map;
118         pc->pc_intr_string = dec_1000_intr_string;
119 	pc->pc_intr_line = dec_1000_intr_line;
120         pc->pc_intr_establish = dec_1000_intr_establish;
121         pc->pc_intr_disestablish = dec_1000_intr_disestablish;
122 
123 	pc->pc_pciide_compat_intr_establish = NULL;
124 	pc->pc_pciide_compat_intr_disestablish = NULL;
125 
126 	dec_1000_pci_intr =
127 	    alpha_shared_intr_alloc(PCI_NIRQ);
128 	for (i = 0; i < PCI_NIRQ; i++) {
129 		alpha_shared_intr_set_maxstrays(dec_1000_pci_intr, i,
130 		    PCI_STRAY_MAX);
131 	}
132 
133 	pci_1000_imi();
134 #if NSIO > 0 || NPCEB > 0
135 	sio_intr_setup(pc, iot);
136 #endif
137 }
138 
139 int
dec_1000_intr_map(pa,ihp)140 dec_1000_intr_map(pa, ihp)
141 	struct pci_attach_args *pa;
142         pci_intr_handle_t *ihp;
143 {
144 	pcitag_t bustag = pa->pa_intrtag;
145 	int buspin, device, line = pa->pa_intrline;
146 
147 	/*
148 	 * The console places the interrupt mapping in the "line" value.
149 	 * We trust it whenever possible.
150 	 */
151 	if (line >= 0 && line < PCI_NIRQ) {
152 		*ihp = line;
153 		return 0;
154 	}
155 
156 	if (pa->pa_bridgetag) {
157 		buspin = PPB_INTERRUPT_SWIZZLE(pa->pa_rawintrpin,
158 		    pa->pa_device);
159 		if (pa->pa_bridgeih[buspin - 1] == 0)
160 			return 1;
161 
162 		*ihp = pa->pa_bridgeih[buspin - 1];
163 		return 0;
164 	}
165 
166 	buspin = pa->pa_intrpin;
167 	pci_decompose_tag(pa->pa_pc, bustag, NULL, &device, NULL);
168 
169 	switch (device) {
170 	case 6:
171 		if (buspin != 1)
172 			break;
173 		*ihp = 0xc;		/* integrated ncr scsi */
174 		return 0;
175 	case 11:
176 	case 12:
177 	case 13:
178 		*ihp = (device - 11) * 4 + buspin - 1;
179 		return 0;
180 	}
181 
182 	return 1;
183 }
184 
185 const char *
dec_1000_intr_string(ccv,ih)186 dec_1000_intr_string(ccv, ih)
187 	void *ccv;
188 	pci_intr_handle_t ih;
189 {
190 	static const char irqmsg_fmt[] = "dec_1000 irq %ld";
191         static char irqstr[sizeof irqmsg_fmt];
192 
193         if (ih >= PCI_NIRQ)
194                 panic("dec_1000_intr_string: bogus dec_1000 IRQ 0x%lx", ih);
195 
196         snprintf(irqstr, sizeof irqstr, irqmsg_fmt, ih);
197         return (irqstr);
198 }
199 
200 int
dec_1000_intr_line(ccv,ih)201 dec_1000_intr_line(ccv, ih)
202 	void *ccv;
203 	pci_intr_handle_t ih;
204 {
205 #if NSIO > 0
206 	return sio_intr_line(NULL /*XXX*/, ih);
207 #else
208 	return (ih);
209 #endif
210 }
211 
212 void *
dec_1000_intr_establish(ccv,ih,level,func,arg,name)213 dec_1000_intr_establish(ccv, ih, level, func, arg, name)
214         void *ccv;
215         pci_intr_handle_t ih;
216         int level;
217         int (*func)(void *);
218 	void *arg;
219 	const char *name;
220 {
221 	void *cookie;
222 
223         if (ih >= PCI_NIRQ)
224                 panic("dec_1000_intr_establish: IRQ too high, 0x%lx", ih);
225 
226 	cookie = alpha_shared_intr_establish(dec_1000_pci_intr, ih, IST_LEVEL,
227 	    level, func, arg, name);
228 
229 	if (cookie != NULL &&
230 	    alpha_shared_intr_firstactive(dec_1000_pci_intr, ih)) {
231 		scb_set(0x900 + SCB_IDXTOVEC(ih), dec_1000_iointr, NULL);
232 		dec_1000_enable_intr(ih);
233 	}
234 	return (cookie);
235 }
236 
237 void
dec_1000_intr_disestablish(ccv,cookie)238 dec_1000_intr_disestablish(ccv, cookie)
239         void *ccv, *cookie;
240 {
241 	struct alpha_shared_intrhand *ih = cookie;
242 	unsigned int irq = ih->ih_num;
243 	int s;
244 
245 	s = splhigh();
246 
247 	alpha_shared_intr_disestablish(dec_1000_pci_intr, cookie);
248 	if (alpha_shared_intr_isactive(dec_1000_pci_intr, irq) == 0) {
249 		dec_1000_disable_intr(irq);
250 		alpha_shared_intr_set_dfltsharetype(dec_1000_pci_intr, irq,
251 		    IST_NONE);
252 		scb_free(0x900 + SCB_IDXTOVEC(irq));
253 	}
254 
255 	splx(s);
256 }
257 
258 void
dec_1000_iointr(arg,vec)259 dec_1000_iointr(arg, vec)
260 	void *arg;
261 	unsigned long vec;
262 {
263 	int irq;
264 
265 	irq = SCB_VECTOIDX(vec - 0x900);
266 
267 	if (!alpha_shared_intr_dispatch(dec_1000_pci_intr, irq)) {
268 		alpha_shared_intr_stray(dec_1000_pci_intr, irq,
269 		    "dec_1000 irq");
270 		if (ALPHA_SHARED_INTR_DISABLE(dec_1000_pci_intr, irq))
271 			dec_1000_disable_intr(irq);
272 	} else
273 		alpha_shared_intr_reset_strays(dec_1000_pci_intr, irq);
274 }
275 
276 /*
277  * Read and write the mystery ICU IMR registers
278  */
279 
280 #define	IR() bus_space_read_2(another_mystery_icu_iot,		\
281 				another_mystery_icu_ioh, 0)
282 
283 #define	IW(v) bus_space_write_2(another_mystery_icu_iot,	\
284 				another_mystery_icu_ioh, 0, (v))
285 
286 /*
287  * Enable and disable interrupts at the ICU level
288  */
289 
290 void
dec_1000_enable_intr(irq)291 dec_1000_enable_intr(irq)
292 	int irq;
293 {
294 	IW(IR() | 1 << irq);
295 }
296 
297 void
dec_1000_disable_intr(irq)298 dec_1000_disable_intr(irq)
299 	int irq;
300 {
301 	IW(IR() & ~(1 << irq));
302 }
303 /*
304  * Initialize mystery ICU
305  */
306 void
pci_1000_imi()307 pci_1000_imi()
308 {
309 	IW(0);					/* XXX ?? */
310 }
311