1 /* $OpenBSD: agp_intel.c,v 1.23 2014/05/27 12:40:00 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/device.h> 36 #include <sys/rwlock.h> 37 38 #include <dev/pci/pcivar.h> 39 #include <dev/pci/pcireg.h> 40 #include <dev/pci/pcidevs.h> 41 #include <dev/pci/agpvar.h> 42 #include <dev/pci/agpreg.h> 43 44 #include <machine/bus.h> 45 46 struct agp_intel_softc { 47 struct device dev; 48 struct agp_softc *agpdev; 49 struct agp_gatt *gatt; 50 pci_chipset_tag_t isc_pc; 51 pcitag_t isc_tag; 52 bus_addr_t isc_apaddr; 53 bus_size_t isc_apsize; 54 u_int aperture_mask; 55 enum { 56 CHIP_INTEL, 57 CHIP_I443, 58 CHIP_I840, 59 CHIP_I845, 60 CHIP_I850, 61 CHIP_I865 62 } chiptype; 63 /* registers saved during a suspend/resume cycle. */ 64 pcireg_t savectrl; 65 pcireg_t savecmd; 66 pcireg_t savecfg; 67 }; 68 69 70 void agp_intel_attach(struct device *, struct device *, void *); 71 int agp_intel_activate(struct device *, int); 72 void agp_intel_save(struct agp_intel_softc *); 73 void agp_intel_restore(struct agp_intel_softc *); 74 int agp_intel_probe(struct device *, void *, void *); 75 bus_size_t agp_intel_get_aperture(void *); 76 int agp_intel_set_aperture(void *, bus_size_t); 77 void agp_intel_bind_page(void *, bus_addr_t, paddr_t, int); 78 void agp_intel_unbind_page(void *, bus_addr_t); 79 void agp_intel_flush_tlb(void *); 80 81 struct cfattach intelagp_ca = { 82 sizeof(struct agp_intel_softc), agp_intel_probe, agp_intel_attach, 83 NULL, agp_intel_activate 84 }; 85 86 struct cfdriver intelagp_cd = { 87 NULL, "intelagp", DV_DULL 88 }; 89 90 const struct agp_methods agp_intel_methods = { 91 agp_intel_bind_page, 92 agp_intel_unbind_page, 93 agp_intel_flush_tlb, 94 /* default enable and memory routines */ 95 }; 96 97 int 98 agp_intel_probe(struct device *parent, void *match, void *aux) 99 { 100 struct agp_attach_args *aa = aux; 101 struct pci_attach_args *pa = aa->aa_pa; 102 103 /* Must be a pchb */ 104 if (agpbus_probe(aa) == 0) 105 return (0); 106 107 switch (PCI_PRODUCT(pa->pa_id)) { 108 case PCI_PRODUCT_INTEL_82443LX: 109 case PCI_PRODUCT_INTEL_82443BX: 110 case PCI_PRODUCT_INTEL_82440BX: 111 case PCI_PRODUCT_INTEL_82440BX_AGP: 112 case PCI_PRODUCT_INTEL_82815_HB: 113 case PCI_PRODUCT_INTEL_82820_HB: 114 case PCI_PRODUCT_INTEL_82830M_HB: 115 case PCI_PRODUCT_INTEL_82840_HB: 116 case PCI_PRODUCT_INTEL_82845_HB: 117 case PCI_PRODUCT_INTEL_82845G_HB: 118 case PCI_PRODUCT_INTEL_82850_HB: 119 case PCI_PRODUCT_INTEL_82855PM_HB: 120 case PCI_PRODUCT_INTEL_82855GM_HB: 121 case PCI_PRODUCT_INTEL_82860_HB: 122 case PCI_PRODUCT_INTEL_82865G_HB: 123 case PCI_PRODUCT_INTEL_82875P_HB: 124 return (1); 125 } 126 127 return (0); 128 } 129 130 void 131 agp_intel_attach(struct device *parent, struct device *self, void *aux) 132 { 133 struct agp_intel_softc *isc = (struct agp_intel_softc *)self; 134 struct agp_attach_args *aa = aux; 135 struct pci_attach_args *pa = aa->aa_pa; 136 struct agp_gatt *gatt; 137 pcireg_t reg; 138 u_int32_t value; 139 140 isc->isc_pc = pa->pa_pc; 141 isc->isc_tag = pa->pa_tag; 142 143 switch (PCI_PRODUCT(pa->pa_id)) { 144 case PCI_PRODUCT_INTEL_82443LX: 145 case PCI_PRODUCT_INTEL_82443BX: 146 case PCI_PRODUCT_INTEL_82440BX: 147 case PCI_PRODUCT_INTEL_82440BX_AGP: 148 isc->chiptype = CHIP_I443; 149 break; 150 case PCI_PRODUCT_INTEL_82830M_HB: 151 case PCI_PRODUCT_INTEL_82840_HB: 152 isc->chiptype = CHIP_I840; 153 break; 154 case PCI_PRODUCT_INTEL_82845_HB: 155 case PCI_PRODUCT_INTEL_82845G_HB: 156 case PCI_PRODUCT_INTEL_82855PM_HB: 157 isc->chiptype = CHIP_I845; 158 break; 159 case PCI_PRODUCT_INTEL_82850_HB: 160 isc->chiptype = CHIP_I850; 161 break; 162 case PCI_PRODUCT_INTEL_82865G_HB: 163 case PCI_PRODUCT_INTEL_82875P_HB: 164 isc->chiptype = CHIP_I865; 165 break; 166 default: 167 isc->chiptype = CHIP_INTEL; 168 break; 169 } 170 171 if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, AGP_APBASE, 172 PCI_MAPREG_TYPE_MEM, &isc->isc_apaddr, NULL, NULL) != 0) { 173 printf(": can't get aperture info\n"); 174 return; 175 } 176 177 /* Determine maximum supported aperture size. */ 178 value = pci_conf_read(pa->pa_pc, pa->pa_tag, AGP_INTEL_APSIZE); 179 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_APSIZE, APSIZE_MASK); 180 isc->aperture_mask = pci_conf_read(pa->pa_pc, pa->pa_tag, 181 AGP_INTEL_APSIZE) & APSIZE_MASK; 182 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_APSIZE, value); 183 isc->isc_apsize = agp_intel_get_aperture(isc); 184 185 for (;;) { 186 gatt = agp_alloc_gatt(pa->pa_dmat, isc->isc_apsize); 187 if (gatt != NULL) 188 break; 189 190 /* 191 * almost certainly error allocating contigious dma memory 192 * so reduce aperture so that the gatt size reduces. 193 */ 194 isc->isc_apsize /= 2; 195 if (agp_intel_set_aperture(isc, isc->isc_apsize)) { 196 printf(": failed to set aperture\n"); 197 return; 198 } 199 } 200 isc->gatt = gatt; 201 202 /* Install the gatt. */ 203 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_ATTBASE, 204 gatt->ag_physical); 205 206 /* Enable the GLTB and setup the control register. */ 207 switch (isc->chiptype) { 208 case CHIP_I443: 209 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 210 AGPCTRL_AGPRSE | AGPCTRL_GTLB); 211 break; 212 default: 213 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 214 pci_conf_read(isc->isc_pc, isc->isc_tag, 215 AGP_INTEL_AGPCTRL) | AGPCTRL_GTLB); 216 break; 217 } 218 219 /* Enable things, clear errors etc. */ 220 switch (isc->chiptype) { 221 case CHIP_I845: 222 case CHIP_I865: 223 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AGP_I840_MCHCFG); 224 reg |= MCHCFG_AAGN; 225 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_I840_MCHCFG, reg); 226 break; 227 case CHIP_I840: 228 case CHIP_I850: 229 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AGP_INTEL_AGPCMD); 230 reg |= AGPCMD_AGPEN; 231 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_AGPCMD, 232 reg); 233 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AGP_I840_MCHCFG); 234 reg |= MCHCFG_AAGN; 235 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_I840_MCHCFG, 236 reg); 237 break; 238 default: 239 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AGP_INTEL_NBXCFG); 240 reg &= ~NBXCFG_APAE; 241 reg |= NBXCFG_AAGN; 242 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_NBXCFG, reg); 243 break; 244 } 245 246 /* Clear Error status */ 247 switch (isc->chiptype) { 248 case CHIP_I840: 249 pci_conf_write(pa->pa_pc, pa->pa_tag, 250 AGP_INTEL_I8XX_ERRSTS, 0xc000); 251 break; 252 case CHIP_I845: 253 case CHIP_I850: 254 case CHIP_I865: 255 pci_conf_write(isc->isc_pc, isc->isc_tag, 256 AGP_INTEL_I8XX_ERRSTS, 0x00ff); 257 break; 258 259 default: 260 reg = pci_conf_read(isc->isc_pc, isc->isc_tag, 261 AGP_INTEL_ERRCMD); 262 pci_conf_write(isc->isc_pc, isc->isc_tag, 263 AGP_INTEL_ERRCMD, reg); 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 pcireg_t tmp; 323 /* 324 * reset size now just in case, if it worked before then sanity 325 * checking will not fail 326 */ 327 (void)agp_intel_set_aperture(isc, isc->isc_apsize); 328 329 /* Install the gatt. */ 330 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_ATTBASE, 331 isc->gatt->ag_physical); 332 333 /* Enable the GLTB and setup the control register. */ 334 switch (isc->chiptype) { 335 case CHIP_I443: 336 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 337 AGPCTRL_AGPRSE | AGPCTRL_GTLB); 338 break; 339 default: 340 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 341 isc->savectrl); 342 break; 343 } 344 345 /* Enable things, clear errors etc. */ 346 switch (isc->chiptype) { 347 case CHIP_I845: 348 case CHIP_I865: 349 pci_conf_write(isc->isc_pc, isc->isc_tag, 350 AGP_I840_MCHCFG, isc->savecmd); 351 break; 352 case CHIP_I840: 353 case CHIP_I850: 354 pci_conf_write(isc->isc_pc, isc->isc_tag, 355 AGP_INTEL_AGPCMD, isc->savecmd); 356 pci_conf_write(isc->isc_pc, isc->isc_tag, 357 AGP_I840_MCHCFG, isc->savecfg); 358 break; 359 default: 360 pci_conf_write(isc->isc_pc, isc->isc_tag, 361 AGP_INTEL_NBXCFG, isc->savecfg); 362 break; 363 } 364 365 /* Clear Error status */ 366 switch (isc->chiptype) { 367 case CHIP_I840: 368 pci_conf_write(isc->isc_pc, isc->isc_tag, 369 AGP_INTEL_I8XX_ERRSTS, 0xc000); 370 break; 371 case CHIP_I845: 372 case CHIP_I850: 373 case CHIP_I865: 374 pci_conf_write(isc->isc_pc, isc->isc_tag, 375 AGP_INTEL_I8XX_ERRSTS, 0x00ff); 376 break; 377 default: 378 tmp = pci_conf_read(isc->isc_pc, isc->isc_tag, 379 AGP_INTEL_ERRCMD); 380 pci_conf_write(isc->isc_pc, isc->isc_tag, 381 AGP_INTEL_ERRCMD, tmp); 382 break; 383 } 384 } 385 386 bus_size_t 387 agp_intel_get_aperture(void *sc) 388 { 389 struct agp_intel_softc *isc = sc; 390 bus_size_t apsize; 391 392 apsize = pci_conf_read(isc->isc_pc, isc->isc_tag, 393 AGP_INTEL_APSIZE) & isc->aperture_mask; 394 395 /* 396 * The size is determined by the number of low bits of 397 * register APBASE which are forced to zero. The low 22 bits 398 * are always forced to zero and each zero bit in the apsize 399 * field just read forces the corresponding bit in the 27:22 400 * to be zero. We calculate the aperture size accordingly. 401 */ 402 return ((((apsize ^ isc->aperture_mask) << 22) | ((1 << 22) - 1)) + 1); 403 } 404 405 int 406 agp_intel_set_aperture(void *sc, bus_size_t aperture) 407 { 408 struct agp_intel_softc *isc = sc; 409 bus_size_t apsize; 410 411 /* 412 * Reverse the magic from get_aperture. 413 */ 414 apsize = ((aperture - 1) >> 22) ^ isc->aperture_mask; 415 416 /* 417 * Double check for sanity. 418 */ 419 if ((((apsize ^ isc->aperture_mask) << 22) | 420 ((1 << 22) - 1)) + 1 != aperture) 421 return (EINVAL); 422 423 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_APSIZE, apsize); 424 425 return (0); 426 } 427 428 void 429 agp_intel_bind_page(void *sc, bus_addr_t offset, paddr_t physical, int flags) 430 { 431 struct agp_intel_softc *isc = sc; 432 433 isc->gatt->ag_virtual[(offset - isc->isc_apaddr) >> AGP_PAGE_SHIFT] = 434 physical | 0x17; 435 } 436 437 void 438 agp_intel_unbind_page(void *sc, bus_size_t offset) 439 { 440 struct agp_intel_softc *isc = sc; 441 442 isc->gatt->ag_virtual[(offset - isc->isc_apaddr) >> AGP_PAGE_SHIFT] = 0; 443 } 444 445 void 446 agp_intel_flush_tlb(void *sc) 447 { 448 struct agp_intel_softc *isc = sc; 449 pcireg_t reg; 450 451 switch (isc->chiptype) { 452 case CHIP_I865: 453 case CHIP_I850: 454 case CHIP_I845: 455 case CHIP_I840: 456 case CHIP_I443: 457 reg = pci_conf_read(isc->isc_pc, isc->isc_tag, 458 AGP_INTEL_AGPCTRL); 459 reg &= ~AGPCTRL_GTLB; 460 pci_conf_write(isc->isc_pc, isc->isc_tag, 461 AGP_INTEL_AGPCTRL, reg); 462 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 463 reg | AGPCTRL_GTLB); 464 break; 465 default: /* XXX */ 466 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 467 0x2200); 468 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 469 0x2280); 470 break; 471 } 472 } 473