Sync usage with man page.
[netbsd-mini2440.git] / sys / arch / alpha / pci / pci_a12.c
blob9d8cf5e3157f5675936a1719bc0ae5f67e87856a
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.
5 * All rights reserved.
7 * Author: Ross Harvey
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
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
23 * assignment date.
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>
45 #include <sys/time.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 {
72 int on;
73 int (*f)(void *);
74 void *a;
75 } a12_intr_pci = { 0 },
76 a12_intr_serr = { 1, pci_serr },
77 a12_intr_flag = { 1, a12_xbar_flag },
78 a12_intr_iei = { 0 },
79 a12_intr_dc = { 0 },
81 a12_intr_xb = { 0 };
83 static struct gintcall {
84 char flag;
85 char needsclear;
86 char intr_index; /* XXX implicit crossref */
87 struct a12_intr_vect_t *f;
88 char *msg;
89 } gintcall[] = {
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"},
99 { 0 }
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);
117 void
118 pci_a12_pickintr(struct a12c_config *ccp)
120 pci_chipset_tag_t pc = &ccp->ac_pc;
122 pc->pc_intr_v = ccp;
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,
133 "a12", "pci irq");
135 set_iointr(a12_iointr);
138 int
139 avalon_a12_intr_map(ccv, bustag, buspin, line, ihp)
140 void *ccv;
141 pcitag_t bustag;
142 int buspin, line;
143 pci_intr_handle_t *ihp;
145 /* only one PCI slot (per CPU, that is, but there are 12 CPU's!) */
146 *ihp = 0;
147 return 0;
150 const char *
151 avalon_a12_intr_string(void *ccv, pci_intr_handle_t ih)
153 return "a12 pci irq"; /* see "only one" note above */
156 const struct evcnt *
157 avalon_a12_intr_evcnt(void *ccv, pci_intr_handle_t ih)
160 return (&a12_intr_evcnt);
163 void *
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;
168 a12_intr_pci.on= 1;
169 alpha_wmb();
170 REGVAL(A12_OMR) |= A12_OMR_PCI_ENABLE;
171 alpha_mb();
172 return (void *)func;
175 void
176 avalon_a12_intr_disestablish(void *ccv, void *cookie)
178 if(cookie == a12_intr_pci.f) {
179 alpha_wmb();
180 REGVAL(A12_OMR) &= ~A12_OMR_PCI_ENABLE;
181 alpha_mb();
182 a12_intr_pci.f = 0;
183 a12_intr_pci.on= 0;
184 } else What();
187 void a12_intr_register_xb(f)
188 int (*f)(void *);
190 a12_intr_xb.f = f;
191 a12_intr_xb.on = 1;
194 void a12_intr_register_icw(f)
195 int (*f)(void *);
197 long t;
199 t = REGVAL(A12_OMR) & ~A12_OMR_ICW_ENABLE;
200 if ((a12_intr_dc.on = (f != NULL)) != 0)
201 t |= A12_OMR_ICW_ENABLE;
202 a12_intr_dc.f = f;
203 alpha_wmb();
204 REGVAL(A12_OMR) = t;
205 alpha_mb();
208 long a12_nothing;
210 static void
211 clear_gsr_interrupt(long write_1_to_clear)
213 REGVAL(A12_GSR) = write_1_to_clear;
214 alpha_mb();
215 a12_nothing = REGVAL(A12_GSR);
218 static int
219 pci_serr(void *p)
221 panic("pci_serr");
224 static int
225 a12_xbar_flag(void *p)
227 panic("a12_xbar_flag: %s", p);
230 static void
231 a12_GInt(void)
233 struct gintcall *gic;
234 long gsrsource,
235 gsrvalue = LOADGSR();
236 void *s;
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) {
244 if(gic->needsclear)
245 clear_gsr_interrupt(1L<<gic->flag);
247 s = gic->f->a;
248 if (s == NULL)
249 s = gic->msg;
250 if (gic->f->f == NULL)
251 printf("Stray interrupt: %s OMR=%lx\n",
252 gic->msg, REGVAL(A12_OMR) & 0xffc0);
253 else gic->f->f(s);
254 alpha_wmb();
260 * IRQ_H 3 2 1 0
261 * EV5(10) 23 22 21 20
262 * EV5(16) 17 16 15 14
263 * OSF IPL 6 5 4 3
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
269 void
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++;
280 switch(irq) {
281 case 0:
282 if (a12_intr_xb.f == NULL)
283 panic("no switch interrupt registered");
284 else a12_intr_xb.f(NULL);
285 return;
286 case 2:
287 a12_GInt();
288 return;
289 default:
290 panic("a12_iointr");