Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / arch / i386 / pci / opti82c700.c
blob90e46a91f276798d0f60ccf3d099038bc880276e
1 /* $NetBSD: opti82c700.c,v 1.8 2006/11/16 01:32:39 christos Exp $ */
3 /*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
34 * Copyright (c) 1999, by UCHIYAMA Yasushi
35 * All rights reserved.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. The name of the developer may NOT be used to endorse or promote products
43 * derived from this software without specific prior written permission.
45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE.
59 * Support for the Opti 82c700 FireStar PCI-ISA bridge interrupt controller.
62 #include <sys/cdefs.h>
63 __KERNEL_RCSID(0, "$NetBSD: opti82c700.c,v 1.8 2006/11/16 01:32:39 christos Exp $");
65 #include <sys/param.h>
66 #include <sys/systm.h>
67 #include <sys/device.h>
68 #include <sys/malloc.h>
70 #include <machine/intr.h>
71 #include <machine/bus.h>
73 #include <dev/pci/pcivar.h>
74 #include <dev/pci/pcireg.h>
75 #include <dev/pci/pcidevs.h>
77 #include <i386/pci/pci_intr_fixup.h>
78 #include <i386/pci/opti82c700reg.h>
80 #ifdef FIRESTARDEBUG
81 #define DPRINTF(arg) printf arg
82 #else
83 #define DPRINTF(arg)
84 #endif
86 int opti82c700_getclink(pciintr_icu_handle_t, int, int *);
87 int opti82c700_get_intr(pciintr_icu_handle_t, int, int *);
88 int opti82c700_set_intr(pciintr_icu_handle_t, int, int);
89 int opti82c700_get_trigger(pciintr_icu_handle_t, int, int *);
90 int opti82c700_set_trigger(pciintr_icu_handle_t, int, int);
92 const struct pciintr_icu opti82c700_pci_icu = {
93 opti82c700_getclink,
94 opti82c700_get_intr,
95 opti82c700_set_intr,
96 opti82c700_get_trigger,
97 opti82c700_set_trigger,
100 struct opti82c700_handle {
101 pci_chipset_tag_t ph_pc;
102 pcitag_t ph_tag;
105 int opti82c700_addr(int, int *, int *);
106 #ifdef FIRESTARDEBUG
107 void opti82c700_pir_dump(struct opti82c700_handle *);
108 #endif
111 opti82c700_init(pci_chipset_tag_t pc, bus_space_tag_t iot,
112 pcitag_t tag, pciintr_icu_tag_t *ptagp, pciintr_icu_handle_t *phandp)
114 struct opti82c700_handle *ph;
116 ph = malloc(sizeof(*ph), M_DEVBUF, M_NOWAIT);
117 if (ph == NULL)
118 return (1);
120 ph->ph_pc = pc;
121 ph->ph_tag = tag;
122 #ifdef FIRESTARDEBUG
123 opti82c700_pir_dump(ph);
124 #endif
125 *ptagp = &opti82c700_pci_icu;
126 *phandp = ph;
127 return (0);
131 opti82c700_addr(int link, int *addrofs, int *ofs)
133 int regofs, src;
135 regofs = FIRESTAR_PIR_REGOFS(link);
136 src = FIRESTAR_PIR_SELECTSRC(link);
138 switch (src) {
139 case FIRESTAR_PIR_SELECT_NONE:
140 return (1);
142 case FIRESTAR_PIR_SELECT_IRQ:
143 if (regofs < 0 || regofs > 7)
144 return (1);
145 *addrofs = FIRESTAR_CFG_INTR_IRQ + (regofs >> 2);
146 *ofs = (regofs & 3) << 3;
147 break;
149 case FIRESTAR_PIR_SELECT_PIRQ:
150 /* FALLTHROUGH */
151 case FIRESTAR_PIR_SELECT_BRIDGE:
152 if (regofs < 0 || regofs > 3)
153 return (1);
154 *addrofs = FIRESTAR_CFG_INTR_PIRQ;
155 *ofs = regofs << 2;
156 break;
158 default:
159 return (1);
162 return (0);
166 opti82c700_getclink(pciintr_icu_handle_t v, int link, int *clinkp)
168 DPRINTF(("FireStar link value 0x%x: ", link));
170 switch (FIRESTAR_PIR_SELECTSRC(link)) {
171 default:
172 DPRINTF(("bogus IRQ selection source\n"));
173 return (1);
174 case FIRESTAR_PIR_SELECT_NONE:
175 DPRINTF(("No interrupt connection\n"));
176 return (1);
177 case FIRESTAR_PIR_SELECT_IRQ:
178 DPRINTF(("FireStar IRQ pin"));
179 break;
180 case FIRESTAR_PIR_SELECT_PIRQ:
181 DPRINTF(("FireStar PIO pin or Serial IRQ PIRQ#"));
182 break;
183 case FIRESTAR_PIR_SELECT_BRIDGE:
184 DPRINTF(("FireBridge 1 INTx# pin"));
185 break;
188 DPRINTF((" REGOFST:%#x\n", FIRESTAR_PIR_REGOFS(link)));
189 *clinkp = link;
191 return (0);
195 opti82c700_get_intr(pciintr_icu_handle_t v, int clink, int *irqp)
197 struct opti82c700_handle *ph = v;
198 pcireg_t reg;
199 int val, addrofs, ofs;
201 if (opti82c700_addr(clink, &addrofs, &ofs))
202 return (1);
204 reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
205 val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
207 *irqp = (val == FIRESTAR_PIRQ_NONE) ?
208 X86_PCI_INTERRUPT_LINE_NO_CONNECTION : val;
210 return (0);
214 opti82c700_set_intr(pciintr_icu_handle_t v, int clink, int irq)
216 struct opti82c700_handle *ph = v;
217 int addrofs, ofs;
218 pcireg_t reg;
220 if (FIRESTAR_LEGAL_IRQ(irq) == 0)
221 return (1);
223 if (opti82c700_addr(clink, &addrofs, &ofs))
224 return (1);
226 reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
227 reg &= ~(FIRESTAR_CFG_PIRQ_MASK << ofs);
228 reg |= (irq << ofs);
229 pci_conf_write(ph->ph_pc, ph->ph_tag, addrofs, reg);
231 return (0);
235 opti82c700_get_trigger(pciintr_icu_handle_t v, int irq, int *triggerp)
237 struct opti82c700_handle *ph = v;
238 int i, val, addrofs, ofs;
239 pcireg_t reg;
241 if (FIRESTAR_LEGAL_IRQ(irq) == 0) {
242 /* ISA IRQ? */
243 *triggerp = IST_EDGE;
244 return (0);
248 * Search PCIDV1 registers.
250 for (i = 0; i < 8; i++) {
251 opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_IRQ,
252 i), &addrofs, &ofs);
253 reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
254 val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
255 if (val != irq)
256 continue;
257 val = ((reg >> ofs) >> FIRESTAR_TRIGGER_SHIFT) &
258 FIRESTAR_TRIGGER_MASK;
259 *triggerp = val ? IST_LEVEL : IST_EDGE;
260 return (0);
264 * Search PIO PCIIRQ.
266 for (i = 0; i < 4; i++) {
267 opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_PIRQ,
268 i), &addrofs, &ofs);
269 reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
270 val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
271 if (val != irq)
272 continue;
273 *triggerp = IST_LEVEL;
274 return (0);
277 return (1);
281 opti82c700_set_trigger(pciintr_icu_handle_t v, int irq, int trigger)
283 struct opti82c700_handle *ph = v;
284 int i, val, addrofs, ofs;
285 pcireg_t reg;
287 if (FIRESTAR_LEGAL_IRQ(irq) == 0) {
288 /* ISA IRQ? */
289 return ((trigger != IST_LEVEL) ? 0 : 1);
293 * Search PCIDV1 registers.
295 for (i = 0; i < 8; i++) {
296 opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_IRQ,
297 i), &addrofs, &ofs);
298 reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
299 val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
300 if (val != irq)
301 continue;
302 if (trigger == IST_LEVEL)
303 reg |= (FIRESTAR_TRIGGER_MASK <<
304 (FIRESTAR_TRIGGER_SHIFT + ofs));
305 else
306 reg &= ~(FIRESTAR_TRIGGER_MASK <<
307 (FIRESTAR_TRIGGER_SHIFT + ofs));
308 pci_conf_write(ph->ph_pc, ph->ph_tag, addrofs, reg);
309 return (0);
313 * Search PIO PCIIRQ.
315 for (i = 0; i < 4; i++) {
316 opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_PIRQ,
317 i), &addrofs, &ofs);
318 reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
319 val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
320 if (val != irq)
321 continue;
322 return (trigger == IST_LEVEL ? 0 : 1);
325 return (1);
328 #ifdef FIRESTARDEBUG
329 void
330 opti82c700_pir_dump(struct opti82c700_handle *ph)
332 pcireg_t r;
333 pcitag_t tag = ph->ph_tag;
334 pci_chipset_tag_t pc = ph->ph_pc;
335 int i, j, k;
337 /* FireStar IRQ pin */
338 printf("-FireStar IRQ pin-\n");
339 for (i = j = k = 0; i < 8; i += 4) {
340 r = pci_conf_read(pc, tag, 0xb0 + i);
341 printf ("\t");
342 for (j = 0; j < 4; j++, k++, r >>= 8) {
343 printf("[%d:%s-IRQ%2d] ", k,
344 (r & (FIRESTAR_TRIGGER_MASK <<
345 FIRESTAR_TRIGGER_SHIFT)) ? "PCI" : "ISA",
346 r & FIRESTAR_CFG_PIRQ_MASK);
348 printf("\n");
351 /* FireStar PIO pin or Serial IRQ PIRQ# */
352 r = pci_conf_read(pc, tag, 0xb8);
353 printf("-FireStar PIO pin or Serial IRQ PIRQ#-\n\t");
354 for (i = 0; i < 4; i++, r >>= 4) {
355 printf("[PCIIRQ%d# %d] ", i, r & FIRESTAR_CFG_PIRQ_MASK);
357 printf("\n");
359 #endif /* FIRESTARDEBUG */