1 1.39 chs /* $NetBSD: agp_intel.c,v 1.39 2019/11/10 21:16:36 chs Exp $ */ 2 1.1 fvdl 3 1.1 fvdl /*- 4 1.1 fvdl * Copyright (c) 2000 Doug Rabson 5 1.1 fvdl * All rights reserved. 6 1.1 fvdl * 7 1.1 fvdl * Redistribution and use in source and binary forms, with or without 8 1.1 fvdl * modification, are permitted provided that the following conditions 9 1.1 fvdl * are met: 10 1.1 fvdl * 1. Redistributions of source code must retain the above copyright 11 1.1 fvdl * notice, this list of conditions and the following disclaimer. 12 1.1 fvdl * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 fvdl * notice, this list of conditions and the following disclaimer in the 14 1.1 fvdl * documentation and/or other materials provided with the distribution. 15 1.1 fvdl * 16 1.1 fvdl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 1.1 fvdl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 1.1 fvdl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 1.1 fvdl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 1.1 fvdl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 1.1 fvdl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 1.1 fvdl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 1.1 fvdl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 1.1 fvdl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.1 fvdl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.1 fvdl * SUCH DAMAGE. 27 1.1 fvdl * 28 1.1 fvdl * $FreeBSD: src/sys/pci/agp_intel.c,v 1.4 2001/07/05 21:28:47 jhb Exp $ 29 1.1 fvdl */ 30 1.4 lukem 31 1.4 lukem #include <sys/cdefs.h> 32 1.39 chs __KERNEL_RCSID(0, "$NetBSD: agp_intel.c,v 1.39 2019/11/10 21:16:36 chs Exp $"); 33 1.1 fvdl 34 1.1 fvdl #include <sys/param.h> 35 1.1 fvdl #include <sys/systm.h> 36 1.1 fvdl #include <sys/malloc.h> 37 1.1 fvdl #include <sys/kernel.h> 38 1.1 fvdl #include <sys/proc.h> 39 1.1 fvdl #include <sys/agpio.h> 40 1.1 fvdl #include <sys/device.h> 41 1.1 fvdl 42 1.1 fvdl #include <dev/pci/pcivar.h> 43 1.1 fvdl #include <dev/pci/pcireg.h> 44 1.7 ichiro #include <dev/pci/pcidevs.h> 45 1.1 fvdl #include <dev/pci/agpvar.h> 46 1.1 fvdl #include <dev/pci/agpreg.h> 47 1.1 fvdl 48 1.23 ad #include <sys/bus.h> 49 1.1 fvdl 50 1.1 fvdl struct agp_intel_softc { 51 1.7 ichiro u_int32_t initial_aperture; 52 1.7 ichiro /* aperture size at startup */ 53 1.7 ichiro struct agp_gatt *gatt; 54 1.10 ichiro struct pci_attach_args vga_pa; 55 1.10 ichiro u_int aperture_mask; 56 1.10 ichiro int chiptype; /* Chip type */ 57 1.8 ichiro #define CHIP_INTEL 0x0 58 1.8 ichiro #define CHIP_I443 0x1 59 1.8 ichiro #define CHIP_I840 0x2 60 1.8 ichiro #define CHIP_I845 0x3 61 1.8 ichiro #define CHIP_I850 0x4 62 1.14 tron #define CHIP_I865 0x5 63 1.18 jmcneill 64 1.1 fvdl }; 65 1.1 fvdl 66 1.1 fvdl static u_int32_t agp_intel_get_aperture(struct agp_softc *); 67 1.1 fvdl static int agp_intel_set_aperture(struct agp_softc *, u_int32_t); 68 1.1 fvdl static int agp_intel_bind_page(struct agp_softc *, off_t, bus_addr_t); 69 1.1 fvdl static int agp_intel_unbind_page(struct agp_softc *, off_t); 70 1.1 fvdl static void agp_intel_flush_tlb(struct agp_softc *); 71 1.24 joerg static int agp_intel_init(struct agp_softc *); 72 1.34 dyoung static bool agp_intel_resume(device_t, const pmf_qual_t *); 73 1.1 fvdl 74 1.15 thorpej static struct agp_methods agp_intel_methods = { 75 1.1 fvdl agp_intel_get_aperture, 76 1.1 fvdl agp_intel_set_aperture, 77 1.1 fvdl agp_intel_bind_page, 78 1.1 fvdl agp_intel_unbind_page, 79 1.1 fvdl agp_intel_flush_tlb, 80 1.1 fvdl agp_generic_enable, 81 1.1 fvdl agp_generic_alloc_memory, 82 1.1 fvdl agp_generic_free_memory, 83 1.1 fvdl agp_generic_bind_memory, 84 1.1 fvdl agp_generic_unbind_memory, 85 1.1 fvdl }; 86 1.1 fvdl 87 1.7 ichiro static int 88 1.37 dyoung agp_intel_vgamatch(const struct pci_attach_args *pa) 89 1.7 ichiro { 90 1.7 ichiro switch (PCI_PRODUCT(pa->pa_id)) { 91 1.35 jakllsch case PCI_PRODUCT_INTEL_82855GM_AGP: 92 1.7 ichiro case PCI_PRODUCT_INTEL_82855PM_AGP: 93 1.7 ichiro case PCI_PRODUCT_INTEL_82443LX_AGP: 94 1.7 ichiro case PCI_PRODUCT_INTEL_82443BX_AGP: 95 1.7 ichiro case PCI_PRODUCT_INTEL_82443GX_AGP: 96 1.10 ichiro case PCI_PRODUCT_INTEL_82850_AGP: /* i850/i860 */ 97 1.7 ichiro case PCI_PRODUCT_INTEL_82845_AGP: 98 1.7 ichiro case PCI_PRODUCT_INTEL_82840_AGP: 99 1.11 tron case PCI_PRODUCT_INTEL_82865_AGP: 100 1.11 tron case PCI_PRODUCT_INTEL_82875P_AGP: 101 1.7 ichiro return (1); 102 1.7 ichiro } 103 1.7 ichiro 104 1.7 ichiro return (0); 105 1.7 ichiro } 106 1.7 ichiro 107 1.1 fvdl int 108 1.32 freza agp_intel_attach(device_t parent, device_t self, void *aux) 109 1.1 fvdl { 110 1.32 freza struct agp_softc *sc = device_private(self); 111 1.32 freza struct pci_attach_args *pa = aux; 112 1.1 fvdl struct agp_intel_softc *isc; 113 1.1 fvdl struct agp_gatt *gatt; 114 1.10 ichiro u_int32_t value; 115 1.1 fvdl 116 1.39 chs isc = malloc(sizeof *isc, M_AGP, M_WAITOK|M_ZERO); 117 1.1 fvdl sc->as_methods = &agp_intel_methods; 118 1.2 fvdl sc->as_chipc = isc; 119 1.2 fvdl 120 1.7 ichiro if (pci_find_device(&isc->vga_pa, agp_intel_vgamatch) == 0) { 121 1.10 ichiro aprint_normal(": using generic initialization for Intel AGP\n"); 122 1.32 freza aprint_normal_dev(sc->as_dev, ""); 123 1.10 ichiro isc->chiptype = CHIP_INTEL; 124 1.7 ichiro } 125 1.7 ichiro 126 1.1 fvdl pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, &sc->as_capoff, 127 1.1 fvdl NULL); 128 1.1 fvdl 129 1.17 christos if (agp_map_aperture(pa, sc, AGP_APBASE) != 0) { 130 1.6 thorpej aprint_error(": can't map aperture\n"); 131 1.1 fvdl free(isc, M_AGP); 132 1.2 fvdl sc->as_chipc = NULL; 133 1.1 fvdl return ENXIO; 134 1.1 fvdl } 135 1.1 fvdl 136 1.7 ichiro switch (PCI_PRODUCT(isc->vga_pa.pa_id)) { 137 1.14 tron case PCI_PRODUCT_INTEL_82443LX_AGP: 138 1.14 tron case PCI_PRODUCT_INTEL_82443BX_AGP: 139 1.14 tron case PCI_PRODUCT_INTEL_82443GX_AGP: 140 1.14 tron isc->chiptype = CHIP_I443; 141 1.14 tron break; 142 1.14 tron case PCI_PRODUCT_INTEL_82840_AGP: 143 1.14 tron isc->chiptype = CHIP_I840; 144 1.14 tron break; 145 1.35 jakllsch case PCI_PRODUCT_INTEL_82855GM_AGP: 146 1.7 ichiro case PCI_PRODUCT_INTEL_82855PM_AGP: 147 1.7 ichiro case PCI_PRODUCT_INTEL_82845_AGP: 148 1.7 ichiro isc->chiptype = CHIP_I845; 149 1.7 ichiro break; 150 1.7 ichiro case PCI_PRODUCT_INTEL_82850_AGP: 151 1.8 ichiro isc->chiptype = CHIP_I850; 152 1.7 ichiro break; 153 1.14 tron case PCI_PRODUCT_INTEL_82865_AGP: 154 1.14 tron case PCI_PRODUCT_INTEL_82875P_AGP: 155 1.14 tron isc->chiptype = CHIP_I865; 156 1.7 ichiro break; 157 1.7 ichiro } 158 1.7 ichiro 159 1.10 ichiro /* Determine maximum supported aperture size. */ 160 1.10 ichiro value = pci_conf_read(sc->as_pc, sc->as_tag, AGP_INTEL_APSIZE); 161 1.10 ichiro pci_conf_write(sc->as_pc, sc->as_tag, 162 1.10 ichiro AGP_INTEL_APSIZE, APSIZE_MASK); 163 1.10 ichiro isc->aperture_mask = pci_conf_read(sc->as_pc, sc->as_tag, 164 1.10 ichiro AGP_INTEL_APSIZE) & APSIZE_MASK; 165 1.10 ichiro pci_conf_write(sc->as_pc, sc->as_tag, AGP_INTEL_APSIZE, value); 166 1.1 fvdl isc->initial_aperture = AGP_GET_APERTURE(sc); 167 1.1 fvdl 168 1.1 fvdl for (;;) { 169 1.1 fvdl gatt = agp_alloc_gatt(sc); 170 1.1 fvdl if (gatt) 171 1.1 fvdl break; 172 1.1 fvdl 173 1.1 fvdl /* 174 1.1 fvdl * Probably contigmalloc failure. Try reducing the 175 1.1 fvdl * aperture so that the gatt size reduces. 176 1.1 fvdl */ 177 1.1 fvdl if (AGP_SET_APERTURE(sc, AGP_GET_APERTURE(sc) / 2)) { 178 1.1 fvdl agp_generic_detach(sc); 179 1.6 thorpej aprint_error(": failed to set aperture\n"); 180 1.1 fvdl return ENOMEM; 181 1.1 fvdl } 182 1.1 fvdl } 183 1.1 fvdl isc->gatt = gatt; 184 1.1 fvdl 185 1.25 jmcneill if (!pmf_device_register(self, NULL, agp_intel_resume)) 186 1.25 jmcneill aprint_error_dev(self, "couldn't establish power handler\n"); 187 1.25 jmcneill 188 1.24 joerg return agp_intel_init(sc); 189 1.24 joerg } 190 1.24 joerg 191 1.24 joerg static int 192 1.24 joerg agp_intel_init(struct agp_softc *sc) 193 1.24 joerg { 194 1.24 joerg struct agp_intel_softc *isc = sc->as_chipc; 195 1.24 joerg struct agp_gatt *gatt = isc->gatt; 196 1.24 joerg pcireg_t reg; 197 1.24 joerg 198 1.1 fvdl /* Install the gatt. */ 199 1.1 fvdl pci_conf_write(sc->as_pc, sc->as_tag, AGP_INTEL_ATTBASE, 200 1.1 fvdl gatt->ag_physical); 201 1.8 ichiro 202 1.8 ichiro /* Enable the GLTB and setup the control register. */ 203 1.8 ichiro switch (isc->chiptype) { 204 1.8 ichiro case CHIP_I443: 205 1.8 ichiro pci_conf_write(sc->as_pc, sc->as_tag, AGP_INTEL_AGPCTRL, 206 1.8 ichiro AGPCTRL_AGPRSE | AGPCTRL_GTLB); 207 1.38 mrg break; 208 1.8 ichiro 209 1.8 ichiro default: 210 1.8 ichiro pci_conf_write(sc->as_pc, sc->as_tag, AGP_INTEL_AGPCTRL, 211 1.9 ichiro pci_conf_read(sc->as_pc, sc->as_tag, AGP_INTEL_AGPCTRL) 212 1.9 ichiro | AGPCTRL_GTLB); 213 1.8 ichiro } 214 1.10 ichiro 215 1.1 fvdl /* Enable things, clear errors etc. */ 216 1.7 ichiro switch (isc->chiptype) { 217 1.7 ichiro case CHIP_I845: 218 1.14 tron case CHIP_I865: 219 1.7 ichiro { 220 1.14 tron reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I840_MCHCFG); 221 1.14 tron reg |= MCHCFG_AAGN; 222 1.14 tron pci_conf_write(sc->as_pc, sc->as_tag, AGP_I840_MCHCFG, reg); 223 1.7 ichiro break; 224 1.7 ichiro } 225 1.7 ichiro case CHIP_I840: 226 1.8 ichiro case CHIP_I850: 227 1.7 ichiro { 228 1.10 ichiro reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_INTEL_AGPCMD); 229 1.10 ichiro reg |= AGPCMD_AGPEN; 230 1.7 ichiro pci_conf_write(sc->as_pc, sc->as_tag, AGP_INTEL_AGPCMD, 231 1.10 ichiro reg); 232 1.10 ichiro reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I840_MCHCFG); 233 1.10 ichiro reg |= MCHCFG_AAGN; 234 1.8 ichiro pci_conf_write(sc->as_pc, sc->as_tag, AGP_I840_MCHCFG, 235 1.10 ichiro reg); 236 1.7 ichiro break; 237 1.7 ichiro } 238 1.8 ichiro default: 239 1.7 ichiro { 240 1.7 ichiro reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_INTEL_NBXCFG); 241 1.7 ichiro reg &= ~NBXCFG_APAE; 242 1.7 ichiro reg |= NBXCFG_AAGN; 243 1.7 ichiro pci_conf_write(sc->as_pc, sc->as_tag, AGP_INTEL_NBXCFG, reg); 244 1.8 ichiro } 245 1.8 ichiro } 246 1.7 ichiro 247 1.8 ichiro /* Clear Error status */ 248 1.9 ichiro switch (isc->chiptype) { 249 1.8 ichiro case CHIP_I840: 250 1.9 ichiro pci_conf_write(sc->as_pc, sc->as_tag, 251 1.9 ichiro AGP_INTEL_I8XX_ERRSTS, 0xc000); 252 1.8 ichiro break; 253 1.1 fvdl 254 1.14 tron case CHIP_I845: 255 1.10 ichiro case CHIP_I850: 256 1.14 tron case CHIP_I865: 257 1.9 ichiro pci_conf_write(sc->as_pc, sc->as_tag, 258 1.9 ichiro AGP_INTEL_I8XX_ERRSTS, 0x00ff); 259 1.7 ichiro break; 260 1.8 ichiro 261 1.8 ichiro default: 262 1.28 gson { 263 1.29 drochner reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_INTEL_ERRSTS); 264 1.29 drochner /* clear error bits (write-one-to-clear) - just write back */ 265 1.29 drochner pci_conf_write(sc->as_pc, sc->as_tag, AGP_INTEL_ERRSTS, reg); 266 1.28 gson } 267 1.7 ichiro } 268 1.1 fvdl 269 1.10 ichiro return (0); 270 1.1 fvdl } 271 1.1 fvdl 272 1.1 fvdl #if 0 273 1.1 fvdl static int 274 1.1 fvdl agp_intel_detach(struct agp_softc *sc) 275 1.1 fvdl { 276 1.1 fvdl int error; 277 1.1 fvdl pcireg_t reg; 278 1.1 fvdl struct agp_intel_softc *isc = sc->as_chipc; 279 1.1 fvdl 280 1.1 fvdl error = agp_generic_detach(sc); 281 1.1 fvdl if (error) 282 1.1 fvdl return error; 283 1.1 fvdl 284 1.7 ichiro /* XXX i845/i855PM/i840/i850E */ 285 1.1 fvdl reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_INTEL_NBXCFG); 286 1.1 fvdl reg &= ~(1 << 9); 287 1.26 perry printf("%s: set NBXCFG to %x\n", __func__, reg); 288 1.1 fvdl pci_conf_write(sc->as_pc, sc->as_tag, AGP_INTEL_NBXCFG, reg); 289 1.1 fvdl pci_conf_write(sc->as_pc, sc->as_tag, AGP_INTEL_ATTBASE, 0); 290 1.1 fvdl AGP_SET_APERTURE(sc, isc->initial_aperture); 291 1.1 fvdl agp_free_gatt(sc, isc->gatt); 292 1.1 fvdl 293 1.1 fvdl return 0; 294 1.1 fvdl } 295 1.1 fvdl #endif 296 1.1 fvdl 297 1.1 fvdl static u_int32_t 298 1.1 fvdl agp_intel_get_aperture(struct agp_softc *sc) 299 1.1 fvdl { 300 1.10 ichiro struct agp_intel_softc *isc = sc->as_chipc; 301 1.1 fvdl u_int32_t apsize; 302 1.1 fvdl 303 1.7 ichiro apsize = pci_conf_read(sc->as_pc, sc->as_tag, 304 1.10 ichiro AGP_INTEL_APSIZE) & isc->aperture_mask; 305 1.1 fvdl 306 1.1 fvdl /* 307 1.1 fvdl * The size is determined by the number of low bits of 308 1.1 fvdl * register APBASE which are forced to zero. The low 22 bits 309 1.1 fvdl * are always forced to zero and each zero bit in the apsize 310 1.1 fvdl * field just read forces the corresponding bit in the 27:22 311 1.1 fvdl * to be zero. We calculate the aperture size accordingly. 312 1.1 fvdl */ 313 1.10 ichiro return (((apsize ^ isc->aperture_mask) << 22) | ((1 << 22) - 1)) + 1; 314 1.1 fvdl } 315 1.1 fvdl 316 1.1 fvdl static int 317 1.1 fvdl agp_intel_set_aperture(struct agp_softc *sc, u_int32_t aperture) 318 1.1 fvdl { 319 1.10 ichiro struct agp_intel_softc *isc = sc->as_chipc; 320 1.1 fvdl u_int32_t apsize; 321 1.1 fvdl 322 1.1 fvdl /* 323 1.1 fvdl * Reverse the magic from get_aperture. 324 1.1 fvdl */ 325 1.10 ichiro apsize = ((aperture - 1) >> 22) ^ isc->aperture_mask; 326 1.1 fvdl 327 1.1 fvdl /* 328 1.1 fvdl * Double check for sanity. 329 1.1 fvdl */ 330 1.10 ichiro if ((((apsize ^ isc->aperture_mask) << 22) | 331 1.7 ichiro ((1 << 22) - 1)) + 1 != aperture) 332 1.1 fvdl return EINVAL; 333 1.1 fvdl 334 1.10 ichiro pci_conf_write(sc->as_pc, sc->as_tag, 335 1.10 ichiro AGP_INTEL_APSIZE, apsize); 336 1.1 fvdl 337 1.1 fvdl return 0; 338 1.1 fvdl } 339 1.1 fvdl 340 1.1 fvdl static int 341 1.1 fvdl agp_intel_bind_page(struct agp_softc *sc, off_t offset, bus_addr_t physical) 342 1.1 fvdl { 343 1.1 fvdl struct agp_intel_softc *isc = sc->as_chipc; 344 1.1 fvdl 345 1.1 fvdl if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT)) 346 1.1 fvdl return EINVAL; 347 1.1 fvdl 348 1.1 fvdl isc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical | 0x17; 349 1.1 fvdl return 0; 350 1.1 fvdl } 351 1.1 fvdl 352 1.1 fvdl static int 353 1.1 fvdl agp_intel_unbind_page(struct agp_softc *sc, off_t offset) 354 1.1 fvdl { 355 1.1 fvdl struct agp_intel_softc *isc = sc->as_chipc; 356 1.1 fvdl 357 1.1 fvdl if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT)) 358 1.1 fvdl return EINVAL; 359 1.1 fvdl 360 1.1 fvdl isc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0; 361 1.1 fvdl return 0; 362 1.1 fvdl } 363 1.1 fvdl 364 1.1 fvdl static void 365 1.1 fvdl agp_intel_flush_tlb(struct agp_softc *sc) 366 1.1 fvdl { 367 1.7 ichiro struct agp_intel_softc *isc = sc->as_chipc; 368 1.10 ichiro pcireg_t reg; 369 1.7 ichiro 370 1.7 ichiro switch (isc->chiptype) { 371 1.14 tron case CHIP_I865: 372 1.13 tron case CHIP_I850: 373 1.13 tron case CHIP_I845: 374 1.13 tron case CHIP_I840: 375 1.10 ichiro case CHIP_I443: 376 1.10 ichiro { 377 1.10 ichiro reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_INTEL_AGPCTRL); 378 1.13 tron reg &= ~AGPCTRL_GTLB; 379 1.7 ichiro pci_conf_write(sc->as_pc, sc->as_tag, AGP_INTEL_AGPCTRL, 380 1.10 ichiro reg); 381 1.7 ichiro pci_conf_write(sc->as_pc, sc->as_tag, AGP_INTEL_AGPCTRL, 382 1.10 ichiro reg | AGPCTRL_GTLB); 383 1.7 ichiro break; 384 1.10 ichiro } 385 1.10 ichiro default: /* XXX */ 386 1.10 ichiro { 387 1.7 ichiro pci_conf_write(sc->as_pc, sc->as_tag, AGP_INTEL_AGPCTRL, 388 1.10 ichiro 0x2200); 389 1.7 ichiro pci_conf_write(sc->as_pc, sc->as_tag, AGP_INTEL_AGPCTRL, 390 1.10 ichiro 0x2280); 391 1.10 ichiro } 392 1.7 ichiro } 393 1.1 fvdl } 394 1.18 jmcneill 395 1.25 jmcneill static bool 396 1.34 dyoung agp_intel_resume(device_t dv, const pmf_qual_t *qual) 397 1.18 jmcneill { 398 1.25 jmcneill struct agp_softc *sc = device_private(dv); 399 1.18 jmcneill 400 1.25 jmcneill agp_intel_init(sc); 401 1.25 jmcneill agp_flush_cache(); 402 1.18 jmcneill 403 1.25 jmcneill return true; 404 1.18 jmcneill } 405