pci_machdep_ofw.c revision 1.11 1 1.11 phx /* $NetBSD: pci_machdep_ofw.c,v 1.11 2008/02/23 21:11:22 phx Exp $ */
2 1.2 garbled
3 1.2 garbled /*-
4 1.2 garbled * Copyright (c) 2007 The NetBSD Foundation, Inc.
5 1.2 garbled * All rights reserved.
6 1.2 garbled *
7 1.2 garbled * This code is derived from software contributed to The NetBSD Foundation
8 1.2 garbled * by Tim Rightnour
9 1.2 garbled *
10 1.2 garbled * Redistribution and use in source and binary forms, with or without
11 1.2 garbled * modification, are permitted provided that the following conditions
12 1.2 garbled * are met:
13 1.2 garbled * 1. Redistributions of source code must retain the above copyright
14 1.2 garbled * notice, this list of conditions and the following disclaimer.
15 1.2 garbled * 2. Redistributions in binary form must reproduce the above copyright
16 1.2 garbled * notice, this list of conditions and the following disclaimer in the
17 1.2 garbled * documentation and/or other materials provided with the distribution.
18 1.2 garbled * 3. All advertising materials mentioning features or use of this software
19 1.2 garbled * must display the following acknowledgement:
20 1.2 garbled * This product includes software developed by the NetBSD
21 1.2 garbled * Foundation, Inc. and its contributors.
22 1.2 garbled * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.2 garbled * contributors may be used to endorse or promote products derived
24 1.2 garbled * from this software without specific prior written permission.
25 1.2 garbled *
26 1.2 garbled * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.2 garbled * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.2 garbled * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.2 garbled * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.2 garbled * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.2 garbled * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.2 garbled * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.2 garbled * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.2 garbled * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.2 garbled * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.2 garbled * POSSIBILITY OF SUCH DAMAGE.
37 1.2 garbled */
38 1.2 garbled
39 1.2 garbled /*
40 1.2 garbled * Generic OFW routines for pci_machdep
41 1.2 garbled */
42 1.2 garbled
43 1.2 garbled #include <sys/cdefs.h>
44 1.11 phx __KERNEL_RCSID(0, "$NetBSD: pci_machdep_ofw.c,v 1.11 2008/02/23 21:11:22 phx Exp $");
45 1.2 garbled
46 1.2 garbled #include <sys/types.h>
47 1.2 garbled #include <sys/param.h>
48 1.2 garbled #include <sys/time.h>
49 1.2 garbled #include <sys/systm.h>
50 1.2 garbled #include <sys/errno.h>
51 1.2 garbled #include <sys/device.h>
52 1.2 garbled #include <sys/malloc.h>
53 1.2 garbled
54 1.2 garbled #include <uvm/uvm_extern.h>
55 1.2 garbled
56 1.2 garbled #include <machine/bus.h>
57 1.2 garbled
58 1.2 garbled #include <machine/autoconf.h>
59 1.2 garbled #include <machine/pio.h>
60 1.2 garbled #include <machine/intr.h>
61 1.2 garbled
62 1.2 garbled #include <dev/pci/pcivar.h>
63 1.2 garbled #include <dev/pci/pcireg.h>
64 1.2 garbled #include <dev/pci/ppbreg.h>
65 1.2 garbled #include <dev/pci/pcidevs.h>
66 1.2 garbled #include <dev/pci/pciconf.h>
67 1.2 garbled
68 1.2 garbled #include <dev/ofw/openfirm.h>
69 1.2 garbled #include <dev/ofw/ofw_pci.h>
70 1.2 garbled
71 1.2 garbled pcitag_t genppc_pci_indirect_make_tag(void *, int, int, int);
72 1.2 garbled void genppc_pci_indirect_decompose_tag(void *, pcitag_t, int *, int *, int *);
73 1.2 garbled
74 1.2 garbled ofw_pic_node_t picnodes[8];
75 1.2 garbled int nrofpics = 0;
76 1.2 garbled
77 1.2 garbled int
78 1.2 garbled genofw_find_picnode(int node)
79 1.2 garbled {
80 1.2 garbled int i;
81 1.2 garbled
82 1.2 garbled for (i = 0; i < 8; i++)
83 1.2 garbled if (node == picnodes[i].node)
84 1.2 garbled return i;
85 1.2 garbled return -1;
86 1.2 garbled }
87 1.2 garbled
88 1.2 garbled void
89 1.2 garbled genofw_find_ofpics(int startnode)
90 1.2 garbled {
91 1.8 garbled int node, iparent, child, iranges[6], irgot=0, i;
92 1.8 garbled uint32_t reg[12];
93 1.2 garbled char name[32];
94 1.2 garbled
95 1.2 garbled for (node = startnode; node; node = OF_peer(node)) {
96 1.2 garbled if ((child = OF_child(node)) != 0)
97 1.2 garbled genofw_find_ofpics(child);
98 1.2 garbled memset(name, 0, sizeof(name));
99 1.2 garbled if (OF_getprop(node, "name", name, sizeof(name)) == -1)
100 1.2 garbled continue;
101 1.2 garbled if (strncmp(name, "interrupt-controller", 20) == 0)
102 1.2 garbled goto foundic;
103 1.3 garbled
104 1.2 garbled if (OF_getprop(node, "interrupt-controller", name,
105 1.2 garbled sizeof(name)) > -1)
106 1.2 garbled goto foundic;
107 1.3 garbled
108 1.3 garbled if (OF_getprop(node, "device_type", name, sizeof(name)) == -1)
109 1.2 garbled continue;
110 1.2 garbled if (strncmp(name, "interrupt-controller", 20) == 0)
111 1.2 garbled goto foundic;
112 1.3 garbled
113 1.3 garbled /* if we didn't find one, skip to the next */
114 1.3 garbled continue;
115 1.2 garbled foundic:
116 1.2 garbled picnodes[nrofpics].node = node;
117 1.2 garbled if (OF_getprop(node, "interrupt-parent", &iparent,
118 1.2 garbled sizeof(iparent)) == sizeof(iparent))
119 1.2 garbled picnodes[nrofpics].parent = iparent;
120 1.2 garbled if (OF_getprop(node, "#interrupt-cells", &iparent,
121 1.2 garbled sizeof(iparent)) == sizeof(iparent))
122 1.2 garbled picnodes[nrofpics].cells = iparent;
123 1.2 garbled else
124 1.2 garbled picnodes[nrofpics].cells = 1;
125 1.8 garbled
126 1.8 garbled picnodes[nrofpics].intrs = 0;
127 1.8 garbled irgot = OF_getprop(node, "interrupt-ranges", iranges,
128 1.8 garbled sizeof(int)*6); /* XXX is this ok? */
129 1.8 garbled if (irgot >= sizeof(int)) {
130 1.8 garbled for (i=0; i < irgot/4; i++)
131 1.8 garbled if (!picnodes[nrofpics].intrs)
132 1.8 garbled picnodes[nrofpics].intrs = iranges[i];
133 1.8 garbled }
134 1.8 garbled
135 1.8 garbled irgot = OF_getprop(node, "reg", reg, sizeof(reg));
136 1.8 garbled
137 1.8 garbled if (!picnodes[nrofpics].intrs)
138 1.2 garbled picnodes[nrofpics].intrs = 16;
139 1.8 garbled
140 1.2 garbled if (nrofpics > 0)
141 1.2 garbled picnodes[nrofpics].offset = picnodes[nrofpics-1].offset
142 1.2 garbled + picnodes[nrofpics-1].intrs;
143 1.2 garbled else
144 1.2 garbled picnodes[nrofpics].offset = 0;
145 1.3 garbled OF_getprop(node, "device_type", name, sizeof(name));
146 1.2 garbled if (strcmp(name, "open-pic") == 0)
147 1.2 garbled picnodes[nrofpics].type = PICNODE_TYPE_OPENPIC;
148 1.2 garbled if (strcmp(name, "interrupt-controller") == 0) {
149 1.2 garbled OF_getprop(node, "compatible", name, sizeof(name));
150 1.8 garbled if (strcmp(name, "heathrow") == 0)
151 1.2 garbled picnodes[nrofpics].type = PICNODE_TYPE_HEATHROW;
152 1.10 garbled if (strcmp(name, "pnpPNP,0") == 0)
153 1.10 garbled picnodes[nrofpics].type = PICNODE_TYPE_8259;
154 1.8 garbled if (strcmp(name, "chrp,iic") == 0) {
155 1.2 garbled picnodes[nrofpics].type = PICNODE_TYPE_8259;
156 1.8 garbled if (irgot >= 9 * sizeof(uint32_t) &&
157 1.8 garbled reg[7] == 0x4d0)
158 1.8 garbled picnodes[nrofpics].type =
159 1.8 garbled PICNODE_TYPE_IVR;
160 1.8 garbled }
161 1.2 garbled }
162 1.3 garbled if (strlen(name) == 0) {
163 1.3 garbled /* probably a Pegasos, assume 8259 */
164 1.3 garbled picnodes[nrofpics].type = PICNODE_TYPE_8259;
165 1.3 garbled }
166 1.2 garbled nrofpics++;
167 1.2 garbled }
168 1.2 garbled }
169 1.2 garbled
170 1.2 garbled /* Fix up the various picnode offsets */
171 1.2 garbled void
172 1.2 garbled genofw_fixup_picnode_offsets(void)
173 1.2 garbled {
174 1.2 garbled int i, curoff;
175 1.2 garbled
176 1.2 garbled curoff=0;
177 1.2 garbled
178 1.2 garbled for (i=0; i < nrofpics; i++) {
179 1.8 garbled if (picnodes[i].type == PICNODE_TYPE_8259 ||
180 1.8 garbled picnodes[i].type == PICNODE_TYPE_IVR) {
181 1.2 garbled picnodes[i].offset = 0;
182 1.2 garbled curoff = picnodes[i].intrs;
183 1.2 garbled }
184 1.2 garbled }
185 1.2 garbled for (i=0; i < nrofpics; i++) {
186 1.2 garbled /* now skip the 8259 */
187 1.2 garbled if (picnodes[i].type == PICNODE_TYPE_8259)
188 1.2 garbled continue;
189 1.8 garbled if (picnodes[i].type == PICNODE_TYPE_IVR)
190 1.8 garbled continue;
191 1.8 garbled
192 1.2 garbled picnodes[i].offset = curoff;
193 1.2 garbled curoff += picnodes[i].intrs;
194 1.2 garbled }
195 1.2 garbled }
196 1.2 garbled
197 1.2 garbled /* we are given a pci devnode, and dig from there */
198 1.2 garbled void
199 1.4 garbled genofw_setup_pciintr_map(void *v, struct genppc_pci_chipset_businfo *pbi,
200 1.4 garbled int pcinode)
201 1.2 garbled {
202 1.2 garbled int node;
203 1.2 garbled u_int32_t map[160];
204 1.2 garbled int parent, len;
205 1.4 garbled int curdev, foundirqs=0;
206 1.2 garbled int i, reclen, nrofpcidevs=0;
207 1.2 garbled u_int32_t acells, icells, pcells;
208 1.2 garbled prop_dictionary_t dict;
209 1.2 garbled prop_dictionary_t sub=0;
210 1.4 garbled pci_chipset_tag_t pc = (pci_chipset_tag_t)v;
211 1.2 garbled
212 1.2 garbled len = OF_getprop(pcinode, "interrupt-map", map, sizeof(map));
213 1.2 garbled if (len == -1)
214 1.2 garbled goto nomap;
215 1.2 garbled
216 1.2 garbled if (OF_getprop(pcinode, "#address-cells", &acells,
217 1.2 garbled sizeof(acells)) == -1)
218 1.2 garbled acells = 1;
219 1.2 garbled if (OF_getprop(pcinode, "#interrupt-cells", &icells,
220 1.2 garbled sizeof(icells)) == -1)
221 1.2 garbled icells = 1;
222 1.2 garbled
223 1.8 garbled parent = map[acells+icells];
224 1.2 garbled if (OF_getprop(parent, "#interrupt-cells", &pcells,
225 1.2 garbled sizeof(pcells)) == -1)
226 1.2 garbled pcells = 1;
227 1.2 garbled
228 1.2 garbled reclen = acells+pcells+icells+1;
229 1.2 garbled nrofpcidevs = len / (reclen * sizeof(int));
230 1.2 garbled
231 1.2 garbled dict = prop_dictionary_create_with_capacity(nrofpcidevs*2);
232 1.2 garbled KASSERT(dict != NULL);
233 1.2 garbled
234 1.2 garbled curdev = -1;
235 1.2 garbled prop_dictionary_set(pbi->pbi_properties, "ofw-pci-intrmap", dict);
236 1.2 garbled for (i = 0; i < nrofpcidevs; i++) {
237 1.2 garbled prop_number_t intr_num;
238 1.8 garbled int dev, pin, pic, func;
239 1.2 garbled char key[20];
240 1.2 garbled
241 1.2 garbled pic = genofw_find_picnode(map[i*reclen + acells + icells]);
242 1.2 garbled KASSERT(pic != -1);
243 1.2 garbled dev = (map[i*reclen] >> 8) / 0x8;
244 1.8 garbled func = (map[i*reclen] >> 8) % 0x8;
245 1.2 garbled if (curdev != dev)
246 1.2 garbled sub = prop_dictionary_create_with_capacity(4);
247 1.2 garbled pin = map[i*reclen + acells];
248 1.2 garbled intr_num = prop_number_create_integer(map[i*reclen + acells + icells + 1] + picnodes[pic].offset);
249 1.8 garbled sprintf(key, "pin-%c", 'A' + (pin-1));
250 1.2 garbled prop_dictionary_set(sub, key, intr_num);
251 1.2 garbled prop_object_release(intr_num);
252 1.2 garbled /* should we care about level? */
253 1.2 garbled
254 1.8 garbled sprintf(key, "devfunc-%d", dev*0x8 + func);
255 1.2 garbled prop_dictionary_set(dict, key, sub);
256 1.2 garbled if (curdev != dev) {
257 1.2 garbled prop_object_release(sub);
258 1.2 garbled curdev = dev;
259 1.2 garbled }
260 1.2 garbled }
261 1.2 garbled /* the mapping is complete */
262 1.2 garbled prop_object_release(dict);
263 1.8 garbled aprint_debug("%s\n", prop_dictionary_externalize(pbi->pbi_properties));
264 1.2 garbled return;
265 1.2 garbled
266 1.2 garbled nomap:
267 1.2 garbled /* so, we have one of those annoying machines that doesn't provide
268 1.2 garbled * a nice simple map of interrupts. We get to do this the hard
269 1.2 garbled * way instead. Lucky us.
270 1.2 garbled */
271 1.2 garbled for (node = OF_child(pcinode), nrofpcidevs=0; node;
272 1.2 garbled node = OF_peer(node))
273 1.2 garbled nrofpcidevs++;
274 1.2 garbled dict = prop_dictionary_create_with_capacity(nrofpcidevs*2);
275 1.2 garbled KASSERT(dict != NULL);
276 1.2 garbled prop_dictionary_set(pbi->pbi_properties, "ofw-pci-intrmap", dict);
277 1.2 garbled
278 1.2 garbled for (node = OF_child(pcinode); node; node = OF_peer(node)) {
279 1.2 garbled uint32_t irqs[4], reg[5];
280 1.2 garbled prop_number_t intr_num;
281 1.8 garbled int dev, pin, func;
282 1.2 garbled char key[20];
283 1.2 garbled
284 1.2 garbled /* walk the bus looking for pci devices and map them */
285 1.2 garbled if (OF_getprop(node, "AAPL,interrupts", irqs, 4) > 0) {
286 1.2 garbled dev = 0;
287 1.8 garbled if (OF_getprop(node, "reg", reg, 5) > 0) {
288 1.2 garbled dev = ((reg[0] & 0x0000ff00) >> 8) / 0x8;
289 1.8 garbled func = ((reg[0] & 0x0000ff00) >> 8) % 0x8;
290 1.8 garbled } else if (OF_getprop(node, "assigned-addresses",
291 1.8 garbled reg, 5) > 0) {
292 1.2 garbled dev = ((reg[0] & 0x0000ff00) >> 8) / 0x8;
293 1.8 garbled func = ((reg[0] & 0x0000ff00) >> 8) % 0x8;
294 1.8 garbled }
295 1.2 garbled if (dev == 0) {
296 1.2 garbled aprint_error("cannot figure out device num "
297 1.2 garbled "for node 0x%x\n", node);
298 1.2 garbled continue;
299 1.2 garbled }
300 1.2 garbled sub = prop_dictionary_create_with_capacity(4);
301 1.2 garbled if (OF_getprop(node, "interrupts", &pin, 4) < 0)
302 1.2 garbled pin = 1;
303 1.2 garbled intr_num = prop_number_create_integer(irqs[0]);
304 1.8 garbled sprintf(key, "pin-%c", 'A' + (pin-1));
305 1.2 garbled prop_dictionary_set(sub, key, intr_num);
306 1.2 garbled prop_object_release(intr_num);
307 1.8 garbled sprintf(key, "devfunc-%d", dev*0x8 + func);
308 1.2 garbled prop_dictionary_set(dict, key, sub);
309 1.2 garbled prop_object_release(sub);
310 1.4 garbled foundirqs++;
311 1.4 garbled }
312 1.4 garbled }
313 1.4 garbled if (foundirqs)
314 1.4 garbled return;
315 1.4 garbled
316 1.4 garbled /*
317 1.4 garbled * If we got this far, we have a super-annoying OFW.
318 1.4 garbled * They didn't bother to fill in any interrupt properties anywhere,
319 1.4 garbled * so we pray that they filled in the ones on the pci devices.
320 1.4 garbled */
321 1.4 garbled for (node = OF_child(pcinode); node; node = OF_peer(node)) {
322 1.4 garbled uint32_t reg[5], irq;
323 1.4 garbled prop_number_t intr_num;
324 1.4 garbled pcitag_t tag;
325 1.4 garbled int dev, pin, func;
326 1.4 garbled char key[20];
327 1.4 garbled
328 1.4 garbled if (OF_getprop(node, "reg", reg, 5) > 0) {
329 1.4 garbled dev = ((reg[0] & 0x0000ff00) >> 8) / 0x8;
330 1.4 garbled func = ((reg[0] & 0x0000ff00) >> 8) % 0x8;
331 1.4 garbled
332 1.4 garbled tag = pci_make_tag(pc, pc->pc_bus, dev, func);
333 1.4 garbled irq = PCI_INTERRUPT_LINE(pci_conf_read(pc, tag,
334 1.4 garbled PCI_INTERRUPT_REG));
335 1.4 garbled if (irq == 255)
336 1.4 garbled irq = 0;
337 1.4 garbled
338 1.4 garbled sub = prop_dictionary_create_with_capacity(4);
339 1.4 garbled if (OF_getprop(node, "interrupts", &pin, 4) < 0)
340 1.4 garbled pin = 1;
341 1.4 garbled intr_num = prop_number_create_integer(irq);
342 1.5 garbled sprintf(key, "pin-%c", 'A' + (pin-1));
343 1.4 garbled prop_dictionary_set(sub, key, intr_num);
344 1.4 garbled prop_object_release(intr_num);
345 1.4 garbled sprintf(key, "devfunc-%d", dev*0x8 + func);
346 1.4 garbled prop_dictionary_set(dict, key, sub);
347 1.4 garbled prop_object_release(sub);
348 1.2 garbled }
349 1.2 garbled }
350 1.6 garbled aprint_debug("%s\n", prop_dictionary_externalize(pbi->pbi_properties));
351 1.2 garbled }
352 1.2 garbled
353 1.2 garbled int
354 1.2 garbled genofw_find_node_by_devfunc(int startnode, int bus, int dev, int func)
355 1.2 garbled {
356 1.2 garbled int node, sz, p=0;
357 1.2 garbled uint32_t reg;
358 1.2 garbled
359 1.2 garbled for (node = startnode; node; node = p) {
360 1.2 garbled sz = OF_getprop(node, "reg", ®, sizeof(reg));
361 1.2 garbled if (sz != sizeof(reg))
362 1.2 garbled continue;
363 1.2 garbled if (OFW_PCI_PHYS_HI_BUS(reg) == bus &&
364 1.2 garbled OFW_PCI_PHYS_HI_DEVICE(reg) == dev &&
365 1.2 garbled OFW_PCI_PHYS_HI_FUNCTION(reg) == func)
366 1.2 garbled return node;
367 1.2 garbled if ((p = OF_child(node)))
368 1.2 garbled continue;
369 1.2 garbled while (node) {
370 1.2 garbled if ((p = OF_peer(node)))
371 1.2 garbled break;
372 1.2 garbled node = OF_parent(node);
373 1.2 garbled }
374 1.2 garbled }
375 1.2 garbled /* couldn't find it */
376 1.2 garbled return -1;
377 1.2 garbled }
378 1.2 garbled
379 1.2 garbled int
380 1.2 garbled genofw_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
381 1.2 garbled {
382 1.2 garbled struct genppc_pci_chipset_businfo *pbi;
383 1.2 garbled prop_dictionary_t dict, devsub;
384 1.2 garbled prop_object_t pinsub;
385 1.2 garbled prop_number_t pbus;
386 1.4 garbled int busno, bus, pin, line, swiz, dev, origdev, func, i;
387 1.2 garbled char key[20];
388 1.2 garbled
389 1.2 garbled pin = pa->pa_intrpin;
390 1.2 garbled line = pa->pa_intrline;
391 1.2 garbled bus = busno = pa->pa_bus;
392 1.2 garbled swiz = pa->pa_intrswiz;
393 1.2 garbled origdev = dev = pa->pa_device;
394 1.4 garbled func = pa->pa_function;
395 1.2 garbled i = 0;
396 1.2 garbled
397 1.2 garbled pbi = SIMPLEQ_FIRST(&pa->pa_pc->pc_pbi);
398 1.2 garbled while (busno--)
399 1.2 garbled pbi = SIMPLEQ_NEXT(pbi, next);
400 1.2 garbled KASSERT(pbi != NULL);
401 1.2 garbled
402 1.2 garbled dict = prop_dictionary_get(pbi->pbi_properties, "ofw-pci-intrmap");
403 1.2 garbled
404 1.2 garbled if (dict != NULL)
405 1.2 garbled i = prop_dictionary_count(dict);
406 1.2 garbled
407 1.2 garbled if (dict == NULL || i == 0) {
408 1.2 garbled /* We have an unmapped bus, now it gets hard */
409 1.2 garbled pbus = prop_dictionary_get(pbi->pbi_properties,
410 1.2 garbled "ofw-pcibus-parent");
411 1.2 garbled if (pbus == NULL)
412 1.2 garbled goto bad;
413 1.2 garbled busno = prop_number_integer_value(pbus);
414 1.2 garbled pbus = prop_dictionary_get(pbi->pbi_properties,
415 1.2 garbled "ofw-pcibus-rawdevnum");
416 1.2 garbled dev = prop_number_integer_value(pbus);
417 1.2 garbled
418 1.2 garbled /* now that we know the parent bus, we need to find it's pbi */
419 1.2 garbled pbi = SIMPLEQ_FIRST(&pa->pa_pc->pc_pbi);
420 1.2 garbled while (busno--)
421 1.2 garbled pbi = SIMPLEQ_NEXT(pbi, next);
422 1.2 garbled KASSERT(pbi != NULL);
423 1.2 garbled
424 1.2 garbled /* swizzle the pin */
425 1.2 garbled pin = ((pin + origdev - 1) & 3) + 1;
426 1.2 garbled
427 1.2 garbled /* now we have the pbi, ask for dict again */
428 1.2 garbled dict = prop_dictionary_get(pbi->pbi_properties,
429 1.2 garbled "ofw-pci-intrmap");
430 1.2 garbled if (dict == NULL)
431 1.2 garbled goto bad;
432 1.2 garbled }
433 1.2 garbled
434 1.2 garbled /* No IRQ used. */
435 1.2 garbled if (pin == 0)
436 1.2 garbled goto bad;
437 1.2 garbled if (pin > 4) {
438 1.2 garbled aprint_error("pci_intr_map: bad interrupt pin %d\n", pin);
439 1.2 garbled goto bad;
440 1.2 garbled }
441 1.2 garbled
442 1.4 garbled sprintf(key, "devfunc-%d", dev*0x8 + func);
443 1.2 garbled devsub = prop_dictionary_get(dict, key);
444 1.2 garbled if (devsub == NULL)
445 1.2 garbled goto bad;
446 1.2 garbled sprintf(key, "pin-%c", 'A' + (pin-1));
447 1.2 garbled pinsub = prop_dictionary_get(devsub, key);
448 1.2 garbled if (pinsub == NULL)
449 1.2 garbled goto bad;
450 1.2 garbled line = prop_number_integer_value(pinsub);
451 1.2 garbled
452 1.2 garbled if (line == 0 || line == 255) {
453 1.2 garbled aprint_error("pci_intr_map: no mapping for pin %c\n",'@' + pin);
454 1.2 garbled goto bad;
455 1.2 garbled }
456 1.2 garbled
457 1.2 garbled *ihp = line;
458 1.2 garbled return 0;
459 1.2 garbled
460 1.2 garbled bad:
461 1.2 garbled *ihp = -1;
462 1.2 garbled return 1;
463 1.2 garbled }
464 1.2 garbled
465 1.2 garbled int
466 1.2 garbled genofw_pci_conf_hook(pci_chipset_tag_t pct, int bus, int dev, int func,
467 1.2 garbled pcireg_t id)
468 1.2 garbled {
469 1.2 garbled struct genppc_pci_chipset_businfo *pbi;
470 1.2 garbled prop_number_t pbus;
471 1.2 garbled pcitag_t tag;
472 1.2 garbled pcireg_t class;
473 1.2 garbled int node;
474 1.2 garbled
475 1.2 garbled /* We have already mapped MPIC's if we have them, so leave them alone */
476 1.2 garbled if (PCI_VENDOR(id) == PCI_VENDOR_IBM &&
477 1.2 garbled PCI_PRODUCT(id) == PCI_PRODUCT_IBM_MPIC2)
478 1.2 garbled return 0;
479 1.2 garbled
480 1.2 garbled if (PCI_VENDOR(id) == PCI_VENDOR_IBM &&
481 1.2 garbled PCI_PRODUCT(id) == PCI_PRODUCT_IBM_MPIC)
482 1.2 garbled return 0;
483 1.2 garbled
484 1.2 garbled /* I highly doubt there are any CHRP ravens, but just in case */
485 1.2 garbled if (PCI_VENDOR(id) == PCI_VENDOR_MOT &&
486 1.2 garbled PCI_PRODUCT(id) == PCI_PRODUCT_MOT_RAVEN)
487 1.2 garbled return (PCI_CONF_ALL & ~PCI_CONF_MAP_MEM);
488 1.2 garbled
489 1.7 mrg /*
490 1.7 mrg * Pegasos2 specific stuff.
491 1.7 mrg */
492 1.7 mrg if (strncmp(model_name, "Pegasos2", 8) == 0) {
493 1.7 mrg
494 1.11 phx /* never reconfigure the MV64361 host bridge */
495 1.11 phx if (PCI_VENDOR(id) == PCI_VENDOR_MARVELL &&
496 1.11 phx PCI_PRODUCT(id) == PCI_PRODUCT_MARVELL_GT64360)
497 1.11 phx return 0;
498 1.11 phx
499 1.7 mrg /* we want to leave viaide(4) alone */
500 1.7 mrg if (PCI_VENDOR(id) == PCI_VENDOR_VIATECH &&
501 1.7 mrg PCI_PRODUCT(id) == PCI_PRODUCT_VIATECH_VT82C586A_IDE)
502 1.7 mrg return 0;
503 1.7 mrg
504 1.9 garbled /* leave the audio IO alone */
505 1.7 mrg if (PCI_VENDOR(id) == PCI_VENDOR_VIATECH &&
506 1.9 garbled PCI_PRODUCT(id) == PCI_PRODUCT_VIATECH_VT82C686A_AC97)
507 1.9 garbled return (PCI_CONF_ALL & ~PCI_CONF_MAP_IO);
508 1.9 garbled
509 1.7 mrg }
510 1.9 garbled
511 1.9 garbled tag = pci_make_tag(pct, bus, dev, func);
512 1.9 garbled class = pci_conf_read(pct, tag, PCI_CLASS_REG);
513 1.7 mrg
514 1.9 garbled /* leave video cards alone */
515 1.9 garbled if (PCI_CLASS(class) == PCI_CLASS_DISPLAY)
516 1.9 garbled return 0;
517 1.9 garbled
518 1.2 garbled /* NOTE, all device specific stuff must be above this line */
519 1.2 garbled /* don't do this on the primary host bridge */
520 1.2 garbled if (bus == 0 && dev == 0 && func == 0)
521 1.2 garbled return PCI_CONF_DEFAULT;
522 1.2 garbled
523 1.2 garbled /*
524 1.2 garbled * PCI bridges have special needs. We need to discover where they
525 1.2 garbled * came from, and wire them appropriately.
526 1.2 garbled */
527 1.2 garbled if (PCI_CLASS(class) == PCI_CLASS_BRIDGE &&
528 1.2 garbled PCI_SUBCLASS(class) == PCI_SUBCLASS_BRIDGE_PCI) {
529 1.2 garbled pbi = malloc(sizeof(struct genppc_pci_chipset_businfo),
530 1.2 garbled M_DEVBUF, M_NOWAIT);
531 1.2 garbled KASSERT(pbi != NULL);
532 1.2 garbled pbi->pbi_properties = prop_dictionary_create();
533 1.2 garbled KASSERT(pbi->pbi_properties != NULL);
534 1.2 garbled node = genofw_find_node_by_devfunc(pct->pc_node, bus, dev,
535 1.2 garbled func);
536 1.2 garbled if (node == -1) {
537 1.2 garbled aprint_error("Cannot find node for device "
538 1.2 garbled "bus %d dev %d func %d\n", bus, dev, func);
539 1.2 garbled prop_object_release(pbi->pbi_properties);
540 1.2 garbled free(pbi, M_DEVBUF);
541 1.2 garbled return (PCI_CONF_DEFAULT);
542 1.2 garbled }
543 1.4 garbled genofw_setup_pciintr_map((void *)pct, pbi, node);
544 1.2 garbled
545 1.2 garbled /* record the parent bus, and the parent device number */
546 1.2 garbled pbus = prop_number_create_integer(bus);
547 1.2 garbled prop_dictionary_set(pbi->pbi_properties, "ofw-pcibus-parent",
548 1.2 garbled pbus);
549 1.2 garbled prop_object_release(pbus);
550 1.2 garbled pbus = prop_number_create_integer(dev);
551 1.2 garbled prop_dictionary_set(pbi->pbi_properties, "ofw-pcibus-rawdevnum",
552 1.2 garbled pbus);
553 1.2 garbled prop_object_release(pbus);
554 1.2 garbled
555 1.2 garbled SIMPLEQ_INSERT_TAIL(&pct->pc_pbi, pbi, next);
556 1.2 garbled }
557 1.2 garbled
558 1.2 garbled return (PCI_CONF_DEFAULT);
559 1.2 garbled }
560