1 /* $NetBSD: opti82c700.c,v 1.8 2006/11/16 01:32:39 christos Exp $ */
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
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
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
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
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>
81 #define DPRINTF(arg) printf arg
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
= {
96 opti82c700_get_trigger
,
97 opti82c700_set_trigger
,
100 struct opti82c700_handle
{
101 pci_chipset_tag_t ph_pc
;
105 int opti82c700_addr(int, int *, int *);
107 void opti82c700_pir_dump(struct opti82c700_handle
*);
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
);
123 opti82c700_pir_dump(ph
);
125 *ptagp
= &opti82c700_pci_icu
;
131 opti82c700_addr(int link
, int *addrofs
, int *ofs
)
135 regofs
= FIRESTAR_PIR_REGOFS(link
);
136 src
= FIRESTAR_PIR_SELECTSRC(link
);
139 case FIRESTAR_PIR_SELECT_NONE
:
142 case FIRESTAR_PIR_SELECT_IRQ
:
143 if (regofs
< 0 || regofs
> 7)
145 *addrofs
= FIRESTAR_CFG_INTR_IRQ
+ (regofs
>> 2);
146 *ofs
= (regofs
& 3) << 3;
149 case FIRESTAR_PIR_SELECT_PIRQ
:
151 case FIRESTAR_PIR_SELECT_BRIDGE
:
152 if (regofs
< 0 || regofs
> 3)
154 *addrofs
= FIRESTAR_CFG_INTR_PIRQ
;
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
)) {
172 DPRINTF(("bogus IRQ selection source\n"));
174 case FIRESTAR_PIR_SELECT_NONE
:
175 DPRINTF(("No interrupt connection\n"));
177 case FIRESTAR_PIR_SELECT_IRQ
:
178 DPRINTF(("FireStar IRQ pin"));
180 case FIRESTAR_PIR_SELECT_PIRQ
:
181 DPRINTF(("FireStar PIO pin or Serial IRQ PIRQ#"));
183 case FIRESTAR_PIR_SELECT_BRIDGE
:
184 DPRINTF(("FireBridge 1 INTx# pin"));
188 DPRINTF((" REGOFST:%#x\n", FIRESTAR_PIR_REGOFS(link
)));
195 opti82c700_get_intr(pciintr_icu_handle_t v
, int clink
, int *irqp
)
197 struct opti82c700_handle
*ph
= v
;
199 int val
, addrofs
, ofs
;
201 if (opti82c700_addr(clink
, &addrofs
, &ofs
))
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
;
214 opti82c700_set_intr(pciintr_icu_handle_t v
, int clink
, int irq
)
216 struct opti82c700_handle
*ph
= v
;
220 if (FIRESTAR_LEGAL_IRQ(irq
) == 0)
223 if (opti82c700_addr(clink
, &addrofs
, &ofs
))
226 reg
= pci_conf_read(ph
->ph_pc
, ph
->ph_tag
, addrofs
);
227 reg
&= ~(FIRESTAR_CFG_PIRQ_MASK
<< ofs
);
229 pci_conf_write(ph
->ph_pc
, ph
->ph_tag
, addrofs
, reg
);
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
;
241 if (FIRESTAR_LEGAL_IRQ(irq
) == 0) {
243 *triggerp
= IST_EDGE
;
248 * Search PCIDV1 registers.
250 for (i
= 0; i
< 8; i
++) {
251 opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_IRQ
,
253 reg
= pci_conf_read(ph
->ph_pc
, ph
->ph_tag
, addrofs
);
254 val
= (reg
>> ofs
) & FIRESTAR_CFG_PIRQ_MASK
;
257 val
= ((reg
>> ofs
) >> FIRESTAR_TRIGGER_SHIFT
) &
258 FIRESTAR_TRIGGER_MASK
;
259 *triggerp
= val
? IST_LEVEL
: IST_EDGE
;
266 for (i
= 0; i
< 4; i
++) {
267 opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_PIRQ
,
269 reg
= pci_conf_read(ph
->ph_pc
, ph
->ph_tag
, addrofs
);
270 val
= (reg
>> ofs
) & FIRESTAR_CFG_PIRQ_MASK
;
273 *triggerp
= IST_LEVEL
;
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
;
287 if (FIRESTAR_LEGAL_IRQ(irq
) == 0) {
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
,
298 reg
= pci_conf_read(ph
->ph_pc
, ph
->ph_tag
, addrofs
);
299 val
= (reg
>> ofs
) & FIRESTAR_CFG_PIRQ_MASK
;
302 if (trigger
== IST_LEVEL
)
303 reg
|= (FIRESTAR_TRIGGER_MASK
<<
304 (FIRESTAR_TRIGGER_SHIFT
+ ofs
));
306 reg
&= ~(FIRESTAR_TRIGGER_MASK
<<
307 (FIRESTAR_TRIGGER_SHIFT
+ ofs
));
308 pci_conf_write(ph
->ph_pc
, ph
->ph_tag
, addrofs
, reg
);
315 for (i
= 0; i
< 4; i
++) {
316 opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_PIRQ
,
318 reg
= pci_conf_read(ph
->ph_pc
, ph
->ph_tag
, addrofs
);
319 val
= (reg
>> ofs
) & FIRESTAR_CFG_PIRQ_MASK
;
322 return (trigger
== IST_LEVEL
? 0 : 1);
330 opti82c700_pir_dump(struct opti82c700_handle
*ph
)
333 pcitag_t tag
= ph
->ph_tag
;
334 pci_chipset_tag_t pc
= ph
->ph_pc
;
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
);
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
);
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
);
359 #endif /* FIRESTARDEBUG */