Annotation of sys/arch/i386/pci/opti82c700.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: opti82c700.c,v 1.7 2006/09/19 11:06:34 jsg Exp $ */
2: /* $NetBSD: opti82c700.c,v 1.2 2000/07/18 11:07:20 soda Exp $ */
3:
4: /*-
5: * Copyright (c) 1999 The NetBSD Foundation, Inc.
6: * All rights reserved.
7: *
8: * This code is derived from software contributed to The NetBSD Foundation
9: * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
10: * NASA Ames Research Center.
11: *
12: * Redistribution and use in source and binary forms, with or without
13: * modification, are permitted provided that the following conditions
14: * are met:
15: * 1. Redistributions of source code must retain the above copyright
16: * notice, this list of conditions and the following disclaimer.
17: * 2. Redistributions in binary form must reproduce the above copyright
18: * notice, this list of conditions and the following disclaimer in the
19: * documentation and/or other materials provided with the distribution.
20: * 3. All advertising materials mentioning features or use of this software
21: * must display the following acknowledgement:
22: * This product includes software developed by the NetBSD
23: * Foundation, Inc. and its contributors.
24: * 4. Neither the name of The NetBSD Foundation nor the names of its
25: * contributors may be used to endorse or promote products derived
26: * from this software without specific prior written permission.
27: *
28: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38: * POSSIBILITY OF SUCH DAMAGE.
39: */
40:
41: /*
42: * Copyright (c) 1999, by UCHIYAMA Yasushi
43: * All rights reserved.
44: *
45: * Redistribution and use in source and binary forms, with or without
46: * modification, are permitted provided that the following conditions
47: * are met:
48: * 1. Redistributions of source code must retain the above copyright
49: * notice, this list of conditions and the following disclaimer.
50: * 2. The name of the developer may NOT be used to endorse or promote products
51: * derived from this software without specific prior written permission.
52: *
53: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
54: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
57: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63: * SUCH DAMAGE.
64: */
65:
66: /*
67: * Support for the Opti 82c700 FireStar PCI-ISA bridge interrupt controller.
68: */
69:
70: #include <sys/param.h>
71: #include <sys/systm.h>
72: #include <sys/device.h>
73: #include <sys/malloc.h>
74:
75: #include <machine/intr.h>
76: #include <machine/bus.h>
77:
78: #include <dev/pci/pcivar.h>
79: #include <dev/pci/pcireg.h>
80: #include <dev/pci/pcidevs.h>
81:
82: #include <i386/pci/pcibiosvar.h>
83: #include <i386/pci/opti82c700reg.h>
84:
85: #ifdef FIRESTARDEBUG
86: #define DPRINTF(arg) printf arg
87: #else
88: #define DPRINTF(arg)
89: #endif
90:
91: int opti82c700_getclink(pciintr_icu_handle_t, int, int *);
92: int opti82c700_get_intr(pciintr_icu_handle_t, int, int *);
93: int opti82c700_set_intr(pciintr_icu_handle_t, int, int);
94: int opti82c700_get_trigger(pciintr_icu_handle_t, int, int *);
95: int opti82c700_set_trigger(pciintr_icu_handle_t, int, int);
96:
97: const struct pciintr_icu opti82c700_pci_icu = {
98: opti82c700_getclink,
99: opti82c700_get_intr,
100: opti82c700_set_intr,
101: opti82c700_get_trigger,
102: opti82c700_set_trigger,
103: };
104:
105: struct opti82c700_handle {
106: pci_chipset_tag_t ph_pc;
107: pcitag_t ph_tag;
108: };
109:
110: int opti82c700_addr(int, int *, int *);
111: #ifdef FIRESTARDEBUG
112: void opti82c700_pir_dump(struct opti82c700_handle *);
113: #endif
114:
115: int
116: opti82c700_init(pci_chipset_tag_t pc, bus_space_tag_t iot, pcitag_t tag,
117: pciintr_icu_tag_t *ptagp, pciintr_icu_handle_t *phandp)
118: {
119: struct opti82c700_handle *ph;
120:
121: ph = malloc(sizeof(*ph), M_DEVBUF, M_NOWAIT);
122: if (ph == NULL)
123: return (1);
124:
125: ph->ph_pc = pc;
126: ph->ph_tag = tag;
127: #ifdef FIRESTARDEBUG
128: opti82c700_pir_dump(ph);
129: #endif
130: *ptagp = &opti82c700_pci_icu;
131: *phandp = ph;
132: return (0);
133: }
134:
135: int
136: opti82c700_addr(int link, int *addrofs, int *ofs)
137: {
138: int regofs, src;
139:
140: regofs = FIRESTAR_PIR_REGOFS(link);
141: src = FIRESTAR_PIR_SELECTSRC(link);
142:
143: switch (src) {
144: case FIRESTAR_PIR_SELECT_NONE:
145: return (1);
146:
147: case FIRESTAR_PIR_SELECT_IRQ:
148: if (regofs < 0 || regofs > 7)
149: return (1);
150: *addrofs = FIRESTAR_CFG_INTR_IRQ + (regofs >> 2);
151: *ofs = (regofs & 3) << 3;
152: break;
153:
154: case FIRESTAR_PIR_SELECT_PIRQ:
155: /* FALLTHROUGH */
156: case FIRESTAR_PIR_SELECT_BRIDGE:
157: if (regofs < 0 || regofs > 3)
158: return (1);
159: *addrofs = FIRESTAR_CFG_INTR_PIRQ;
160: *ofs = regofs << 2;
161: break;
162:
163: default:
164: return (1);
165: }
166:
167: return (0);
168: }
169:
170: int
171: opti82c700_getclink(pciintr_icu_handle_t v, int link, int *clinkp)
172: {
173: DPRINTF(("FireStar link value 0x%x: ", link));
174:
175: switch (FIRESTAR_PIR_SELECTSRC(link)) {
176: default:
177: DPRINTF(("bogus IRQ selection source\n"));
178: return (1);
179: case FIRESTAR_PIR_SELECT_NONE:
180: DPRINTF(("No interrupt connection\n"));
181: return (1);
182: case FIRESTAR_PIR_SELECT_IRQ:
183: DPRINTF(("FireStar IRQ pin"));
184: break;
185: case FIRESTAR_PIR_SELECT_PIRQ:
186: DPRINTF(("FireStar PIO pin or Serial IRQ PIRQ#"));
187: break;
188: case FIRESTAR_PIR_SELECT_BRIDGE:
189: DPRINTF(("FireBridge 1 INTx# pin"));
190: break;
191: }
192:
193: DPRINTF((" REGOFST:%#x\n", FIRESTAR_PIR_REGOFS(link)));
194: *clinkp = link;
195:
196: return (0);
197: }
198:
199: int
200: opti82c700_get_intr(pciintr_icu_handle_t v, int clink, int *irqp)
201: {
202: struct opti82c700_handle *ph = v;
203: pcireg_t reg;
204: int val, addrofs, ofs;
205:
206: if (opti82c700_addr(clink, &addrofs, &ofs))
207: return (1);
208:
209: reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
210: val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
211:
212: *irqp = (val == FIRESTAR_PIRQ_NONE) ?
213: I386_PCI_INTERRUPT_LINE_NO_CONNECTION : val;
214:
215: return (0);
216: }
217:
218: int
219: opti82c700_set_intr(pciintr_icu_handle_t v, int clink, int irq)
220: {
221: struct opti82c700_handle *ph = v;
222: int addrofs, ofs;
223: pcireg_t reg;
224:
225: if (FIRESTAR_LEGAL_IRQ(irq) == 0)
226: return (1);
227:
228: if (opti82c700_addr(clink, &addrofs, &ofs))
229: return (1);
230:
231: reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
232: reg &= ~(FIRESTAR_CFG_PIRQ_MASK << ofs);
233: reg |= (irq << ofs);
234: pci_conf_write(ph->ph_pc, ph->ph_tag, addrofs, reg);
235:
236: return (0);
237: }
238:
239: int
240: opti82c700_get_trigger(pciintr_icu_handle_t v, int irq, int *triggerp)
241: {
242: struct opti82c700_handle *ph = v;
243: int i, val, addrofs, ofs;
244: pcireg_t reg;
245:
246: if (FIRESTAR_LEGAL_IRQ(irq) == 0) {
247: /* ISA IRQ? */
248: *triggerp = IST_EDGE;
249: return (0);
250: }
251:
252: /*
253: * Search PCIDV1 registers.
254: */
255: for (i = 0; i < 8; i++) {
256: opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_IRQ,
257: i), &addrofs, &ofs);
258: reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
259: val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
260: if (val != irq)
261: continue;
262: val = ((reg >> ofs) >> FIRESTAR_TRIGGER_SHIFT) &
263: FIRESTAR_TRIGGER_MASK;
264: *triggerp = val ? IST_LEVEL : IST_EDGE;
265: return (0);
266: }
267:
268: /*
269: * Search PIO PCIIRQ.
270: */
271: for (i = 0; i < 4; i++) {
272: opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_PIRQ,
273: i), &addrofs, &ofs);
274: reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
275: val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
276: if (val != irq)
277: continue;
278: *triggerp = IST_LEVEL;
279: return (0);
280: }
281:
282: return (1);
283: }
284:
285: int
286: opti82c700_set_trigger(pciintr_icu_handle_t v, int irq, int trigger)
287: {
288: struct opti82c700_handle *ph = v;
289: int i, val, addrofs, ofs;
290: pcireg_t reg;
291:
292: if (FIRESTAR_LEGAL_IRQ(irq) == 0) {
293: /* ISA IRQ? */
294: return ((trigger != IST_LEVEL) ? 0 : 1);
295: }
296:
297: /*
298: * Search PCIDV1 registers.
299: */
300: for (i = 0; i < 8; i++) {
301: opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_IRQ,
302: i), &addrofs, &ofs);
303: reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
304: val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
305: if (val != irq)
306: continue;
307: if (trigger == IST_LEVEL)
308: reg |= (FIRESTAR_TRIGGER_MASK <<
309: (FIRESTAR_TRIGGER_SHIFT + ofs));
310: else
311: reg &= ~(FIRESTAR_TRIGGER_MASK <<
312: (FIRESTAR_TRIGGER_SHIFT + ofs));
313: pci_conf_write(ph->ph_pc, ph->ph_tag, addrofs, reg);
314: return (0);
315: }
316:
317: /*
318: * Search PIO PCIIRQ.
319: */
320: for (i = 0; i < 4; i++) {
321: opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_PIRQ,
322: i), &addrofs, &ofs);
323: reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
324: val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
325: if (val != irq)
326: continue;
327: return (trigger == IST_LEVEL ? 0 : 1);
328: }
329:
330: return (1);
331: }
CVSweb