1 /* $OpenBSD: pchb.c,v 1.89 2014/03/26 14:41:41 mpi Exp $ */ 2 /* $NetBSD: pchb.c,v 1.65 2007/08/15 02:26:13 markd Exp $ */ 3 4 /* 5 * Copyright (c) 2000 Michael Shalayeff 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. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 26 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 * THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 /*- 30 * Copyright (c) 1996, 1998, 2000 The NetBSD Foundation, Inc. 31 * All rights reserved. 32 * 33 * This code is derived from software contributed to The NetBSD Foundation 34 * by Jason R. Thorpe. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 45 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 46 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 47 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 48 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 49 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 50 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 51 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 52 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 53 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 54 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 55 * POSSIBILITY OF SUCH DAMAGE. 56 */ 57 58 #include <sys/param.h> 59 #include <sys/systm.h> 60 #include <sys/device.h> 61 #include <sys/timeout.h> 62 #include <sys/rwlock.h> 63 64 #include <machine/bus.h> 65 66 #include <dev/pci/pcivar.h> 67 #include <dev/pci/pcireg.h> 68 #include <dev/pci/pcidevs.h> 69 70 #include <dev/pci/agpvar.h> 71 #include <dev/pci/ppbreg.h> 72 73 #include <dev/rndvar.h> 74 75 #include <dev/ic/i82802reg.h> 76 77 #include "agp.h" 78 79 #define PCISET_INTEL_BRIDGETYPE_MASK 0x3 80 #define PCISET_INTEL_TYPE_COMPAT 0x1 81 #define PCISET_INTEL_TYPE_AUX 0x2 82 83 #define PCISET_INTEL_BUSCONFIG_REG 0x48 84 #define PCISET_INTEL_BRIDGE_NUMBER(reg) (((reg) >> 8) & 0xff) 85 #define PCISET_INTEL_PCI_BUS_NUMBER(reg) (((reg) >> 16) & 0xff) 86 87 #define PCISET_INTEL_SDRAMC_REG 0x74 88 #define PCISET_INTEL_SDRAMC_IPDLT (1 << 24) 89 90 /* XXX should be in dev/ic/i82424{reg.var}.h */ 91 #define I82424_CPU_BCTL_REG 0x53 92 #define I82424_PCI_BCTL_REG 0x54 93 94 #define I82424_BCTL_CPUMEM_POSTEN 0x01 95 #define I82424_BCTL_CPUPCI_POSTEN 0x02 96 #define I82424_BCTL_PCIMEM_BURSTEN 0x01 97 #define I82424_BCTL_PCI_BURSTEN 0x02 98 99 /* XXX should be in dev/ic/amd64htreg.h */ 100 #define AMD64HT_LDT0_BUS 0x94 101 #define AMD64HT_LDT0_TYPE 0x98 102 #define AMD64HT_LDT1_BUS 0xb4 103 #define AMD64HT_LDT1_TYPE 0xb8 104 #define AMD64HT_LDT2_BUS 0xd4 105 #define AMD64HT_LDT2_TYPE 0xd8 106 #define AMD64HT_LDT3_BUS 0xf4 107 #define AMD64HT_LDT3_TYPE 0xf8 108 109 #define AMD64HT_NUM_LDT 4 110 111 #define AMD64HT_LDT_TYPE_MASK 0x0000001f 112 #define AMD64HT_LDT_INIT_COMPLETE 0x00000002 113 #define AMD64HT_LDT_NC 0x00000004 114 115 #define AMD64HT_LDT_SEC_BUS_NUM(reg) (((reg) >> 8) & 0xff) 116 117 struct pchb_softc { 118 struct device sc_dev; 119 120 bus_space_tag_t sc_bt; 121 bus_space_handle_t sc_bh; 122 123 /* rng stuff */ 124 int sc_rng_active; 125 int sc_rng_ax; 126 int sc_rng_i; 127 struct timeout sc_rng_to; 128 }; 129 130 int pchbmatch(struct device *, void *, void *); 131 void pchbattach(struct device *, struct device *, void *); 132 int pchbactivate(struct device *, int); 133 134 struct cfattach pchb_ca = { 135 sizeof(struct pchb_softc), pchbmatch, pchbattach, NULL, 136 pchbactivate 137 }; 138 139 struct cfdriver pchb_cd = { 140 NULL, "pchb", DV_DULL 141 }; 142 143 int pchb_print(void *, const char *); 144 void pchb_rnd(void *); 145 void pchb_amd64ht_attach(struct device *, struct pci_attach_args *, int); 146 147 int 148 pchbmatch(struct device *parent, void *match, void *aux) 149 { 150 struct pci_attach_args *pa = aux; 151 152 #ifdef __i386__ 153 /* XXX work around broken via82x866 chipsets */ 154 const struct pci_matchid via_devices[] = { 155 { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C586_PWR }, 156 { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C596 }, 157 { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C596B_PM }, 158 { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C686A_SMB } 159 }; 160 if (pci_matchbyid(pa, via_devices, 161 sizeof(via_devices) / sizeof(via_devices[0]))) 162 return (0); 163 #endif /* __i386__ */ 164 165 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE && 166 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_HOST) 167 return (1); 168 169 return (0); 170 } 171 172 void 173 pchbattach(struct device *parent, struct device *self, void *aux) 174 { 175 struct pchb_softc *sc = (struct pchb_softc *)self; 176 struct pci_attach_args *pa = aux; 177 struct pcibus_attach_args pba; 178 pcireg_t bcreg, bir; 179 u_char bdnum, pbnum; 180 pcitag_t tag; 181 int i, r; 182 int doattach = 0; 183 184 switch (PCI_VENDOR(pa->pa_id)) { 185 case PCI_VENDOR_AMD: 186 printf("\n"); 187 switch (PCI_PRODUCT(pa->pa_id)) { 188 case PCI_PRODUCT_AMD_AMD64_0F_HT: 189 case PCI_PRODUCT_AMD_AMD64_10_HT: 190 for (i = 0; i < AMD64HT_NUM_LDT; i++) 191 pchb_amd64ht_attach(self, pa, i); 192 break; 193 } 194 break; 195 #ifdef __i386__ 196 case PCI_VENDOR_RCC: 197 { 198 /* 199 * The variable below is a bit vector representing the 200 * Serverworks busses that have already been attached. 201 * Bit 0 represents bus 0 and so forth. The initial 202 * value is 1 because we never actually want to 203 * attach bus 0 since bus 0 is the mainbus. 204 */ 205 static u_int32_t rcc_bus_visited = 1; 206 207 printf("\n"); 208 bdnum = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x44); 209 if (bdnum >= (sizeof(rcc_bus_visited) * 8) || 210 (rcc_bus_visited & (1 << bdnum))) 211 break; 212 213 rcc_bus_visited |= 1 << bdnum; 214 215 /* 216 * This host bridge has a second PCI bus. 217 * Configure it. 218 */ 219 pbnum = bdnum; 220 doattach = 1; 221 break; 222 } 223 #endif 224 case PCI_VENDOR_INTEL: 225 switch (PCI_PRODUCT(pa->pa_id)) { 226 #ifdef __i386__ 227 case PCI_PRODUCT_INTEL_82452_HB: 228 bcreg = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x40); 229 pbnum = PCISET_INTEL_BRIDGE_NUMBER(bcreg); 230 if (pbnum != 0xff) { 231 pbnum++; 232 doattach = 1; 233 } 234 break; 235 case PCI_PRODUCT_INTEL_82443BX_AGP: /* 82443BX AGP (PAC) */ 236 case PCI_PRODUCT_INTEL_82443BX_NOAGP: /* 82443BX Host-PCI (no AGP) */ 237 /* 238 * An incorrect address may be driven on the 239 * DRAM bus, resulting in memory data being 240 * fetched from the wrong location. This is 241 * the workaround. 242 */ 243 if (PCI_REVISION(pa->pa_class) < 0x3) { 244 bcreg = pci_conf_read(pa->pa_pc, pa->pa_tag, 245 PCISET_INTEL_SDRAMC_REG); 246 bcreg |= PCISET_INTEL_SDRAMC_IPDLT; 247 pci_conf_write(pa->pa_pc, pa->pa_tag, 248 PCISET_INTEL_SDRAMC_REG, bcreg); 249 } 250 break; 251 case PCI_PRODUCT_INTEL_PCI450_PB: 252 bcreg = pci_conf_read(pa->pa_pc, pa->pa_tag, 253 PCISET_INTEL_BUSCONFIG_REG); 254 bdnum = PCISET_INTEL_BRIDGE_NUMBER(bcreg); 255 pbnum = PCISET_INTEL_PCI_BUS_NUMBER(bcreg); 256 switch (bdnum & PCISET_INTEL_BRIDGETYPE_MASK) { 257 default: 258 printf(": bdnum=%x (reserved)", bdnum); 259 break; 260 case PCISET_INTEL_TYPE_COMPAT: 261 printf(": Compatibility PB (bus %d)", pbnum); 262 break; 263 case PCISET_INTEL_TYPE_AUX: 264 printf(": Auxiliary PB (bus %d)", pbnum); 265 doattach = 1; 266 } 267 break; 268 case PCI_PRODUCT_INTEL_CDC: 269 bcreg = pci_conf_read(pa->pa_pc, pa->pa_tag, 270 I82424_CPU_BCTL_REG); 271 if (bcreg & I82424_BCTL_CPUPCI_POSTEN) { 272 bcreg &= ~I82424_BCTL_CPUPCI_POSTEN; 273 pci_conf_write(pa->pa_pc, pa->pa_tag, 274 I82424_CPU_BCTL_REG, bcreg); 275 printf(": disabled CPU-PCI write posting"); 276 } 277 break; 278 case PCI_PRODUCT_INTEL_82454NX: 279 pbnum = 0; 280 switch (pa->pa_device) { 281 case 18: /* PXB 0 bus A - primary bus */ 282 break; 283 case 19: /* PXB 0 bus B */ 284 /* read SUBA0 from MIOC */ 285 tag = pci_make_tag(pa->pa_pc, 0, 16, 0); 286 bcreg = pci_conf_read(pa->pa_pc, tag, 0xd0); 287 pbnum = ((bcreg & 0x0000ff00) >> 8) + 1; 288 break; 289 case 20: /* PXB 1 bus A */ 290 /* read BUSNO1 from MIOC */ 291 tag = pci_make_tag(pa->pa_pc, 0, 16, 0); 292 bcreg = pci_conf_read(pa->pa_pc, tag, 0xd0); 293 pbnum = (bcreg & 0xff000000) >> 24; 294 break; 295 case 21: /* PXB 1 bus B */ 296 /* read SUBA1 from MIOC */ 297 tag = pci_make_tag(pa->pa_pc, 0, 16, 0); 298 bcreg = pci_conf_read(pa->pa_pc, tag, 0xd4); 299 pbnum = (bcreg & 0x000000ff) + 1; 300 break; 301 } 302 if (pbnum != 0) 303 doattach = 1; 304 break; 305 /* RNG */ 306 case PCI_PRODUCT_INTEL_82810_HB: 307 case PCI_PRODUCT_INTEL_82810_DC100_HB: 308 case PCI_PRODUCT_INTEL_82810E_HB: 309 case PCI_PRODUCT_INTEL_82815_HB: 310 case PCI_PRODUCT_INTEL_82820_HB: 311 case PCI_PRODUCT_INTEL_82840_HB: 312 case PCI_PRODUCT_INTEL_82850_HB: 313 case PCI_PRODUCT_INTEL_82860_HB: 314 #endif /* __i386__ */ 315 case PCI_PRODUCT_INTEL_82915G_HB: 316 case PCI_PRODUCT_INTEL_82945G_HB: 317 case PCI_PRODUCT_INTEL_82925X_HB: 318 case PCI_PRODUCT_INTEL_82955X_HB: 319 sc->sc_bt = pa->pa_memt; 320 if (bus_space_map(sc->sc_bt, I82802_IOBASE, 321 I82802_IOSIZE, 0, &sc->sc_bh)) 322 break; 323 324 /* probe and init rng */ 325 if (!(bus_space_read_1(sc->sc_bt, sc->sc_bh, 326 I82802_RNG_HWST) & I82802_RNG_HWST_PRESENT)) 327 break; 328 329 /* enable RNG */ 330 bus_space_write_1(sc->sc_bt, sc->sc_bh, 331 I82802_RNG_HWST, 332 bus_space_read_1(sc->sc_bt, sc->sc_bh, 333 I82802_RNG_HWST) | I82802_RNG_HWST_ENABLE); 334 335 /* see if we can read anything */ 336 for (i = 1000; i-- && 337 !(bus_space_read_1(sc->sc_bt, sc->sc_bh, 338 I82802_RNG_RNGST) & I82802_RNG_RNGST_DATAV); ) 339 DELAY(10); 340 341 if (!(bus_space_read_1(sc->sc_bt, sc->sc_bh, 342 I82802_RNG_RNGST) & I82802_RNG_RNGST_DATAV)) 343 break; 344 345 r = bus_space_read_1(sc->sc_bt, sc->sc_bh, 346 I82802_RNG_DATA); 347 348 timeout_set(&sc->sc_rng_to, pchb_rnd, sc); 349 sc->sc_rng_i = 4; 350 pchb_rnd(sc); 351 sc->sc_rng_active = 1; 352 break; 353 } 354 printf("\n"); 355 break; 356 case PCI_VENDOR_VIATECH: 357 switch (PCI_PRODUCT(pa->pa_id)) { 358 case PCI_PRODUCT_VIATECH_VT8251_PCIE_0: 359 /* 360 * Bump the host bridge into PCI-PCI bridge 361 * mode by clearing magic bit on the VLINK 362 * device. This allows us to read the bus 363 * number for the PCI bus attached to this 364 * host bridge. 365 */ 366 tag = pci_make_tag(pa->pa_pc, 0, 17, 7); 367 bcreg = pci_conf_read(pa->pa_pc, tag, 0xfc); 368 bcreg &= ~0x00000004; /* XXX Magic */ 369 pci_conf_write(pa->pa_pc, tag, 0xfc, bcreg); 370 371 bir = pci_conf_read(pa->pa_pc, 372 pa->pa_tag, PPB_REG_BUSINFO); 373 pbnum = PPB_BUSINFO_PRIMARY(bir); 374 if (pbnum > 0) 375 doattach = 1; 376 377 /* Switch back to host bridge mode. */ 378 bcreg |= 0x00000004; /* XXX Magic */ 379 pci_conf_write(pa->pa_pc, tag, 0xfc, bcreg); 380 break; 381 } 382 printf("\n"); 383 break; 384 default: 385 printf("\n"); 386 break; 387 } 388 389 #if NAGP > 0 390 /* 391 * Intel IGD have an odd interface and attach at vga, however, 392 * in that mode they don't have the AGP cap bit, so this 393 * test should be sufficient 394 */ 395 if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, 396 NULL, NULL) != 0) { 397 struct agp_attach_args aa; 398 aa.aa_busname = "agp"; 399 aa.aa_pa = pa; 400 401 config_found(self, &aa, agpdev_print); 402 } 403 #endif /* NAGP > 0 */ 404 405 if (doattach == 0) 406 return; 407 408 bzero(&pba, sizeof(pba)); 409 pba.pba_busname = "pci"; 410 pba.pba_iot = pa->pa_iot; 411 pba.pba_memt = pa->pa_memt; 412 pba.pba_dmat = pa->pa_dmat; 413 pba.pba_busex = pa->pa_busex; 414 pba.pba_domain = pa->pa_domain; 415 pba.pba_bus = pbnum; 416 pba.pba_pc = pa->pa_pc; 417 config_found(self, &pba, pchb_print); 418 } 419 420 int 421 pchbactivate(struct device *self, int act) 422 { 423 struct pchb_softc *sc = (struct pchb_softc *)self; 424 int rv = 0; 425 426 switch (act) { 427 case DVACT_RESUME: 428 /* re-enable RNG, if we have it */ 429 if (sc->sc_rng_active) 430 bus_space_write_1(sc->sc_bt, sc->sc_bh, 431 I82802_RNG_HWST, 432 bus_space_read_1(sc->sc_bt, sc->sc_bh, 433 I82802_RNG_HWST) | I82802_RNG_HWST_ENABLE); 434 rv = config_activate_children(self, act); 435 break; 436 default: 437 rv = config_activate_children(self, act); 438 break; 439 } 440 return (rv); 441 } 442 443 444 int 445 pchb_print(void *aux, const char *pnp) 446 { 447 struct pcibus_attach_args *pba = aux; 448 449 if (pnp) 450 printf("%s at %s", pba->pba_busname, pnp); 451 printf(" bus %d", pba->pba_bus); 452 return (UNCONF); 453 } 454 455 /* 456 * Should do FIPS testing as per: 457 * http://csrc.nist.gov/publications/fips/fips140-1/fips1401.pdf 458 */ 459 void 460 pchb_rnd(void *v) 461 { 462 struct pchb_softc *sc = v; 463 464 /* 465 * Don't wait for data to be ready. If it's not there, we'll check 466 * next time. 467 */ 468 if ((bus_space_read_1(sc->sc_bt, sc->sc_bh, I82802_RNG_RNGST) & 469 I82802_RNG_RNGST_DATAV)) { 470 471 sc->sc_rng_ax = (sc->sc_rng_ax << 8) | 472 bus_space_read_1(sc->sc_bt, sc->sc_bh, I82802_RNG_DATA); 473 474 if (!sc->sc_rng_i--) { 475 sc->sc_rng_i = 4; 476 add_true_randomness(sc->sc_rng_ax); 477 } 478 } 479 480 timeout_add(&sc->sc_rng_to, 1); 481 } 482 483 void 484 pchb_amd64ht_attach(struct device *self, struct pci_attach_args *pa, int i) 485 { 486 struct pcibus_attach_args pba; 487 pcireg_t type, bus; 488 int reg; 489 490 reg = AMD64HT_LDT0_TYPE + i * 0x20; 491 type = pci_conf_read(pa->pa_pc, pa->pa_tag, reg); 492 if ((type & AMD64HT_LDT_INIT_COMPLETE) == 0 || 493 (type & AMD64HT_LDT_NC) == 0) 494 return; 495 496 reg = AMD64HT_LDT0_BUS + i * 0x20; 497 bus = pci_conf_read(pa->pa_pc, pa->pa_tag, reg); 498 if (AMD64HT_LDT_SEC_BUS_NUM(bus) > 0) { 499 bzero(&pba, sizeof(pba)); 500 pba.pba_busname = "pci"; 501 pba.pba_iot = pa->pa_iot; 502 pba.pba_memt = pa->pa_memt; 503 pba.pba_dmat = pa->pa_dmat; 504 pba.pba_busex = pa->pa_busex; 505 pba.pba_domain = pa->pa_domain; 506 pba.pba_bus = AMD64HT_LDT_SEC_BUS_NUM(bus); 507 pba.pba_pc = pa->pa_pc; 508 config_found(self, &pba, pchb_print); 509 } 510 } 511