1 /* $OpenBSD: pci_bus_fixup.c,v 1.9 2006/08/18 22:18:18 kettenis Exp $ */ 2 /* $NetBSD: pci_bus_fixup.c,v 1.1 1999/11/17 07:32:58 thorpej Exp $ */ 3 4 /* 5 * Copyright (c) 1999, by UCHIYAMA Yasushi 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. The name of the developer may NOT be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 /* 30 * PCI bus renumbering support. 31 */ 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/kernel.h> 36 #include <sys/device.h> 37 38 #include <machine/bus.h> 39 40 #include <dev/pci/pcireg.h> 41 #include <dev/pci/pcivar.h> 42 #include <dev/pci/pcidevs.h> 43 #include <dev/pci/ppbreg.h> 44 45 #include <i386/pci/pcibiosvar.h> 46 47 int pci_bus_check(pci_chipset_tag_t, int); 48 int pci_bus_assign(pci_chipset_tag_t, int); 49 void pcibus_print_devid(pci_chipset_tag_t, pcitag_t); 50 51 int 52 pci_bus_check(pci_chipset_tag_t pc, int bus) 53 { 54 int device, maxdevs, function, nfuncs, bus_max, bus_sub; 55 const struct pci_quirkdata *qd; 56 pcireg_t reg; 57 pcitag_t tag; 58 59 bus_max = bus; 60 61 maxdevs = pci_bus_maxdevs(pc, bus); 62 for (device = 0; device < maxdevs; device++) { 63 tag = pci_make_tag(pc, bus, device, 0); 64 reg = pci_conf_read(pc, tag, PCI_ID_REG); 65 66 /* can't be that many */ 67 if (bus_max == 255) 68 break; 69 70 /* Invalid vendor ID value? */ 71 if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID) 72 continue; 73 /* XXX Not invalid, but we've done this ~forever. */ 74 if (PCI_VENDOR(reg) == 0) 75 continue; 76 77 qd = pci_lookup_quirkdata(PCI_VENDOR(reg), PCI_PRODUCT(reg)); 78 79 reg = pci_conf_read(pc, tag, PCI_BHLC_REG); 80 if (PCI_HDRTYPE_MULTIFN(reg) || 81 (qd != NULL && 82 (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0)) 83 nfuncs = 8; 84 else 85 nfuncs = 1; 86 87 for (function = 0; function < nfuncs; function++) { 88 tag = pci_make_tag(pc, bus, device, function); 89 reg = pci_conf_read(pc, tag, PCI_ID_REG); 90 91 /* Invalid vendor ID value? */ 92 if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID) 93 continue; 94 /* XXX Not invalid, but we've done this ~forever. */ 95 if (PCI_VENDOR(reg) == 0) 96 continue; 97 98 reg = pci_conf_read(pc, tag, PCI_CLASS_REG); 99 if (PCI_CLASS(reg) == PCI_CLASS_BRIDGE && 100 (PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_PCI || 101 PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_CARDBUS)) { 102 103 reg = pci_conf_read(pc, tag, PPB_REG_BUSINFO); 104 if (PPB_BUSINFO_PRIMARY(reg) != bus) { 105 if (pcibios_flags & PCIBIOS_VERBOSE) { 106 pcibus_print_devid(pc, tag); 107 printf("Mismatched primary bus: " 108 "primary %d, secondary %d, " 109 "subordinate %d\n", 110 PPB_BUSINFO_PRIMARY(reg), 111 PPB_BUSINFO_SECONDARY(reg), 112 PPB_BUSINFO_SUBORDINATE(reg)); 113 } 114 return (-1); 115 } 116 if (PPB_BUSINFO_SECONDARY(reg) <= bus) { 117 if (pcibios_flags & PCIBIOS_VERBOSE) { 118 pcibus_print_devid(pc, tag); 119 printf("Incorrect secondary bus: " 120 "primary %d, secondary %d, " 121 "subordinate %d\n", 122 PPB_BUSINFO_PRIMARY(reg), 123 PPB_BUSINFO_SECONDARY(reg), 124 PPB_BUSINFO_SUBORDINATE(reg)); 125 } 126 return (-1); 127 } 128 129 /* Scan subordinate bus. */ 130 bus_sub = pci_bus_check(pc, 131 PPB_BUSINFO_SECONDARY(reg)); 132 if (bus_sub == -1) 133 return (-1); 134 135 if (PPB_BUSINFO_SUBORDINATE(reg) < bus_sub) { 136 if (pcibios_flags & PCIBIOS_VERBOSE) { 137 pcibus_print_devid(pc, tag); 138 printf("Incorrect subordinate bus %d: " 139 "primary %d, secondary %d, " 140 "subordinate %d\n", bus_sub, 141 PPB_BUSINFO_PRIMARY(reg), 142 PPB_BUSINFO_SECONDARY(reg), 143 PPB_BUSINFO_SUBORDINATE(reg)); 144 } 145 return (-1); 146 } 147 148 bus_max = (bus_sub > bus_max) ? 149 bus_sub : bus_max; 150 } 151 } 152 } 153 154 return (bus_max); /* last # of subordinate bus */ 155 } 156 157 int 158 pci_bus_assign(pci_chipset_tag_t pc, int bus) 159 { 160 static int bridge_cnt; 161 int bridge, device, maxdevs, function, nfuncs, bus_max, bus_sub; 162 const struct pci_quirkdata *qd; 163 pcireg_t reg; 164 pcitag_t tag; 165 166 bus_max = bus; 167 168 maxdevs = pci_bus_maxdevs(pc, bus); 169 for (device = 0; device < maxdevs; device++) { 170 tag = pci_make_tag(pc, bus, device, 0); 171 reg = pci_conf_read(pc, tag, PCI_ID_REG); 172 173 /* can't be that many */ 174 if (bus_max == 255) 175 break; 176 177 /* Invalid vendor ID value? */ 178 if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID) 179 continue; 180 /* XXX Not invalid, but we've done this ~forever. */ 181 if (PCI_VENDOR(reg) == 0) 182 continue; 183 184 qd = pci_lookup_quirkdata(PCI_VENDOR(reg), PCI_PRODUCT(reg)); 185 186 reg = pci_conf_read(pc, tag, PCI_BHLC_REG); 187 if (PCI_HDRTYPE_MULTIFN(reg) || 188 (qd != NULL && 189 (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0)) 190 nfuncs = 8; 191 else 192 nfuncs = 1; 193 194 for (function = 0; function < nfuncs; function++) { 195 tag = pci_make_tag(pc, bus, device, function); 196 reg = pci_conf_read(pc, tag, PCI_ID_REG); 197 198 /* Invalid vendor ID value? */ 199 if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID) 200 continue; 201 /* XXX Not invalid, but we've done this ~forever. */ 202 if (PCI_VENDOR(reg) == 0) 203 continue; 204 205 reg = pci_conf_read(pc, tag, PCI_CLASS_REG); 206 if (PCI_CLASS(reg) == PCI_CLASS_BRIDGE && 207 (PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_PCI || 208 PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_CARDBUS)) { 209 /* Assign the bridge's secondary bus #. */ 210 bus_max++; 211 212 reg = pci_conf_read(pc, tag, PPB_REG_BUSINFO); 213 reg &= 0xff000000; 214 reg |= bus | (bus_max << 8) | (0xff << 16); 215 pci_conf_write(pc, tag, PPB_REG_BUSINFO, reg); 216 217 /* Scan subordinate bus. */ 218 bus_sub = pci_bus_assign(pc, bus_max); 219 220 /* Configure the bridge. */ 221 reg &= 0xff000000; 222 reg |= bus | (bus_max << 8) | (bus_sub << 16); 223 pci_conf_write(pc, tag, PPB_REG_BUSINFO, reg); 224 225 if (pcibios_flags & PCIBIOS_VERBOSE) { 226 /* Assign the bridge #. */ 227 bridge = bridge_cnt++; 228 229 printf("PCI bridge %d: primary %d, " 230 "secondary %d, subordinate %d\n", 231 bridge, bus, bus_max, bus_sub); 232 } 233 234 /* Next bridge's secondary bus #. */ 235 bus_max = (bus_sub > bus_max) ? 236 bus_sub : bus_max; 237 } 238 } 239 } 240 241 return (bus_max); /* last # of subordinate bus */ 242 } 243 244 int 245 pci_bus_fixup(pci_chipset_tag_t pc, int bus) 246 { 247 int bus_max; 248 249 bus_max = pci_bus_check(pc, bus); 250 if (bus_max != -1) 251 return (bus_max); 252 253 if (pcibios_flags & PCIBIOS_VERBOSE) 254 printf("PCI bus renumbering needed\n"); 255 return pci_bus_assign(pc, bus); 256 } 257 258 void 259 pcibus_print_devid(pci_chipset_tag_t pc, pcitag_t tag) 260 { 261 int bus, device, function; 262 pcireg_t id; 263 264 id = pci_conf_read(pc, tag, PCI_ID_REG); 265 pci_decompose_tag(pc, tag, &bus, &device, &function); 266 printf("%03d:%02d:%d %04x:%04x\n", bus, device, function, 267 PCI_VENDOR(id), PCI_PRODUCT(id)); 268 } 269