1 /* $NetBSD: pchb.c,v 1.5 2007/12/09 20:27:49 jmcneill Exp $ */ 2 3 /*- 4 * Copyright (c) 1996, 1998, 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> 40 __KERNEL_RCSID(0, "$NetBSD: pchb.c,v 1.5 2007/12/09 20:27:49 jmcneill Exp $"); 41 42 #include <sys/types.h> 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/device.h> 46 47 #include <machine/bus.h> 48 49 #include <dev/pci/pcivar.h> 50 #include <dev/pci/pcireg.h> 51 52 #include <dev/pci/pcidevs.h> 53 54 #include <dev/pci/agpreg.h> 55 #include <dev/pci/agpvar.h> 56 57 #include <arch/x86/pci/pchbvar.h> 58 59 #include "rnd.h" 60 61 #define PCISET_BRIDGETYPE_MASK 0x3 62 #define PCISET_TYPE_COMPAT 0x1 63 #define PCISET_TYPE_AUX 0x2 64 65 #define PCISET_BUSCONFIG_REG 0x48 66 #define PCISET_BRIDGE_NUMBER(reg) (((reg) >> 8) & 0xff) 67 #define PCISET_PCI_BUS_NUMBER(reg) (((reg) >> 16) & 0xff) 68 69 /* XXX should be in dev/ic/i82443reg.h */ 70 #define I82443BX_SDRAMC_REG 0x76 71 72 /* XXX should be in dev/ic/i82424{reg.var}.h */ 73 #define I82424_CPU_BCTL_REG 0x53 74 #define I82424_PCI_BCTL_REG 0x54 75 76 #define I82424_BCTL_CPUMEM_POSTEN 0x01 77 #define I82424_BCTL_CPUPCI_POSTEN 0x02 78 #define I82424_BCTL_PCIMEM_BURSTEN 0x01 79 #define I82424_BCTL_PCI_BURSTEN 0x02 80 81 int pchbmatch(struct device *, struct cfdata *, void *); 82 void pchbattach(struct device *, struct device *, void *); 83 84 static bool pchb_resume(device_t); 85 static bool pchb_suspend(device_t); 86 87 CFATTACH_DECL(pchb, sizeof(struct pchb_softc), 88 pchbmatch, pchbattach, NULL, NULL); 89 90 int 91 pchbmatch(struct device *parent, struct cfdata *match, void *aux) 92 { 93 struct pci_attach_args *pa = aux; 94 95 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE && 96 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_HOST) 97 return 1; 98 99 return 0; 100 } 101 102 void 103 pchbattach(struct device *parent, struct device *self, void *aux) 104 { 105 #if NRND > 0 106 struct pchb_softc *sc = (void *) self; 107 #endif 108 struct pci_attach_args *pa = aux; 109 char devinfo[256]; 110 struct pcibus_attach_args pba; 111 struct agpbus_attach_args apa; 112 pcireg_t bcreg; 113 u_char bdnum, pbnum = 0; /* XXX: gcc */ 114 pcitag_t tag; 115 int doattach, attachflags, has_agp; 116 117 aprint_naive("\n"); 118 aprint_normal("\n"); 119 120 doattach = 0; 121 has_agp = 0; 122 attachflags = pa->pa_flags; 123 124 /* 125 * Print out a description, and configure certain chipsets which 126 * have auxiliary PCI buses. 127 */ 128 129 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); 130 aprint_normal("%s: %s (rev. 0x%02x)\n", self->dv_xname, devinfo, 131 PCI_REVISION(pa->pa_class)); 132 133 switch (PCI_VENDOR(pa->pa_id)) { 134 /* 135 * i386 stuff. 136 */ 137 case PCI_VENDOR_SERVERWORKS: 138 pbnum = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x44) & 0xff; 139 140 if (pbnum == 0) 141 break; 142 143 /* 144 * This host bridge has a second PCI bus. 145 * Configure it. 146 */ 147 switch (PCI_PRODUCT(pa->pa_id)) { 148 case PCI_PRODUCT_SERVERWORKS_CSB5: 149 case PCI_PRODUCT_SERVERWORKS_CSB6: 150 /* These devices show up as host bridges, but are 151 really southbridges. */ 152 break; 153 case PCI_PRODUCT_SERVERWORKS_CMIC_HE: 154 case PCI_PRODUCT_SERVERWORKS_CMIC_LE: 155 case PCI_PRODUCT_SERVERWORKS_CMIC_SL: 156 /* CNBs and CIOBs are connected to these using a 157 private bus. The bus number register is that of 158 the first PCI bus hanging off the CIOB. We let 159 the CIOB attachment handle configuring the PCI 160 buses. */ 161 break; 162 default: 163 aprint_error("%s: unknown ServerWorks chip ID " 164 "0x%04x; trying to attach PCI buses behind it\n", 165 self->dv_xname, PCI_PRODUCT(pa->pa_id)); 166 /* FALLTHROUGH */ 167 case PCI_PRODUCT_SERVERWORKS_CNB20_LE_AGP: 168 case PCI_PRODUCT_SERVERWORKS_CNB30_LE_PCI: 169 case PCI_PRODUCT_SERVERWORKS_CNB20_LE_PCI: 170 case PCI_PRODUCT_SERVERWORKS_CNB20_HE_PCI: 171 case PCI_PRODUCT_SERVERWORKS_CNB20_HE_AGP: 172 case PCI_PRODUCT_SERVERWORKS_CIOB_X: 173 case PCI_PRODUCT_SERVERWORKS_CNB30_HE: 174 case PCI_PRODUCT_SERVERWORKS_CNB20_HE_PCI2: 175 case PCI_PRODUCT_SERVERWORKS_CIOB_X2: 176 case PCI_PRODUCT_SERVERWORKS_CIOB_E: 177 switch (attachflags & 178 (PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED)) { 179 case 0: 180 /* Doesn't smell like there's anything there. */ 181 break; 182 case PCI_FLAGS_MEM_ENABLED: 183 attachflags |= PCI_FLAGS_IO_ENABLED; 184 /* FALLTHROUGH */ 185 default: 186 doattach = 1; 187 break; 188 } 189 break; 190 } 191 break; 192 case PCI_VENDOR_INTEL: 193 switch (PCI_PRODUCT(pa->pa_id)) { 194 case PCI_PRODUCT_INTEL_82452_PB: 195 bcreg = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x40); 196 pbnum = PCISET_BRIDGE_NUMBER(bcreg); 197 if (pbnum != 0xff) { 198 pbnum++; 199 doattach = 1; 200 } 201 break; 202 case PCI_PRODUCT_INTEL_82443BX_AGP: 203 case PCI_PRODUCT_INTEL_82443BX_NOAGP: 204 /* 205 * http://www.intel.com/design/chipsets/specupdt/290639.htm 206 * says this bug is fixed in steppings >= C0 (erratum 11), 207 * so don't tweak the bits in that case. 208 */ 209 if (!(PCI_REVISION(pa->pa_class) >= 0x03)) { 210 /* 211 * BIOS BUG WORKAROUND! The 82443BX 212 * datasheet indicates that the only 213 * legal setting for the "Idle/Pipeline 214 * DRAM Leadoff Timing (IPLDT)" parameter 215 * (bits 9:8) is 01. Unfortunately, some 216 * BIOSs do not set these bits properly. 217 */ 218 bcreg = pci_conf_read(pa->pa_pc, pa->pa_tag, 219 I82443BX_SDRAMC_REG); 220 if ((bcreg & 0x0300) != 0x0100) { 221 aprint_verbose("%s: fixing " 222 "Idle/Pipeline DRAM " 223 "Leadoff Timing\n", self->dv_xname); 224 bcreg &= ~0x0300; 225 bcreg |= 0x0100; 226 pci_conf_write(pa->pa_pc, pa->pa_tag, 227 I82443BX_SDRAMC_REG, bcreg); 228 } 229 } 230 break; 231 232 case PCI_PRODUCT_INTEL_PCI450_PB: 233 bcreg = pci_conf_read(pa->pa_pc, pa->pa_tag, 234 PCISET_BUSCONFIG_REG); 235 bdnum = PCISET_BRIDGE_NUMBER(bcreg); 236 pbnum = PCISET_PCI_BUS_NUMBER(bcreg); 237 switch (bdnum & PCISET_BRIDGETYPE_MASK) { 238 default: 239 aprint_error("%s: bdnum=%x (reserved)\n", 240 self->dv_xname, bdnum); 241 break; 242 case PCISET_TYPE_COMPAT: 243 aprint_verbose( 244 "%s: Compatibility PB (bus %d)\n", 245 self->dv_xname, pbnum); 246 break; 247 case PCISET_TYPE_AUX: 248 aprint_verbose("%s: Auxiliary PB (bus %d)\n", 249 self->dv_xname, pbnum); 250 /* 251 * This host bridge has a second PCI bus. 252 * Configure it. 253 */ 254 doattach = 1; 255 break; 256 } 257 break; 258 case PCI_PRODUCT_INTEL_CDC: 259 bcreg = pci_conf_read(pa->pa_pc, pa->pa_tag, 260 I82424_CPU_BCTL_REG); 261 if (bcreg & I82424_BCTL_CPUPCI_POSTEN) { 262 bcreg &= ~I82424_BCTL_CPUPCI_POSTEN; 263 pci_conf_write(pa->pa_pc, pa->pa_tag, 264 I82424_CPU_BCTL_REG, bcreg); 265 aprint_verbose( 266 "%s: disabled CPU-PCI write posting\n", 267 self->dv_xname); 268 } 269 break; 270 case PCI_PRODUCT_INTEL_82451NX_PXB: 271 /* 272 * The NX chipset supports up to 2 "PXB" chips 273 * which can drive 2 PCI buses each. Each bus 274 * shows up as logical PCI device, with fixed 275 * device numbers between 18 and 21. 276 * See the datasheet at 277 ftp://download.intel.com/design/chipsets/datashts/24377102.pdf 278 * for details. 279 * (It would be easier to attach all the buses 280 * at the MIOC, but less aesthetical imho.) 281 */ 282 if ((attachflags & 283 (PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED)) == 284 PCI_FLAGS_MEM_ENABLED) 285 attachflags |= PCI_FLAGS_IO_ENABLED; 286 287 pbnum = 0; 288 switch (pa->pa_device) { 289 case 18: /* PXB 0 bus A - primary bus */ 290 break; 291 case 19: /* PXB 0 bus B */ 292 /* read SUBA0 from MIOC */ 293 tag = pci_make_tag(pa->pa_pc, 0, 16, 0); 294 bcreg = pci_conf_read(pa->pa_pc, tag, 0xd0); 295 pbnum = ((bcreg & 0x0000ff00) >> 8) + 1; 296 break; 297 case 20: /* PXB 1 bus A */ 298 /* read BUSNO1 from MIOC */ 299 tag = pci_make_tag(pa->pa_pc, 0, 16, 0); 300 bcreg = pci_conf_read(pa->pa_pc, tag, 0xd0); 301 pbnum = (bcreg & 0xff000000) >> 24; 302 break; 303 case 21: /* PXB 1 bus B */ 304 /* read SUBA1 from MIOC */ 305 tag = pci_make_tag(pa->pa_pc, 0, 16, 0); 306 bcreg = pci_conf_read(pa->pa_pc, tag, 0xd4); 307 pbnum = (bcreg & 0x000000ff) + 1; 308 break; 309 } 310 if (pbnum != 0) 311 doattach = 1; 312 break; 313 314 /* 315 * i386 and amd64 stuff. 316 */ 317 case PCI_PRODUCT_INTEL_82810_MCH: 318 case PCI_PRODUCT_INTEL_82810_DC100_MCH: 319 case PCI_PRODUCT_INTEL_82810E_MCH: 320 case PCI_PRODUCT_INTEL_82815_FULL_HUB: 321 case PCI_PRODUCT_INTEL_82830MP_IO_1: 322 case PCI_PRODUCT_INTEL_82845G_DRAM: 323 case PCI_PRODUCT_INTEL_82855GM_MCH: 324 case PCI_PRODUCT_INTEL_82865_HB: 325 case PCI_PRODUCT_INTEL_82915G_HB: 326 case PCI_PRODUCT_INTEL_82915GM_HB: 327 case PCI_PRODUCT_INTEL_82945P_MCH: 328 case PCI_PRODUCT_INTEL_82945GM_HB: 329 case PCI_PRODUCT_INTEL_82965Q_HB: 330 case PCI_PRODUCT_INTEL_82965G_HB: 331 case PCI_PRODUCT_INTEL_82965PM_HB: 332 case PCI_PRODUCT_INTEL_82Q35_HB: 333 case PCI_PRODUCT_INTEL_82G33_HB: 334 case PCI_PRODUCT_INTEL_82Q33_HB: 335 /* 336 * The host bridge is either in GFX mode (internal 337 * graphics) or in AGP mode. In GFX mode, we pretend 338 * to have AGP because the graphics memory access 339 * is very similar and the AGP GATT code will 340 * deal with this. In the latter case, the 341 * pci_get_capability(PCI_CAP_AGP) test below will 342 * fire, so we do no harm by already setting the flag. 343 */ 344 has_agp = 1; 345 break; 346 } 347 break; 348 } 349 350 #if NRND > 0 351 /* 352 * Attach a random number generator, if there is one. 353 */ 354 pchb_attach_rnd(sc, pa); 355 #endif 356 357 if (!pmf_device_register(self, pchb_suspend, pchb_resume)) 358 aprint_error_dev(self, "couldn't establish power handler\n"); 359 360 /* 361 * If we haven't detected AGP yet (via a product ID), 362 * then check for AGP capability on the device. 363 */ 364 if (has_agp || 365 pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, 366 NULL, NULL) != 0) { 367 apa.apa_pci_args = *pa; 368 config_found_ia(self, "agpbus", &apa, agpbusprint); 369 } 370 371 if (doattach) { 372 pba.pba_iot = pa->pa_iot; 373 pba.pba_memt = pa->pa_memt; 374 pba.pba_dmat = pa->pa_dmat; 375 pba.pba_dmat64 = pa->pa_dmat64; 376 pba.pba_pc = pa->pa_pc; 377 pba.pba_flags = attachflags; 378 pba.pba_bus = pbnum; 379 pba.pba_bridgetag = NULL; 380 pba.pba_pc = pa->pa_pc; 381 pba.pba_intrswiz = 0; 382 memset(&pba.pba_intrtag, 0, sizeof(pba.pba_intrtag)); 383 config_found_ia(self, "pcibus", &pba, pcibusprint); 384 } 385 } 386 387 static bool 388 pchb_suspend(device_t dv) 389 { 390 struct pchb_softc *sc = device_private(dv); 391 pci_chipset_tag_t pc; 392 pcitag_t tag; 393 int off; 394 395 pc = sc->sc_pc; 396 tag = sc->sc_tag; 397 398 for (off = 0x40; off <= 0xff; off += 4) 399 sc->sc_pciconfext[(off - 0x40) / 4] = pci_conf_read(pc, tag, off); 400 401 return true; 402 } 403 404 static bool 405 pchb_resume(device_t dv) 406 { 407 struct pchb_softc *sc = device_private(dv); 408 pci_chipset_tag_t pc; 409 pcitag_t tag; 410 int off; 411 412 pc = sc->sc_pc; 413 tag = sc->sc_tag; 414 415 for (off = 0x40; off <= 0xff; off += 4) 416 pci_conf_write(pc, tag, off, sc->sc_pciconfext[(off - 0x40) / 4]); 417 418 return true; 419 } 420