This source file includes following definitions.
- via8231_init
- via8231_getclink
- via8231_get_intr
- via8231_set_intr
- via8231_get_trigger
- via8231_set_trigger
- via8231_pir_dump
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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 },
122 { 0x0f, 8+0 },
123 { 0x0f, 8+4 },
124 { 0x0f, 16+4 }
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