Annotation of sys/arch/i386/pci/via8231.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: via8231.c,v 1.7 2006/09/19 11:06:34 jsg Exp $ */
2:
3: /*-
4: * Copyright (c) 1999 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
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.
10: *
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.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the NetBSD
22: * Foundation, Inc. and its contributors.
23: * 4. Neither the name of The NetBSD Foundation nor the names of its
24: * contributors may be used to endorse or promote products derived
25: * from this software without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37: * POSSIBILITY OF SUCH DAMAGE.
38: */
39: /*
40: * Copyright (c) 2005, by Michael Shalayeff
41: * Copyright (c) 2003, by Matthew Gream
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 VIA Technologies Inc. VIA8231 PCI to ISA Bridge
68: * Based upon documentation:
69: * 1. VIA VT8231 South Bridge, Revision 1.85 (March 11, 2002), pg 73
70: * 2. VIA VT8237R South Bridge, Revision 2.06 (December 15, 2004), pg 100
71: * Derived from amd756.c
72: */
73:
74: #include <sys/param.h>
75: #include <sys/systm.h>
76: #include <sys/device.h>
77: #include <sys/malloc.h>
78:
79: #include <machine/intr.h>
80: #include <machine/bus.h>
81:
82: #include <dev/pci/pcivar.h>
83: #include <dev/pci/pcireg.h>
84: #include <dev/pci/pcidevs.h>
85:
86: #include <i386/pci/pcibiosvar.h>
87: #include <i386/pci/via8231reg.h>
88:
89: struct via8231_handle {
90: bus_space_tag_t ph_iot;
91: bus_space_handle_t ph_regs_ioh;
92: pci_chipset_tag_t ph_pc;
93: pcitag_t ph_tag;
94: int flags;
95: #define VT8237 0x0001
96: };
97:
98: int via8231_getclink(pciintr_icu_handle_t, int, int *);
99: int via8231_get_intr(pciintr_icu_handle_t, int, int *);
100: int via8231_set_intr(pciintr_icu_handle_t, int, int);
101: int via8231_get_trigger(pciintr_icu_handle_t, int, int *);
102: int via8231_set_trigger(pciintr_icu_handle_t, int, int);
103: #ifdef VIA8231_DEBUG
104: static void via8231_pir_dump(const char*, struct via8231_handle *);
105: #endif
106:
107: const struct pciintr_icu via8231_pci_icu = {
108: via8231_getclink,
109: via8231_get_intr,
110: via8231_set_intr,
111: via8231_get_trigger,
112: via8231_set_trigger,
113: };
114:
115: struct mask_shft_pair {
116: int mask;
117: int shft;
118: };
119:
120: static const struct mask_shft_pair via8231_routing_cnfg[VIA8231_LINK_MAX+1] = {
121: { 0x0f, 0+4 }, /*PINTA#*/
122: { 0x0f, 8+0 }, /*PINTB#*/
123: { 0x0f, 8+4 }, /*PINTC#*/
124: { 0x0f, 16+4 } /*PINTD#*/
125: };
126:
127: #define VIA8231_GET_TRIGGER_CNFG(reg, pirq) \
128: ((reg) & (1 << (3 - (clink & 3))))
129: #define VIA8231_SET_TRIGGER_CNFG(reg, clink, cfg) \
130: (((reg) & ~(1 << (3 - (clink & 3)))) | ((cfg) << (3 - (clink & 3))))
131:
132: #define VIA8231_GET_ROUTING_CNFG(reg, pirq) \
133: (((reg) >> via8231_routing_cnfg[(pirq)].shft) & \
134: via8231_routing_cnfg[(pirq)].mask)
135:
136: #define VIA8231_SET_ROUTING_CNFG(reg, pirq, cfg) \
137: (((reg) & ~(via8231_routing_cnfg[(pirq)].mask << \
138: via8231_routing_cnfg[(pirq)].shft)) | \
139: (((cfg) & via8231_routing_cnfg[(pirq)].mask) << \
140: via8231_routing_cnfg[(pirq)].shft))
141:
142: int
143: via8231_init(pci_chipset_tag_t pc, bus_space_tag_t iot, pcitag_t tag,
144: pciintr_icu_tag_t *ptagp, pciintr_icu_handle_t *phandp)
145: {
146: struct via8231_handle *ph;
147: pcireg_t id;
148:
149: ph = malloc(sizeof(*ph), M_DEVBUF, M_NOWAIT);
150: if (ph == NULL)
151: return (1);
152:
153: ph->ph_iot = iot;
154: ph->ph_pc = pc;
155: ph->ph_tag = tag;
156: id = pci_conf_read(pc, tag, PCI_ID_REG);
157: ph->flags = PCI_VENDOR(id) == PCI_VENDOR_VIATECH &&
158: PCI_PRODUCT(id) == PCI_PRODUCT_VIATECH_VT8231_ISA? 0 : VT8237;
159:
160: *ptagp = &via8231_pci_icu;
161: *phandp = ph;
162:
163: #ifdef VIA8231_DEBUG
164: via8231_pir_dump("via8231_init", ph);
165: #endif
166:
167: return 0;
168: }
169:
170: int
171: via8231_getclink(pciintr_icu_handle_t v, int link, int *clinkp)
172: {
173: struct via8231_handle *ph = v;
174:
175: if ((ph->flags & VT8237) && !VIA8237_LINK_LEGAL(link - 1))
176: return (1);
177:
178: if (!(ph->flags & VT8237) && !VIA8231_LINK_LEGAL(link - 1))
179: return (1);
180:
181: *clinkp = link - 1;
182: return (0);
183: }
184:
185: int
186: via8231_get_intr(pciintr_icu_handle_t v, int clink, int *irqp)
187: {
188: struct via8231_handle *ph = v;
189: int reg, val;
190:
191: if (VIA8237_LINK_LEGAL(clink) == 0)
192: return (1);
193:
194: if (VIA8231_LINK_LEGAL(clink)) {
195: reg = VIA8231_GET_ROUTING(ph);
196: val = VIA8231_GET_ROUTING_CNFG(reg, clink);
197: } else {
198: reg = VIA8237_GET_ROUTING(ph);
199: val = (reg >> ((clink & 3) * 4)) & 0xf;
200: }
201:
202: *irqp = (val == VIA8231_ROUTING_CNFG_DISABLED) ?
203: I386_PCI_INTERRUPT_LINE_NO_CONNECTION : val;
204:
205: return (0);
206: }
207:
208: int
209: via8231_set_intr(pciintr_icu_handle_t v, int clink, int irq)
210: {
211: struct via8231_handle *ph = v;
212: int reg;
213:
214: if (VIA8237_LINK_LEGAL(clink) == 0 || VIA8231_PIRQ_LEGAL(irq) == 0)
215: return (1);
216:
217: #ifdef VIA8231_DEBUG
218: printf("via8231_set_intr: link(%02x) --> irq(%02x)\n", clink, irq);
219: via8231_pir_dump("via8231_set_intr: ", ph);
220: #endif
221:
222: if (VIA8231_LINK_LEGAL(clink)) {
223: reg = VIA8231_GET_ROUTING(ph);
224: VIA8231_SET_ROUTING(ph,
225: VIA8231_SET_ROUTING_CNFG(reg, clink, irq));
226: } else {
227: reg = VIA8237_GET_ROUTING(ph);
228: VIA8237_SET_ROUTING(ph, (reg & ~(0xf << (clink & 3))) |
229: ((irq & 0xf) << (clink & 3)));
230: }
231:
232: return (0);
233: }
234:
235: int
236: via8231_get_trigger(pciintr_icu_handle_t v, int irq, int *triggerp)
237: {
238: struct via8231_handle *ph = v;
239: int reg, clink, max, pciirq;
240:
241: if (VIA8231_PIRQ_LEGAL(irq) == 0)
242: return (1);
243:
244: max = ph->flags & VT8237? VIA8237_LINK_MAX : VIA8231_LINK_MAX;
245: for (clink = 0; clink <= max; clink++) {
246: via8231_get_intr(v, clink, &pciirq);
247: if (pciirq == irq) {
248: reg = VIA8231_LINK_LEGAL(clink)?
249: VIA8231_GET_TRIGGER(ph):
250: VIA8237_GET_TRIGGER(ph);
251: *triggerp = VIA8231_GET_TRIGGER_CNFG(reg, clink)?
252: IST_EDGE : IST_LEVEL;
253: return (0);
254: }
255: }
256:
257: return (1);
258: }
259:
260: int
261: via8231_set_trigger(pciintr_icu_handle_t v, int irq, int trigger)
262: {
263: struct via8231_handle *ph = v;
264: int reg, clink, max, pciirq;
265:
266: if (VIA8231_PIRQ_LEGAL(irq) == 0 || VIA8231_TRIG_LEGAL(trigger) == 0)
267: return (1);
268:
269: #ifdef VIA8231_DEBUG
270: printf("via8231_set_trig: irq(%02x) --> trig(%02x)\n", irq, trigger);
271: via8231_pir_dump("via8231_set_trig: ", ph);
272: #endif
273:
274: max = ph->flags & VT8237? VIA8237_LINK_MAX : VIA8231_LINK_MAX;
275: for (clink = 0; clink <= VIA8231_LINK_MAX; clink++) {
276: via8231_get_intr(v, clink, &pciirq);
277: if (pciirq == irq) {
278: reg = VIA8231_LINK_LEGAL(clink)?
279: VIA8231_GET_TRIGGER(ph):
280: VIA8237_GET_TRIGGER(ph);
281: switch (trigger) {
282: case IST_LEVEL:
283: reg = VIA8231_SET_TRIGGER_CNFG(reg, clink,
284: VIA8231_TRIGGER_CNFG_LEVEL);
285: break;
286: case IST_EDGE:
287: reg = VIA8231_SET_TRIGGER_CNFG(reg, clink,
288: VIA8231_TRIGGER_CNFG_EDGE);
289: break;
290: default:
291: return (1);
292: }
293: if (VIA8231_LINK_LEGAL(clink))
294: VIA8231_SET_TRIGGER(ph, reg);
295: else
296: VIA8237_SET_TRIGGER(ph, reg);
297: return (0);
298: }
299: }
300:
301: return (1);
302: }
303:
304: #ifdef VIA8231_DEBUG
305: static void
306: via8231_pir_dump(const char *m, struct via8231_handle *ph)
307: {
308: int a, b;
309:
310: a = VIA8231_GET_TRIGGER(ph);
311: b = VIA8231_GET_ROUTING(ph);
312:
313: printf("%s STATE: trigger(%02x), routing(%08x)\n", m, a, b);
314: }
315: #endif
CVSweb