pci_1000.c revision 1.1
1/* $OpenBSD: pci_1000.c,v 1.1 2002/06/30 16:24:40 miod 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 * 3. All advertising materials mentioning features or use of this software
22 *    must display the following acknowledgement:
23 *	This product includes software developed by the NetBSD
24 *	Foundation, Inc. and its contributors.
25 * 4. Neither the name of The NetBSD Foundation nor the names of its
26 *    contributors may be used to endorse or promote products derived
27 *    from this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
30 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
31 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
33 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 * POSSIBILITY OF SUCH DAMAGE.
40 */
41
42/*
43 * Copyright (c) 1995, 1996 Carnegie-Mellon University.
44 * All rights reserved.
45 *
46 * Author: Chris G. Demetriou
47 *
48 * Permission to use, copy, modify and distribute this software and
49 * its documentation is hereby granted, provided that both the copyright
50 * notice and this permission notice appear in all copies of the
51 * software, derivative works or modified versions, and any portions
52 * thereof, and that both notices appear in supporting documentation.
53 *
54 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
55 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
56 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
57 *
58 * Carnegie Mellon requests users of this software to return to
59 *
60 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
61 *  School of Computer Science
62 *  Carnegie Mellon University
63 *  Pittsburgh PA 15213-3890
64 *
65 * any improvements or extensions that they make and grant Carnegie the
66 * rights to redistribute these changes.
67 */
68
69#include <sys/types.h>
70#include <sys/param.h>
71#include <sys/time.h>
72#include <sys/systm.h>
73#include <sys/errno.h>
74#include <sys/malloc.h>
75#include <sys/device.h>
76
77#include <uvm/uvm_extern.h>
78
79#include <machine/autoconf.h>
80
81#include <dev/pci/pcireg.h>
82#include <dev/pci/pcivar.h>
83
84#include <alpha/pci/pci_1000.h>
85
86#include "sio.h"
87#if NSIO > 0 || NPCEB > 0
88#include <alpha/pci/siovar.h>
89#endif
90
91static bus_space_tag_t another_mystery_icu_iot;
92static bus_space_handle_t another_mystery_icu_ioh;
93
94int	dec_1000_intr_map(void *, pcitag_t, int, int, pci_intr_handle_t *);
95const char *dec_1000_intr_string(void *, pci_intr_handle_t);
96int	dec_1000_intr_line(void *, pci_intr_handle_t);
97#if 0
98const struct evcnt *dec_1000_intr_evcnt(void *, pci_intr_handle_t);
99#endif
100void	*dec_1000_intr_establish(void *, pci_intr_handle_t,
101	    int, int (*func)(void *), void *, char *);
102void	dec_1000_intr_disestablish(void *, void *);
103
104#define	PCI_NIRQ	16
105#define	PCI_STRAY_MAX	5
106
107struct alpha_shared_intr *dec_1000_pci_intr;
108
109void dec_1000_iointr(void *framep, unsigned long vec);
110void dec_1000_enable_intr(int irq);
111void dec_1000_disable_intr(int irq);
112void pci_1000_imi(void);
113static pci_chipset_tag_t pc_tag;
114
115void
116pci_1000_pickintr(core, iot, memt, pc)
117	void *core;
118	bus_space_tag_t iot, memt;
119	pci_chipset_tag_t pc;
120{
121#if 0
122	char *cp;
123#endif
124	int i;
125
126	another_mystery_icu_iot = iot;
127
128	pc_tag = pc;
129	if (bus_space_map(iot, 0x536, 2, 0, &another_mystery_icu_ioh))
130		panic("pci_1000_pickintr");
131        pc->pc_intr_v = core;
132        pc->pc_intr_map = dec_1000_intr_map;
133        pc->pc_intr_string = dec_1000_intr_string;
134	pc->pc_intr_line = dec_1000_intr_line;
135#if 0
136	pc->pc_intr_evcnt = dec_1000_intr_evcnt;
137#endif
138        pc->pc_intr_establish = dec_1000_intr_establish;
139        pc->pc_intr_disestablish = dec_1000_intr_disestablish;
140
141	pc->pc_pciide_compat_intr_establish = NULL;
142	pc->pc_pciide_compat_intr_disestablish = NULL;
143
144	dec_1000_pci_intr =
145	    alpha_shared_intr_alloc(PCI_NIRQ);
146	for (i = 0; i < PCI_NIRQ; i++) {
147		alpha_shared_intr_set_maxstrays(dec_1000_pci_intr, i,
148		    PCI_STRAY_MAX);
149
150#if 0
151		cp = alpha_shared_intr_string(dec_1000_pci_intr, i);
152		sprintf(cp, "irq %d", i);
153		evcnt_attach_dynamic(alpha_shared_intr_evcnt(
154		    dec_1000_pci_intr, i), EVCNT_TYPE_INTR, NULL,
155		    "dec_1000", cp);
156#endif
157	}
158
159	pci_1000_imi();
160#if NSIO > 0 || NPCEB > 0
161	sio_intr_setup(pc, iot);
162#endif
163	set_iointr(dec_1000_iointr);
164}
165
166int
167dec_1000_intr_map(ccv, bustag, buspin, line, ihp)
168	void *ccv;
169	pcitag_t bustag;
170	int buspin, line;
171        pci_intr_handle_t *ihp;
172{
173	int	device;
174
175	if (buspin == 0)	/* No IRQ used. */
176		return 1;
177	if (!(1 <= buspin && buspin <= 4))
178		goto bad;
179
180	alpha_pci_decompose_tag(pc_tag, bustag, NULL, &device, NULL);
181
182	switch(device) {
183	case 6:
184		if(buspin != 1)
185			break;
186		*ihp = 0xc;		/* integrated ncr scsi */
187		return 0;
188	case 11:
189	case 12:
190	case 13:
191		*ihp = (device - 11) * 4 + buspin - 1;
192		return 0;
193	}
194
195bad:	printf("dec_1000_intr_map: can't map dev %d pin %d\n", device, buspin);
196	return 1;
197}
198
199const char *
200dec_1000_intr_string(ccv, ih)
201	void *ccv;
202	pci_intr_handle_t ih;
203{
204	static const char irqmsg_fmt[] = "dec_1000 irq %ld";
205        static char irqstr[sizeof irqmsg_fmt];
206
207        if (ih >= PCI_NIRQ)
208                panic("dec_1000_intr_string: bogus dec_1000 IRQ 0x%lx", ih);
209
210        snprintf(irqstr, sizeof irqstr, irqmsg_fmt, ih);
211        return (irqstr);
212}
213
214int
215dec_1000_intr_line(ccv, ih)
216	void *ccv;
217	pci_intr_handle_t ih;
218{
219#if NSIO > 0
220	return sio_intr_line(NULL /*XXX*/, ih);
221#else
222	return (ih);
223#endif
224}
225
226#if 0
227const struct evcnt *
228dec_1000_intr_evcnt(ccv, ih)
229	void *ccv;
230	pci_intr_handle_t ih;
231{
232
233	if (ih >= PCI_NIRQ)
234		panic("dec_1000_intr_evcnt: bogus dec_1000 IRQ 0x%lx", ih);
235
236	return (alpha_shared_intr_evcnt(dec_1000_pci_intr, ih));
237}
238#endif
239
240void *
241dec_1000_intr_establish(ccv, ih, level, func, arg, name)
242        void *ccv;
243        pci_intr_handle_t ih;
244        int level;
245        int (*func)(void *);
246	void *arg;
247	char *name;
248{
249	void *cookie;
250
251        if (ih >= PCI_NIRQ)
252                panic("dec_1000_intr_establish: IRQ too high, 0x%lx", ih);
253
254	cookie = alpha_shared_intr_establish(dec_1000_pci_intr, ih, IST_LEVEL,
255	    level, func, arg, name);
256
257	if (cookie != NULL &&
258	    alpha_shared_intr_isactive(dec_1000_pci_intr, ih)) {
259		dec_1000_enable_intr(ih);
260	}
261	return (cookie);
262}
263
264void
265dec_1000_intr_disestablish(ccv, cookie)
266        void *ccv, *cookie;
267{
268	struct alpha_shared_intrhand *ih = cookie;
269	unsigned int irq = ih->ih_num;
270	int s;
271
272	s = splhigh();
273
274	alpha_shared_intr_disestablish(dec_1000_pci_intr, cookie,
275	    "dec_1000 irq");
276	if (alpha_shared_intr_isactive(dec_1000_pci_intr, irq) == 0) {
277		dec_1000_disable_intr(irq);
278		alpha_shared_intr_set_dfltsharetype(dec_1000_pci_intr, irq,
279		    IST_NONE);
280	}
281
282	splx(s);
283}
284
285void
286dec_1000_iointr(framep, vec)
287	void *framep;
288	unsigned long vec;
289{
290	int irq;
291
292	if (vec >= 0x900) {
293		if (vec >= 0x900 + (PCI_NIRQ << 4))
294			panic("dec_1000_iointr: vec 0x%lx out of range", vec);
295		irq = (vec - 0x900) >> 4;
296
297		if (!alpha_shared_intr_dispatch(dec_1000_pci_intr, irq)) {
298			alpha_shared_intr_stray(dec_1000_pci_intr, irq,
299			    "dec_1000 irq");
300			if (ALPHA_SHARED_INTR_DISABLE(dec_1000_pci_intr, irq))
301				dec_1000_disable_intr(irq);
302		}
303		return;
304	}
305#if NSIO > 0 || NPCEB > 0
306	if (vec >= 0x800) {
307		sio_iointr(framep, vec);
308		return;
309	}
310#endif
311	panic("dec_1000_intr: weird vec 0x%lx", vec);
312}
313
314/*
315 * Read and write the mystery ICU IMR registers
316 */
317
318#define	IR() bus_space_read_2(another_mystery_icu_iot,		\
319				another_mystery_icu_ioh, 0)
320
321#define	IW(v) bus_space_write_2(another_mystery_icu_iot,	\
322				another_mystery_icu_ioh, 0, (v))
323
324/*
325 * Enable and disable interrupts at the ICU level
326 */
327
328void
329dec_1000_enable_intr(irq)
330	int irq;
331{
332	IW(IR() | 1 << irq);
333}
334
335void
336dec_1000_disable_intr(irq)
337	int irq;
338{
339	IW(IR() & ~(1 << irq));
340}
341/*
342 * Initialize mystery ICU
343 */
344void
345pci_1000_imi()
346{
347	IW(0);					/* XXX ?? */
348}
349