1 /* $NetBSD: pci_a12.c,v 1.10 2009/03/14 21:04:02 dsl Exp $ */
3 /* [Notice revision 2.0]
4 * Copyright (c) 1997, 1998 Avalon Computer Systems, Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright and
13 * author notice, 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. Neither the name of Avalon Computer Systems, Inc. nor the names of
18 * its contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 * 4. This copyright will be assigned to The NetBSD Foundation on
21 * 1/1/2000 unless these terms (including possibly the assignment
22 * date) are updated in writing by Avalon prior to the latest specified
25 * THIS SOFTWARE IS PROVIDED BY AVALON COMPUTER SYSTEMS, INC. AND CONTRIBUTORS
26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
38 #include "opt_avalon_a12.h" /* Config options headers */
39 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
41 __KERNEL_RCSID(0, "$NetBSD: pci_a12.c,v 1.10 2009/03/14 21:04:02 dsl Exp $");
43 #include <sys/types.h>
44 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/errno.h>
48 #include <sys/malloc.h>
49 #include <sys/device.h>
50 #include <sys/syslog.h>
52 #include <uvm/uvm_extern.h>
54 #include <machine/autoconf.h>
56 #include <dev/pci/pcireg.h>
57 #include <dev/pci/pcivar.h>
59 #include <alpha/pci/a12creg.h>
60 #include <alpha/pci/a12cvar.h>
62 #include <alpha/pci/pci_a12.h>
64 #define PCI_A12() /* Generate ctags(1) key */
66 #define LOADGSR() (REGVAL(A12_GSR) & 0x7fc0)
68 static int pci_serr(void *);
69 static int a12_xbar_flag(void *);
71 struct a12_intr_vect_t
{
75 } a12_intr_pci
= { 0 },
76 a12_intr_serr
= { 1, pci_serr
},
77 a12_intr_flag
= { 1, a12_xbar_flag
},
83 static struct gintcall
{
86 char intr_index
; /* XXX implicit crossref */
87 struct a12_intr_vect_t
*f
;
90 { 6, 0, 2, &a12_intr_pci
, "PCI Device" },
91 { 7, 1, 3, &a12_intr_serr
, "PCI SERR#" },
92 { 8, 1, 4, &a12_intr_flag
, "XB Frame MCE" },
93 { 9, 1, 5, &a12_intr_flag
, "XB Frame ECE" },
94 /* skip 10, gsr.TEI */
95 { 11, 1, 6, &a12_intr_iei
, "Interval Timer"},
96 { 12, 1, 7, &a12_intr_flag
, "XB FIFO Overrun"},
97 { 13, 1, 8, &a12_intr_flag
, "XB FIFO Underrun"},
98 { 14, 1, 9, &a12_intr_dc
, "DC Control Word"},
102 struct evcnt a12_intr_evcnt
;
104 int avalon_a12_intr_map(void *, pcitag_t
, int, int,
105 pci_intr_handle_t
*);
106 const char *avalon_a12_intr_string(void *, pci_intr_handle_t
);
107 const struct evcnt
*avalon_a12_intr_evcnt(void *, pci_intr_handle_t
);
108 void *avalon_a12_intr_establish(void *, pci_intr_handle_t
,
109 int, int (*func
)(void *), void *);
110 void avalon_a12_intr_disestablish(void *, void *);
112 static void clear_gsr_interrupt(long);
113 static void a12_GInt(void);
115 void a12_iointr(void *framep
, unsigned long vec
);
118 pci_a12_pickintr(struct a12c_config
*ccp
)
120 pci_chipset_tag_t pc
= &ccp
->ac_pc
;
123 pc
->pc_intr_map
= avalon_a12_intr_map
;
124 pc
->pc_intr_string
= avalon_a12_intr_string
;
125 pc
->pc_intr_evcnt
= avalon_a12_intr_evcnt
;
126 pc
->pc_intr_establish
= avalon_a12_intr_establish
;
127 pc
->pc_intr_disestablish
= avalon_a12_intr_disestablish
;
129 /* Not supported on A12. */
130 pc
->pc_pciide_compat_intr_establish
= NULL
;
132 evcnt_attach_dynamic(&a12_intr_evcnt
, EVCNT_TYPE_INTR
, NULL
,
135 set_iointr(a12_iointr
);
139 avalon_a12_intr_map(ccv
, bustag
, buspin
, line
, ihp
)
143 pci_intr_handle_t
*ihp
;
145 /* only one PCI slot (per CPU, that is, but there are 12 CPU's!) */
151 avalon_a12_intr_string(void *ccv
, pci_intr_handle_t ih
)
153 return "a12 pci irq"; /* see "only one" note above */
157 avalon_a12_intr_evcnt(void *ccv
, pci_intr_handle_t ih
)
160 return (&a12_intr_evcnt
);
164 avalon_a12_intr_establish(void *ccv
, pci_intr_handle_t ih
, int level
, int (*func
)(void *), void *arg
)
166 a12_intr_pci
.f
= func
;
167 a12_intr_pci
.a
= arg
;
170 REGVAL(A12_OMR
) |= A12_OMR_PCI_ENABLE
;
176 avalon_a12_intr_disestablish(void *ccv
, void *cookie
)
178 if(cookie
== a12_intr_pci
.f
) {
180 REGVAL(A12_OMR
) &= ~A12_OMR_PCI_ENABLE
;
187 void a12_intr_register_xb(f
)
194 void a12_intr_register_icw(f
)
199 t
= REGVAL(A12_OMR
) & ~A12_OMR_ICW_ENABLE
;
200 if ((a12_intr_dc
.on
= (f
!= NULL
)) != 0)
201 t
|= A12_OMR_ICW_ENABLE
;
211 clear_gsr_interrupt(long write_1_to_clear
)
213 REGVAL(A12_GSR
) = write_1_to_clear
;
215 a12_nothing
= REGVAL(A12_GSR
);
225 a12_xbar_flag(void *p
)
227 panic("a12_xbar_flag: %s", p
);
233 struct gintcall
*gic
;
235 gsrvalue
= LOADGSR();
239 * Switch interrupts do not go through this function
241 for(gic
=gintcall
; gic
->f
; ++gic
) {
242 gsrsource
= gsrvalue
& 1L<<gic
->flag
;
243 if (gsrsource
&& gic
->f
->on
) {
245 clear_gsr_interrupt(1L<<gic
->flag
);
250 if (gic
->f
->f
== NULL
)
251 printf("Stray interrupt: %s OMR=%lx\n",
252 gic
->msg
, REGVAL(A12_OMR
) & 0xffc0);
261 * EV5(10) 23 22 21 20
262 * EV5(16) 17 16 15 14
264 * VECTOR(16) 940 930 920 900 note: no 910 or 940
265 * f(VECTOR) 4 3 2 0 note: no 1 or 4
266 * EVENT Never Clk Misc Xbar
270 a12_iointr(void *framep
, unsigned long vec
)
272 unsigned irq
= (vec
-0x900) >> 4; /* this is the f(vector) above */
275 * Xbar device is in the A12 CPU core logic, so its interrupts
276 * might as well be hardwired.
278 a12_intr_evcnt
.ev_count
++;
282 if (a12_intr_xb
.f
== NULL
)
283 panic("no switch interrupt registered");
284 else a12_intr_xb
.f(NULL
);