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