1 /* $OpenBSD: agp_intel.c,v 1.20 2012/11/13 23:36:17 kettenis Exp $ */ 2 /* $NetBSD: agp_intel.c,v 1.3 2001/09/15 00:25:00 thorpej Exp $ */ 3 4 /*- 5 * Copyright (c) 2000 Doug Rabson 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 AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD: src/sys/pci/agp_intel.c,v 1.4 2001/07/05 21:28:47 jhb Exp $ 30 */ 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/malloc.h> 35 #include <sys/kernel.h> 36 #include <sys/lock.h> 37 #include <sys/agpio.h> 38 #include <sys/device.h> 39 #include <sys/agpio.h> 40 41 #include <dev/pci/pcivar.h> 42 #include <dev/pci/pcireg.h> 43 #include <dev/pci/pcidevs.h> 44 #include <dev/pci/agpvar.h> 45 #include <dev/pci/agpreg.h> 46 47 #include <machine/bus.h> 48 49 struct agp_intel_softc { 50 struct device dev; 51 struct agp_softc *agpdev; 52 struct agp_gatt *gatt; 53 pci_chipset_tag_t isc_pc; 54 pcitag_t isc_tag; 55 bus_addr_t isc_apaddr; 56 bus_size_t isc_apsize; 57 u_int aperture_mask; 58 enum { 59 CHIP_INTEL, 60 CHIP_I443, 61 CHIP_I840, 62 CHIP_I845, 63 CHIP_I850, 64 CHIP_I865 65 } chiptype; 66 /* registers saved during a suspend/resume cycle. */ 67 pcireg_t savectrl; 68 pcireg_t savecmd; 69 pcireg_t savecfg; 70 }; 71 72 73 void agp_intel_attach(struct device *, struct device *, void *); 74 int agp_intel_activate(struct device *, int); 75 void agp_intel_save(struct agp_intel_softc *); 76 void agp_intel_restore(struct agp_intel_softc *); 77 int agp_intel_probe(struct device *, void *, void *); 78 bus_size_t agp_intel_get_aperture(void *); 79 int agp_intel_set_aperture(void *, bus_size_t); 80 void agp_intel_bind_page(void *, bus_addr_t, paddr_t, int); 81 void agp_intel_unbind_page(void *, bus_addr_t); 82 void agp_intel_flush_tlb(void *); 83 84 struct cfattach intelagp_ca = { 85 sizeof(struct agp_intel_softc), agp_intel_probe, agp_intel_attach, 86 NULL, agp_intel_activate 87 }; 88 89 struct cfdriver intelagp_cd = { 90 NULL, "intelagp", DV_DULL 91 }; 92 93 const struct agp_methods agp_intel_methods = { 94 agp_intel_bind_page, 95 agp_intel_unbind_page, 96 agp_intel_flush_tlb, 97 /* default enable and memory routines */ 98 }; 99 100 int 101 agp_intel_probe(struct device *parent, void *match, void *aux) 102 { 103 struct agp_attach_args *aa = aux; 104 struct pci_attach_args *pa = aa->aa_pa; 105 106 /* Must be a pchb */ 107 if (agpbus_probe(aa) == 0) 108 return (0); 109 110 switch (PCI_PRODUCT(pa->pa_id)) { 111 case PCI_PRODUCT_INTEL_82443LX: 112 case PCI_PRODUCT_INTEL_82443BX: 113 case PCI_PRODUCT_INTEL_82440BX: 114 case PCI_PRODUCT_INTEL_82440BX_AGP: 115 case PCI_PRODUCT_INTEL_82815_HB: 116 case PCI_PRODUCT_INTEL_82820_HB: 117 case PCI_PRODUCT_INTEL_82830M_HB: 118 case PCI_PRODUCT_INTEL_82840_HB: 119 case PCI_PRODUCT_INTEL_82845_HB: 120 case PCI_PRODUCT_INTEL_82845G_HB: 121 case PCI_PRODUCT_INTEL_82850_HB: 122 case PCI_PRODUCT_INTEL_82855PM_HB: 123 case PCI_PRODUCT_INTEL_82855GM_HB: 124 case PCI_PRODUCT_INTEL_82860_HB: 125 case PCI_PRODUCT_INTEL_82865G_HB: 126 case PCI_PRODUCT_INTEL_82875P_HB: 127 return (1); 128 } 129 130 return (0); 131 } 132 133 void 134 agp_intel_attach(struct device *parent, struct device *self, void *aux) 135 { 136 struct agp_intel_softc *isc = (struct agp_intel_softc *)self; 137 struct agp_attach_args *aa = aux; 138 struct pci_attach_args *pa = aa->aa_pa; 139 struct agp_gatt *gatt; 140 pcireg_t reg; 141 u_int32_t value; 142 143 isc->isc_pc = pa->pa_pc; 144 isc->isc_tag = pa->pa_tag; 145 146 switch (PCI_PRODUCT(pa->pa_id)) { 147 case PCI_PRODUCT_INTEL_82443LX: 148 case PCI_PRODUCT_INTEL_82443BX: 149 case PCI_PRODUCT_INTEL_82440BX: 150 case PCI_PRODUCT_INTEL_82440BX_AGP: 151 isc->chiptype = CHIP_I443; 152 break; 153 case PCI_PRODUCT_INTEL_82830M_HB: 154 case PCI_PRODUCT_INTEL_82840_HB: 155 isc->chiptype = CHIP_I840; 156 break; 157 case PCI_PRODUCT_INTEL_82845_HB: 158 case PCI_PRODUCT_INTEL_82845G_HB: 159 case PCI_PRODUCT_INTEL_82855PM_HB: 160 isc->chiptype = CHIP_I845; 161 break; 162 case PCI_PRODUCT_INTEL_82850_HB: 163 isc->chiptype = CHIP_I850; 164 break; 165 case PCI_PRODUCT_INTEL_82865G_HB: 166 case PCI_PRODUCT_INTEL_82875P_HB: 167 isc->chiptype = CHIP_I865; 168 break; 169 default: 170 isc->chiptype = CHIP_INTEL; 171 break; 172 } 173 174 if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, AGP_APBASE, 175 PCI_MAPREG_TYPE_MEM, &isc->isc_apaddr, NULL, NULL) != 0) { 176 printf(": can't get aperture info\n"); 177 return; 178 } 179 180 /* Determine maximum supported aperture size. */ 181 value = pci_conf_read(pa->pa_pc, pa->pa_tag, AGP_INTEL_APSIZE); 182 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_APSIZE, APSIZE_MASK); 183 isc->aperture_mask = pci_conf_read(pa->pa_pc, pa->pa_tag, 184 AGP_INTEL_APSIZE) & APSIZE_MASK; 185 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_APSIZE, value); 186 isc->isc_apsize = agp_intel_get_aperture(isc); 187 188 for (;;) { 189 gatt = agp_alloc_gatt(pa->pa_dmat, isc->isc_apsize); 190 if (gatt != NULL) 191 break; 192 193 /* 194 * almost certainly error allocating contigious dma memory 195 * so reduce aperture so that the gatt size reduces. 196 */ 197 isc->isc_apsize /= 2; 198 if (agp_intel_set_aperture(isc, isc->isc_apsize)) { 199 printf(": failed to set aperture\n"); 200 return; 201 } 202 } 203 isc->gatt = gatt; 204 205 /* Install the gatt. */ 206 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_ATTBASE, 207 gatt->ag_physical); 208 209 /* Enable the GLTB and setup the control register. */ 210 switch (isc->chiptype) { 211 case CHIP_I443: 212 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 213 AGPCTRL_AGPRSE | AGPCTRL_GTLB); 214 break; 215 default: 216 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 217 pci_conf_read(isc->isc_pc, isc->isc_tag, 218 AGP_INTEL_AGPCTRL) | AGPCTRL_GTLB); 219 break; 220 } 221 222 /* Enable things, clear errors etc. */ 223 switch (isc->chiptype) { 224 case CHIP_I845: 225 case CHIP_I865: 226 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AGP_I840_MCHCFG); 227 reg |= MCHCFG_AAGN; 228 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_I840_MCHCFG, reg); 229 break; 230 case CHIP_I840: 231 case CHIP_I850: 232 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AGP_INTEL_AGPCMD); 233 reg |= AGPCMD_AGPEN; 234 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_AGPCMD, 235 reg); 236 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AGP_I840_MCHCFG); 237 reg |= MCHCFG_AAGN; 238 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_I840_MCHCFG, 239 reg); 240 break; 241 default: 242 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AGP_INTEL_NBXCFG); 243 reg &= ~NBXCFG_APAE; 244 reg |= NBXCFG_AAGN; 245 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_NBXCFG, reg); 246 break; 247 } 248 249 /* Clear Error status */ 250 switch (isc->chiptype) { 251 case CHIP_I840: 252 pci_conf_write(pa->pa_pc, pa->pa_tag, 253 AGP_INTEL_I8XX_ERRSTS, 0xc000); 254 break; 255 case CHIP_I845: 256 case CHIP_I850: 257 case CHIP_I865: 258 pci_conf_write(isc->isc_pc, isc->isc_tag, 259 AGP_INTEL_I8XX_ERRSTS, 0x00ff); 260 break; 261 262 default: 263 reg = pci_conf_read(isc->isc_pc, isc->isc_tag, 264 AGP_INTEL_ERRCMD); 265 pci_conf_write(isc->isc_pc, isc->isc_tag, 266 AGP_INTEL_ERRCMD, reg); 267 } 268 269 isc->agpdev = (struct agp_softc *)agp_attach_bus(pa, &agp_intel_methods, 270 isc->isc_apaddr, isc->isc_apsize, &isc->dev); 271 return; 272 } 273 274 int 275 agp_intel_activate(struct device *arg, int act) 276 { 277 struct agp_intel_softc *isc = (struct agp_intel_softc *)arg; 278 279 switch (act) { 280 case DVACT_SUSPEND: 281 agp_intel_save(isc); 282 break; 283 case DVACT_RESUME: 284 agp_intel_restore(isc); 285 break; 286 } 287 288 return (0); 289 } 290 291 void 292 agp_intel_save(struct agp_intel_softc *isc) 293 { 294 295 if (isc->chiptype != CHIP_I443) { 296 isc->savectrl = pci_conf_read(isc->isc_pc, isc->isc_tag, 297 AGP_INTEL_AGPCTRL); 298 } 299 300 switch (isc->chiptype) { 301 case CHIP_I845: 302 case CHIP_I865: 303 isc->savecmd = pci_conf_read(isc->isc_pc, isc->isc_tag, 304 AGP_I840_MCHCFG); 305 306 break; 307 case CHIP_I840: 308 case CHIP_I850: 309 isc->savecmd = pci_conf_read(isc->isc_pc, isc->isc_tag, 310 AGP_INTEL_AGPCMD); 311 isc->savecfg = pci_conf_read(isc->isc_pc, isc->isc_tag, 312 AGP_I840_MCHCFG); 313 314 break; 315 default: 316 isc->savecfg = pci_conf_read(isc->isc_pc, isc->isc_tag, 317 AGP_INTEL_NBXCFG); 318 break; 319 } 320 } 321 322 void 323 agp_intel_restore(struct agp_intel_softc *isc) 324 { 325 pcireg_t tmp; 326 /* 327 * reset size now just in case, if it worked before then sanity 328 * checking will not fail 329 */ 330 (void)agp_intel_set_aperture(isc, isc->isc_apsize); 331 332 /* Install the gatt. */ 333 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_ATTBASE, 334 isc->gatt->ag_physical); 335 336 /* Enable the GLTB and setup the control register. */ 337 switch (isc->chiptype) { 338 case CHIP_I443: 339 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 340 AGPCTRL_AGPRSE | AGPCTRL_GTLB); 341 break; 342 default: 343 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 344 isc->savectrl); 345 break; 346 } 347 348 /* Enable things, clear errors etc. */ 349 switch (isc->chiptype) { 350 case CHIP_I845: 351 case CHIP_I865: 352 pci_conf_write(isc->isc_pc, isc->isc_tag, 353 AGP_I840_MCHCFG, isc->savecmd); 354 break; 355 case CHIP_I840: 356 case CHIP_I850: 357 pci_conf_write(isc->isc_pc, isc->isc_tag, 358 AGP_INTEL_AGPCMD, isc->savecmd); 359 pci_conf_write(isc->isc_pc, isc->isc_tag, 360 AGP_I840_MCHCFG, isc->savecfg); 361 break; 362 default: 363 pci_conf_write(isc->isc_pc, isc->isc_tag, 364 AGP_INTEL_NBXCFG, isc->savecfg); 365 break; 366 } 367 368 /* Clear Error status */ 369 switch (isc->chiptype) { 370 case CHIP_I840: 371 pci_conf_write(isc->isc_pc, isc->isc_tag, 372 AGP_INTEL_I8XX_ERRSTS, 0xc000); 373 break; 374 case CHIP_I845: 375 case CHIP_I850: 376 case CHIP_I865: 377 pci_conf_write(isc->isc_pc, isc->isc_tag, 378 AGP_INTEL_I8XX_ERRSTS, 0x00ff); 379 break; 380 default: 381 tmp = pci_conf_read(isc->isc_pc, isc->isc_tag, 382 AGP_INTEL_ERRCMD); 383 pci_conf_write(isc->isc_pc, isc->isc_tag, 384 AGP_INTEL_ERRCMD, tmp); 385 break; 386 } 387 } 388 389 #if 0 390 int 391 agp_intel_detach(struct agp_softc *sc) 392 { 393 int error; 394 pcireg_t reg; 395 struct agp_intel_softc *isc = sc->sc_chipc; 396 397 error = agp_generic_detach(sc); 398 if (error) 399 return (error); 400 401 /* XXX i845/i855PM/i840/i850E */ 402 reg = pci_conf_read(sc->sc_pc, sc->sc_tag, AGP_INTEL_NBXCFG); 403 reg &= ~(1 << 9); 404 printf("%s: set NBXCFG to %x\n", __FUNCTION__, reg); 405 pci_conf_write(sc->sc_pc, sc->sc_tag, AGP_INTEL_NBXCFG, reg); 406 pci_conf_write(sc->sc_pc, sc->sc_tag, AGP_INTEL_ATTBASE, 0); 407 AGP_SET_APERTURE(sc, isc->initial_aperture); 408 agp_free_gatt(sc, isc->gatt); 409 410 return (0); 411 } 412 #endif 413 414 bus_size_t 415 agp_intel_get_aperture(void *sc) 416 { 417 struct agp_intel_softc *isc = sc; 418 bus_size_t apsize; 419 420 apsize = pci_conf_read(isc->isc_pc, isc->isc_tag, 421 AGP_INTEL_APSIZE) & isc->aperture_mask; 422 423 /* 424 * The size is determined by the number of low bits of 425 * register APBASE which are forced to zero. The low 22 bits 426 * are always forced to zero and each zero bit in the apsize 427 * field just read forces the corresponding bit in the 27:22 428 * to be zero. We calculate the aperture size accordingly. 429 */ 430 return ((((apsize ^ isc->aperture_mask) << 22) | ((1 << 22) - 1)) + 1); 431 } 432 433 int 434 agp_intel_set_aperture(void *sc, bus_size_t aperture) 435 { 436 struct agp_intel_softc *isc = sc; 437 bus_size_t apsize; 438 439 /* 440 * Reverse the magic from get_aperture. 441 */ 442 apsize = ((aperture - 1) >> 22) ^ isc->aperture_mask; 443 444 /* 445 * Double check for sanity. 446 */ 447 if ((((apsize ^ isc->aperture_mask) << 22) | 448 ((1 << 22) - 1)) + 1 != aperture) 449 return (EINVAL); 450 451 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_APSIZE, apsize); 452 453 return (0); 454 } 455 456 void 457 agp_intel_bind_page(void *sc, bus_addr_t offset, paddr_t physical, int flags) 458 { 459 struct agp_intel_softc *isc = sc; 460 461 isc->gatt->ag_virtual[(offset - isc->isc_apaddr) >> AGP_PAGE_SHIFT] = 462 physical | 0x17; 463 } 464 465 void 466 agp_intel_unbind_page(void *sc, bus_size_t offset) 467 { 468 struct agp_intel_softc *isc = sc; 469 470 isc->gatt->ag_virtual[(offset - isc->isc_apaddr) >> AGP_PAGE_SHIFT] = 0; 471 } 472 473 void 474 agp_intel_flush_tlb(void *sc) 475 { 476 struct agp_intel_softc *isc = sc; 477 pcireg_t reg; 478 479 switch (isc->chiptype) { 480 case CHIP_I865: 481 case CHIP_I850: 482 case CHIP_I845: 483 case CHIP_I840: 484 case CHIP_I443: 485 reg = pci_conf_read(isc->isc_pc, isc->isc_tag, 486 AGP_INTEL_AGPCTRL); 487 reg &= ~AGPCTRL_GTLB; 488 pci_conf_write(isc->isc_pc, isc->isc_tag, 489 AGP_INTEL_AGPCTRL, reg); 490 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 491 reg | AGPCTRL_GTLB); 492 break; 493 default: /* XXX */ 494 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 495 0x2200); 496 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 497 0x2280); 498 break; 499 } 500 } 501