1 /* $OpenBSD: agp_intel.c,v 1.18 2010/08/07 20:47:24 deraadt 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 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_ERRSTS, 0x70); 264 } 265 266 isc->agpdev = (struct agp_softc *)agp_attach_bus(pa, &agp_intel_methods, 267 isc->isc_apaddr, isc->isc_apsize, &isc->dev); 268 return; 269 } 270 271 int 272 agp_intel_activate(struct device *arg, int act) 273 { 274 struct agp_intel_softc *isc = (struct agp_intel_softc *)arg; 275 276 switch (act) { 277 case DVACT_SUSPEND: 278 agp_intel_save(isc); 279 break; 280 case DVACT_RESUME: 281 agp_intel_restore(isc); 282 break; 283 } 284 285 return (0); 286 } 287 288 void 289 agp_intel_save(struct agp_intel_softc *isc) 290 { 291 292 if (isc->chiptype != CHIP_I443) { 293 isc->savectrl = pci_conf_read(isc->isc_pc, isc->isc_tag, 294 AGP_INTEL_AGPCTRL); 295 } 296 297 switch (isc->chiptype) { 298 case CHIP_I845: 299 case CHIP_I865: 300 isc->savecmd = pci_conf_read(isc->isc_pc, isc->isc_tag, 301 AGP_I840_MCHCFG); 302 303 break; 304 case CHIP_I840: 305 case CHIP_I850: 306 isc->savecmd = pci_conf_read(isc->isc_pc, isc->isc_tag, 307 AGP_INTEL_AGPCMD); 308 isc->savecfg = pci_conf_read(isc->isc_pc, isc->isc_tag, 309 AGP_I840_MCHCFG); 310 311 break; 312 default: 313 isc->savecfg = pci_conf_read(isc->isc_pc, isc->isc_tag, 314 AGP_INTEL_NBXCFG); 315 break; 316 } 317 } 318 319 void 320 agp_intel_restore(struct agp_intel_softc *isc) 321 { 322 /* 323 * reset size now just in case, if it worked before then sanity 324 * checking will not fail 325 */ 326 (void)agp_intel_set_aperture(isc, isc->isc_apsize); 327 328 /* Install the gatt. */ 329 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_ATTBASE, 330 isc->gatt->ag_physical); 331 332 /* Enable the GLTB and setup the control register. */ 333 switch (isc->chiptype) { 334 case CHIP_I443: 335 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 336 AGPCTRL_AGPRSE | AGPCTRL_GTLB); 337 break; 338 default: 339 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 340 isc->savectrl); 341 break; 342 } 343 344 /* Enable things, clear errors etc. */ 345 switch (isc->chiptype) { 346 case CHIP_I845: 347 case CHIP_I865: 348 pci_conf_write(isc->isc_pc, isc->isc_tag, 349 AGP_I840_MCHCFG, isc->savecmd); 350 break; 351 case CHIP_I840: 352 case CHIP_I850: 353 pci_conf_write(isc->isc_pc, isc->isc_tag, 354 AGP_INTEL_AGPCMD, isc->savecmd); 355 pci_conf_write(isc->isc_pc, isc->isc_tag, 356 AGP_I840_MCHCFG, isc->savecfg); 357 break; 358 default: 359 pci_conf_write(isc->isc_pc, isc->isc_tag, 360 AGP_INTEL_NBXCFG, isc->savecfg); 361 break; 362 } 363 364 /* Clear Error status */ 365 switch (isc->chiptype) { 366 case CHIP_I840: 367 pci_conf_write(isc->isc_pc, isc->isc_tag, 368 AGP_INTEL_I8XX_ERRSTS, 0xc000); 369 break; 370 case CHIP_I845: 371 case CHIP_I850: 372 case CHIP_I865: 373 pci_conf_write(isc->isc_pc, isc->isc_tag, 374 AGP_INTEL_I8XX_ERRSTS, 0x00ff); 375 break; 376 default: 377 pci_conf_write(isc->isc_pc, isc->isc_tag, 378 AGP_INTEL_ERRSTS, 0x70); 379 break; 380 } 381 } 382 383 #if 0 384 int 385 agp_intel_detach(struct agp_softc *sc) 386 { 387 int error; 388 pcireg_t reg; 389 struct agp_intel_softc *isc = sc->sc_chipc; 390 391 error = agp_generic_detach(sc); 392 if (error) 393 return (error); 394 395 /* XXX i845/i855PM/i840/i850E */ 396 reg = pci_conf_read(sc->sc_pc, sc->sc_tag, AGP_INTEL_NBXCFG); 397 reg &= ~(1 << 9); 398 printf("%s: set NBXCFG to %x\n", __FUNCTION__, reg); 399 pci_conf_write(sc->sc_pc, sc->sc_tag, AGP_INTEL_NBXCFG, reg); 400 pci_conf_write(sc->sc_pc, sc->sc_tag, AGP_INTEL_ATTBASE, 0); 401 AGP_SET_APERTURE(sc, isc->initial_aperture); 402 agp_free_gatt(sc, isc->gatt); 403 404 return (0); 405 } 406 #endif 407 408 bus_size_t 409 agp_intel_get_aperture(void *sc) 410 { 411 struct agp_intel_softc *isc = sc; 412 bus_size_t apsize; 413 414 apsize = pci_conf_read(isc->isc_pc, isc->isc_tag, 415 AGP_INTEL_APSIZE) & isc->aperture_mask; 416 417 /* 418 * The size is determined by the number of low bits of 419 * register APBASE which are forced to zero. The low 22 bits 420 * are always forced to zero and each zero bit in the apsize 421 * field just read forces the corresponding bit in the 27:22 422 * to be zero. We calculate the aperture size accordingly. 423 */ 424 return ((((apsize ^ isc->aperture_mask) << 22) | ((1 << 22) - 1)) + 1); 425 } 426 427 int 428 agp_intel_set_aperture(void *sc, bus_size_t aperture) 429 { 430 struct agp_intel_softc *isc = sc; 431 bus_size_t apsize; 432 433 /* 434 * Reverse the magic from get_aperture. 435 */ 436 apsize = ((aperture - 1) >> 22) ^ isc->aperture_mask; 437 438 /* 439 * Double check for sanity. 440 */ 441 if ((((apsize ^ isc->aperture_mask) << 22) | 442 ((1 << 22) - 1)) + 1 != aperture) 443 return (EINVAL); 444 445 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_APSIZE, apsize); 446 447 return (0); 448 } 449 450 void 451 agp_intel_bind_page(void *sc, bus_addr_t offset, paddr_t physical, int flags) 452 { 453 struct agp_intel_softc *isc = sc; 454 455 isc->gatt->ag_virtual[(offset - isc->isc_apaddr) >> AGP_PAGE_SHIFT] = 456 physical | 0x17; 457 } 458 459 void 460 agp_intel_unbind_page(void *sc, bus_size_t offset) 461 { 462 struct agp_intel_softc *isc = sc; 463 464 isc->gatt->ag_virtual[(offset - isc->isc_apaddr) >> AGP_PAGE_SHIFT] = 0; 465 } 466 467 void 468 agp_intel_flush_tlb(void *sc) 469 { 470 struct agp_intel_softc *isc = sc; 471 pcireg_t reg; 472 473 switch (isc->chiptype) { 474 case CHIP_I865: 475 case CHIP_I850: 476 case CHIP_I845: 477 case CHIP_I840: 478 case CHIP_I443: 479 reg = pci_conf_read(isc->isc_pc, isc->isc_tag, 480 AGP_INTEL_AGPCTRL); 481 reg &= ~AGPCTRL_GTLB; 482 pci_conf_write(isc->isc_pc, isc->isc_tag, 483 AGP_INTEL_AGPCTRL, reg); 484 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 485 reg | AGPCTRL_GTLB); 486 break; 487 default: /* XXX */ 488 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 489 0x2200); 490 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 491 0x2280); 492 break; 493 } 494 } 495