1 /* $NetBSD: agp_i810.c,v 1.44 2007/10/30 12:22:54 jnemeth Exp $ */ 2 3 /*- 4 * Copyright (c) 2000 Doug Rabson 5 * Copyright (c) 2000 Ruslan Ermilov 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_i810.c,v 1.4 2001/07/05 21:28:47 jhb Exp $ 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: agp_i810.c,v 1.44 2007/10/30 12:22:54 jnemeth Exp $"); 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/malloc.h> 38 #include <sys/kernel.h> 39 #include <sys/lock.h> 40 #include <sys/proc.h> 41 #include <sys/device.h> 42 #include <sys/conf.h> 43 44 #include <uvm/uvm_extern.h> 45 46 #include <dev/pci/pcivar.h> 47 #include <dev/pci/pcireg.h> 48 #include <dev/pci/pcidevs.h> 49 #include <dev/pci/agpvar.h> 50 #include <dev/pci/agpreg.h> 51 52 #include <sys/agpio.h> 53 54 #include <sys/bus.h> 55 56 #include "agp_intel.h" 57 58 #define READ1(off) bus_space_read_1(isc->bst, isc->bsh, off) 59 #define READ4(off) bus_space_read_4(isc->bst, isc->bsh, off) 60 #define WRITE4(off,v) bus_space_write_4(isc->bst, isc->bsh, off, v) 61 #define WRITEGTT(off, v) \ 62 do { \ 63 if (isc->chiptype == CHIP_I915) { \ 64 bus_space_write_4(isc->gtt_bst, isc->gtt_bsh, \ 65 (u_int32_t)((off) >> AGP_PAGE_SHIFT) * 4, \ 66 (v)); \ 67 } else if (isc->chiptype == CHIP_I965) { \ 68 WRITE4(AGP_I965_GTT + \ 69 (u_int32_t)((off) >> AGP_PAGE_SHIFT) * 4, \ 70 (v)); \ 71 } else { \ 72 WRITE4(AGP_I810_GTT + \ 73 (u_int32_t)((off) >> AGP_PAGE_SHIFT) * 4, \ 74 (v)); \ 75 } \ 76 } while (0) 77 78 #define CHIP_I810 0 /* i810/i815 */ 79 #define CHIP_I830 1 /* 830M/845G */ 80 #define CHIP_I855 2 /* 852GM/855GM/865G */ 81 #define CHIP_I915 3 /* 915G/915GM/945G/945GM */ 82 #define CHIP_I965 4 /* 965Q */ 83 84 struct agp_i810_softc { 85 u_int32_t initial_aperture; /* aperture size at startup */ 86 struct agp_gatt *gatt; 87 int chiptype; /* i810-like or i830 */ 88 u_int32_t dcache_size; /* i810 only */ 89 u_int32_t stolen; /* number of i830/845 gtt entries 90 for stolen memory */ 91 bus_space_tag_t bst; /* register bus_space tag */ 92 bus_space_handle_t bsh; /* register bus_space handle */ 93 bus_space_tag_t gtt_bst; /* GTT bus_space tag */ 94 bus_space_handle_t gtt_bsh; /* GTT bus_space handle */ 95 struct pci_attach_args vga_pa; 96 97 void *sc_powerhook; 98 struct pci_conf_state sc_pciconf; 99 }; 100 101 static u_int32_t agp_i810_get_aperture(struct agp_softc *); 102 static int agp_i810_set_aperture(struct agp_softc *, u_int32_t); 103 static int agp_i810_bind_page(struct agp_softc *, off_t, bus_addr_t); 104 static int agp_i810_unbind_page(struct agp_softc *, off_t); 105 static void agp_i810_flush_tlb(struct agp_softc *); 106 static int agp_i810_enable(struct agp_softc *, u_int32_t mode); 107 static struct agp_memory *agp_i810_alloc_memory(struct agp_softc *, int, 108 vsize_t); 109 static int agp_i810_free_memory(struct agp_softc *, struct agp_memory *); 110 static int agp_i810_bind_memory(struct agp_softc *, struct agp_memory *, off_t); 111 static int agp_i810_unbind_memory(struct agp_softc *, struct agp_memory *); 112 static void agp_i810_powerhook(int, void *); 113 114 static struct agp_methods agp_i810_methods = { 115 agp_i810_get_aperture, 116 agp_i810_set_aperture, 117 agp_i810_bind_page, 118 agp_i810_unbind_page, 119 agp_i810_flush_tlb, 120 agp_i810_enable, 121 agp_i810_alloc_memory, 122 agp_i810_free_memory, 123 agp_i810_bind_memory, 124 agp_i810_unbind_memory, 125 }; 126 127 /* XXXthorpej -- duplicated code (see arch/i386/pci/pchb.c) */ 128 static int 129 agp_i810_vgamatch(struct pci_attach_args *pa) 130 { 131 132 if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY || 133 PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_VGA) 134 return (0); 135 136 switch (PCI_PRODUCT(pa->pa_id)) { 137 case PCI_PRODUCT_INTEL_82810_GC: 138 case PCI_PRODUCT_INTEL_82810_DC100_GC: 139 case PCI_PRODUCT_INTEL_82810E_GC: 140 case PCI_PRODUCT_INTEL_82815_FULL_GRAPH: 141 case PCI_PRODUCT_INTEL_82830MP_IV: 142 case PCI_PRODUCT_INTEL_82845G_IGD: 143 case PCI_PRODUCT_INTEL_82855GM_IGD: 144 case PCI_PRODUCT_INTEL_82865_IGD: 145 case PCI_PRODUCT_INTEL_82915G_IGD: 146 case PCI_PRODUCT_INTEL_82915GM_IGD: 147 case PCI_PRODUCT_INTEL_82945P_IGD: 148 case PCI_PRODUCT_INTEL_82945GM_IGD: 149 case PCI_PRODUCT_INTEL_82945GM_IGD_1: 150 case PCI_PRODUCT_INTEL_82965Q_IGD: 151 case PCI_PRODUCT_INTEL_82965Q_IGD_1: 152 case PCI_PRODUCT_INTEL_82965G_IGD: 153 case PCI_PRODUCT_INTEL_82965G_IGD_1: 154 return (1); 155 } 156 157 return (0); 158 } 159 160 static int 161 agp_i965_map_aperture(struct pci_attach_args *pa, struct agp_softc *sc, int reg) 162 { 163 /* 164 * Find the aperture. Don't map it (yet), this would 165 * eat KVA. 166 */ 167 if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, reg, 168 PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_64BIT, &sc->as_apaddr, &sc->as_apsize, 169 &sc->as_apflags) != 0) 170 return ENXIO; 171 172 sc->as_apt = pa->pa_memt; 173 174 return 0; 175 } 176 177 int 178 agp_i810_attach(struct device *parent, struct device *self, void *aux) 179 { 180 struct agp_softc *sc = (void *)self; 181 struct agp_i810_softc *isc; 182 struct agp_gatt *gatt; 183 int error, apbase; 184 bus_size_t mmadrsize; 185 186 isc = malloc(sizeof *isc, M_AGP, M_NOWAIT|M_ZERO); 187 if (isc == NULL) { 188 aprint_error(": can't allocate chipset-specific softc\n"); 189 return ENOMEM; 190 } 191 sc->as_chipc = isc; 192 sc->as_methods = &agp_i810_methods; 193 194 if (pci_find_device(&isc->vga_pa, agp_i810_vgamatch) == 0) { 195 #if NAGP_INTEL > 0 196 const struct pci_attach_args *pa = aux; 197 198 switch (PCI_PRODUCT(pa->pa_id)) { 199 case PCI_PRODUCT_INTEL_82840_HB: 200 case PCI_PRODUCT_INTEL_82865_HB: 201 case PCI_PRODUCT_INTEL_82845G_DRAM: 202 case PCI_PRODUCT_INTEL_82815_FULL_HUB: 203 return agp_intel_attach(parent, self, aux); 204 } 205 #endif 206 aprint_error(": can't find internal VGA device config space\n"); 207 free(isc, M_AGP); 208 return ENOENT; 209 } 210 211 /* XXXfvdl */ 212 sc->as_dmat = isc->vga_pa.pa_dmat; 213 214 switch (PCI_PRODUCT(isc->vga_pa.pa_id)) { 215 case PCI_PRODUCT_INTEL_82810_GC: 216 case PCI_PRODUCT_INTEL_82810_DC100_GC: 217 case PCI_PRODUCT_INTEL_82810E_GC: 218 case PCI_PRODUCT_INTEL_82815_FULL_GRAPH: 219 isc->chiptype = CHIP_I810; 220 break; 221 case PCI_PRODUCT_INTEL_82830MP_IV: 222 case PCI_PRODUCT_INTEL_82845G_IGD: 223 isc->chiptype = CHIP_I830; 224 break; 225 case PCI_PRODUCT_INTEL_82855GM_IGD: 226 case PCI_PRODUCT_INTEL_82865_IGD: 227 isc->chiptype = CHIP_I855; 228 break; 229 case PCI_PRODUCT_INTEL_82915G_IGD: 230 case PCI_PRODUCT_INTEL_82915GM_IGD: 231 case PCI_PRODUCT_INTEL_82945P_IGD: 232 case PCI_PRODUCT_INTEL_82945GM_IGD: 233 case PCI_PRODUCT_INTEL_82945GM_IGD_1: 234 isc->chiptype = CHIP_I915; 235 break; 236 case PCI_PRODUCT_INTEL_82965Q_IGD: 237 case PCI_PRODUCT_INTEL_82965Q_IGD_1: 238 case PCI_PRODUCT_INTEL_82965G_IGD: 239 case PCI_PRODUCT_INTEL_82965G_IGD_1: 240 isc->chiptype = CHIP_I965; 241 break; 242 } 243 244 apbase = isc->chiptype == CHIP_I915 ? AGP_I915_GMADR : AGP_I810_GMADR; 245 if (isc->chiptype == CHIP_I965) { 246 error = agp_i965_map_aperture(&isc->vga_pa, sc, AGP_I965_GMADR); 247 } else { 248 error = agp_map_aperture(&isc->vga_pa, sc, apbase); 249 } 250 if (error != 0) { 251 aprint_error(": can't map aperture\n"); 252 free(isc, M_AGP); 253 return error; 254 } 255 256 if (isc->chiptype == CHIP_I915) { 257 error = pci_mapreg_map(&isc->vga_pa, AGP_I915_MMADR, 258 PCI_MAPREG_TYPE_MEM, 0, &isc->bst, &isc->bsh, 259 NULL, &mmadrsize); 260 if (error != 0) { 261 aprint_error(": can't map mmadr registers\n"); 262 agp_generic_detach(sc); 263 return error; 264 } 265 error = pci_mapreg_map(&isc->vga_pa, AGP_I915_GTTADR, 266 PCI_MAPREG_TYPE_MEM, 0, &isc->gtt_bst, &isc->gtt_bsh, 267 NULL, NULL); 268 if (error != 0) { 269 aprint_error(": can't map gttadr registers\n"); 270 /* XXX we should release mmadr here */ 271 agp_generic_detach(sc); 272 return error; 273 } 274 } else if (isc->chiptype == CHIP_I965) { 275 error = pci_mapreg_map(&isc->vga_pa, AGP_I965_MMADR, 276 PCI_MAPREG_TYPE_MEM, 0, &isc->bst, &isc->bsh, 277 NULL, &mmadrsize); 278 if (error != 0) { 279 aprint_error(": can't map mmadr registers\n"); 280 agp_generic_detach(sc); 281 return error; 282 } 283 } else { 284 error = pci_mapreg_map(&isc->vga_pa, AGP_I810_MMADR, 285 PCI_MAPREG_TYPE_MEM, 0, &isc->bst, &isc->bsh, 286 NULL, &mmadrsize); 287 if (error != 0) { 288 aprint_error(": can't map mmadr registers\n"); 289 agp_generic_detach(sc); 290 return error; 291 } 292 } 293 294 isc->initial_aperture = AGP_GET_APERTURE(sc); 295 296 gatt = malloc(sizeof(struct agp_gatt), M_AGP, M_NOWAIT); 297 if (!gatt) { 298 agp_generic_detach(sc); 299 return ENOMEM; 300 } 301 isc->gatt = gatt; 302 303 gatt->ag_entries = AGP_GET_APERTURE(sc) >> AGP_PAGE_SHIFT; 304 305 if (isc->chiptype == CHIP_I810) { 306 void *virtual; 307 int dummyseg; 308 309 /* Some i810s have on-chip memory called dcache */ 310 if (READ1(AGP_I810_DRT) & AGP_I810_DRT_POPULATED) 311 isc->dcache_size = 4 * 1024 * 1024; 312 else 313 isc->dcache_size = 0; 314 315 /* According to the specs the gatt on the i810 must be 64k */ 316 if (agp_alloc_dmamem(sc->as_dmat, 64 * 1024, 317 0, &gatt->ag_dmamap, &virtual, &gatt->ag_physical, 318 &gatt->ag_dmaseg, 1, &dummyseg) != 0) { 319 free(gatt, M_AGP); 320 agp_generic_detach(sc); 321 return ENOMEM; 322 } 323 gatt->ag_virtual = (uint32_t *)virtual; 324 325 gatt->ag_size = gatt->ag_entries * sizeof(u_int32_t); 326 memset(gatt->ag_virtual, 0, gatt->ag_size); 327 328 agp_flush_cache(); 329 /* Install the GATT. */ 330 WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1); 331 } else if (isc->chiptype == CHIP_I830) { 332 /* The i830 automatically initializes the 128k gatt on boot. */ 333 pcireg_t reg; 334 u_int32_t pgtblctl; 335 u_int16_t gcc1; 336 337 reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I830_GCC0); 338 gcc1 = (u_int16_t)(reg >> 16); 339 switch (gcc1 & AGP_I830_GCC1_GMS) { 340 case AGP_I830_GCC1_GMS_STOLEN_512: 341 isc->stolen = (512 - 132) * 1024 / 4096; 342 break; 343 case AGP_I830_GCC1_GMS_STOLEN_1024: 344 isc->stolen = (1024 - 132) * 1024 / 4096; 345 break; 346 case AGP_I830_GCC1_GMS_STOLEN_8192: 347 isc->stolen = (8192 - 132) * 1024 / 4096; 348 break; 349 default: 350 isc->stolen = 0; 351 aprint_error( 352 ": unknown memory configuration, disabling\n"); 353 agp_generic_detach(sc); 354 return EINVAL; 355 } 356 if (isc->stolen > 0) { 357 aprint_error(": detected %dk stolen memory\n%s", 358 isc->stolen * 4, sc->as_dev.dv_xname); 359 } 360 361 /* GATT address is already in there, make sure it's enabled */ 362 pgtblctl = READ4(AGP_I810_PGTBL_CTL); 363 pgtblctl |= 1; 364 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl); 365 366 gatt->ag_physical = pgtblctl & ~1; 367 } else if (isc->chiptype == CHIP_I855 || isc->chiptype == CHIP_I915 || 368 isc->chiptype == CHIP_I965) { 369 pcireg_t reg; 370 u_int32_t pgtblctl, stolen; 371 u_int16_t gcc1; 372 373 /* Stolen memory is set up at the beginning of the aperture by 374 * the BIOS, consisting of the GATT followed by 4kb for the 375 * BIOS display. 376 */ 377 switch (isc->chiptype) { 378 case CHIP_I855: 379 stolen = 128 + 4; 380 break; 381 case CHIP_I915: 382 stolen = 256 + 4; 383 break; 384 case CHIP_I965: 385 stolen = 512 + 4; 386 break; 387 default: 388 aprint_error(": bad chiptype\n"); 389 agp_generic_detach(sc); 390 return EINVAL; 391 } 392 393 reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I855_GCC1); 394 gcc1 = (u_int16_t)(reg >> 16); 395 switch (gcc1 & AGP_I855_GCC1_GMS) { 396 case AGP_I855_GCC1_GMS_STOLEN_1M: 397 isc->stolen = (1024 - stolen) * 1024 / 4096; 398 break; 399 case AGP_I855_GCC1_GMS_STOLEN_4M: 400 isc->stolen = (4096 - stolen) * 1024 / 4096; 401 break; 402 case AGP_I855_GCC1_GMS_STOLEN_8M: 403 isc->stolen = (8192 - stolen) * 1024 / 4096; 404 break; 405 case AGP_I855_GCC1_GMS_STOLEN_16M: 406 isc->stolen = (16384 - stolen) * 1024 / 4096; 407 break; 408 case AGP_I855_GCC1_GMS_STOLEN_32M: 409 isc->stolen = (32768 - stolen) * 1024 / 4096; 410 break; 411 case AGP_I915_GCC1_GMS_STOLEN_48M: 412 isc->stolen = (49152 - stolen) * 1024 / 4096; 413 break; 414 case AGP_I915_GCC1_GMS_STOLEN_64M: 415 isc->stolen = (65536 - stolen) * 1024 / 4096; 416 break; 417 default: 418 isc->stolen = 0; 419 aprint_error( 420 ": unknown memory configuration, disabling\n"); 421 agp_generic_detach(sc); 422 return EINVAL; 423 } 424 if (isc->stolen > 0) { 425 aprint_error(": detected %dk stolen memory\n%s", 426 isc->stolen * 4, sc->as_dev.dv_xname); 427 } 428 429 /* GATT address is already in there, make sure it's enabled */ 430 pgtblctl = READ4(AGP_I810_PGTBL_CTL); 431 pgtblctl |= 1; 432 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl); 433 434 gatt->ag_physical = pgtblctl & ~1; 435 } 436 437 /* 438 * Make sure the chipset can see everything. 439 */ 440 agp_flush_cache(); 441 442 isc->sc_powerhook = powerhook_establish(sc->as_dev.dv_xname, 443 agp_i810_powerhook, sc); 444 if (isc->sc_powerhook == NULL) 445 printf("%s: WARNING: unable to establish PCI power hook\n", 446 sc->as_dev.dv_xname); 447 448 #if 0 449 /* 450 * another device (drm) may need access to this region 451 * we do not need it anymore 452 */ 453 bus_space_unmap(isc->bst, isc->bsh, mmadrsize); 454 #endif 455 456 return 0; 457 } 458 459 #if 0 460 static int 461 agp_i810_detach(struct agp_softc *sc) 462 { 463 int error; 464 struct agp_i810_softc *isc = sc->as_chipc; 465 466 error = agp_generic_detach(sc); 467 if (error) 468 return error; 469 470 /* Clear the GATT base. */ 471 if (sc->chiptype == CHIP_I810) { 472 WRITE4(AGP_I810_PGTBL_CTL, 0); 473 } else { 474 unsigned int pgtblctl; 475 pgtblctl = READ4(AGP_I810_PGTBL_CTL); 476 pgtblctl &= ~1; 477 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl); 478 } 479 480 /* Put the aperture back the way it started. */ 481 AGP_SET_APERTURE(sc, isc->initial_aperture); 482 483 if (sc->chiptype == CHIP_I810) { 484 agp_free_dmamem(sc->as_dmat, gatt->ag_size, gatt->ag_dmamap, 485 (void *)gatt->ag_virtual, &gatt->ag_dmaseg, 1); 486 } 487 free(sc->gatt, M_AGP); 488 489 return 0; 490 } 491 #endif 492 493 static u_int32_t 494 agp_i810_get_aperture(struct agp_softc *sc) 495 { 496 struct agp_i810_softc *isc = sc->as_chipc; 497 pcireg_t reg; 498 u_int16_t miscc, gcc1, msac; 499 500 switch (isc->chiptype) { 501 case CHIP_I810: 502 reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I810_SMRAM); 503 miscc = (u_int16_t)(reg >> 16); 504 if ((miscc & AGP_I810_MISCC_WINSIZE) == 505 AGP_I810_MISCC_WINSIZE_32) 506 return 32 * 1024 * 1024; 507 else 508 return 64 * 1024 * 1024; 509 case CHIP_I830: 510 reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I830_GCC0); 511 gcc1 = (u_int16_t)(reg >> 16); 512 if ((gcc1 & AGP_I830_GCC1_GMASIZE) == AGP_I830_GCC1_GMASIZE_64) 513 return 64 * 1024 * 1024; 514 else 515 return 128 * 1024 * 1024; 516 case CHIP_I855: 517 return 128 * 1024 * 1024; 518 case CHIP_I915: 519 reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I915_MSAC); 520 msac = (u_int16_t)(reg >> 16); 521 if (msac & AGP_I915_MSAC_APER_128M) 522 return 128 * 1024 * 1024; 523 else 524 return 256 * 1024 * 1024; 525 case CHIP_I965: 526 return 512 * 1024 * 1024; 527 default: 528 aprint_error(": Unknown chipset\n"); 529 } 530 531 return 0; 532 } 533 534 static int 535 agp_i810_set_aperture(struct agp_softc *sc, u_int32_t aperture) 536 { 537 struct agp_i810_softc *isc = sc->as_chipc; 538 pcireg_t reg; 539 u_int16_t miscc, gcc1; 540 541 switch (isc->chiptype) { 542 case CHIP_I810: 543 /* 544 * Double check for sanity. 545 */ 546 if (aperture != (32 * 1024 * 1024) && 547 aperture != (64 * 1024 * 1024)) { 548 printf("%s: bad aperture size %d\n", 549 sc->as_dev.dv_xname, aperture); 550 return EINVAL; 551 } 552 553 reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I810_SMRAM); 554 miscc = (u_int16_t)(reg >> 16); 555 miscc &= ~AGP_I810_MISCC_WINSIZE; 556 if (aperture == 32 * 1024 * 1024) 557 miscc |= AGP_I810_MISCC_WINSIZE_32; 558 else 559 miscc |= AGP_I810_MISCC_WINSIZE_64; 560 561 reg &= 0x0000ffff; 562 reg |= ((pcireg_t)miscc) << 16; 563 pci_conf_write(sc->as_pc, sc->as_tag, AGP_I810_SMRAM, reg); 564 break; 565 case CHIP_I830: 566 if (aperture != (64 * 1024 * 1024) && 567 aperture != (128 * 1024 * 1024)) { 568 printf("%s: bad aperture size %d\n", 569 sc->as_dev.dv_xname, aperture); 570 return EINVAL; 571 } 572 reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I830_GCC0); 573 gcc1 = (u_int16_t)(reg >> 16); 574 gcc1 &= ~AGP_I830_GCC1_GMASIZE; 575 if (aperture == 64 * 1024 * 1024) 576 gcc1 |= AGP_I830_GCC1_GMASIZE_64; 577 else 578 gcc1 |= AGP_I830_GCC1_GMASIZE_128; 579 580 reg &= 0x0000ffff; 581 reg |= ((pcireg_t)gcc1) << 16; 582 pci_conf_write(sc->as_pc, sc->as_tag, AGP_I830_GCC0, reg); 583 break; 584 case CHIP_I855: 585 case CHIP_I915: 586 if (aperture != agp_i810_get_aperture(sc)) { 587 printf("%s: bad aperture size %d\n", 588 sc->as_dev.dv_xname, aperture); 589 return EINVAL; 590 } 591 break; 592 case CHIP_I965: 593 if (aperture != 512 * 1024 * 1024) { 594 printf("%s: bad aperture size %d\n", 595 sc->as_dev.dv_xname, aperture); 596 return EINVAL; 597 } 598 break; 599 } 600 601 return 0; 602 } 603 604 static int 605 agp_i810_bind_page(struct agp_softc *sc, off_t offset, bus_addr_t physical) 606 { 607 struct agp_i810_softc *isc = sc->as_chipc; 608 609 if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT)) { 610 #ifdef AGP_DEBUG 611 printf("%s: failed: offset 0x%08x, shift %d, entries %d\n", 612 sc->as_dev.dv_xname, (int)offset, AGP_PAGE_SHIFT, 613 isc->gatt->ag_entries); 614 #endif 615 return EINVAL; 616 } 617 618 if (isc->chiptype != CHIP_I830) { 619 if ((offset >> AGP_PAGE_SHIFT) < isc->stolen) { 620 #ifdef AGP_DEBUG 621 printf("%s: trying to bind into stolen memory", 622 sc->as_dev.dv_xname); 623 #endif 624 return EINVAL; 625 } 626 } 627 628 WRITEGTT(offset, physical | 1); 629 return 0; 630 } 631 632 static int 633 agp_i810_unbind_page(struct agp_softc *sc, off_t offset) 634 { 635 struct agp_i810_softc *isc = sc->as_chipc; 636 637 if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT)) 638 return EINVAL; 639 640 if (isc->chiptype != CHIP_I810 ) { 641 if ((offset >> AGP_PAGE_SHIFT) < isc->stolen) { 642 #ifdef AGP_DEBUG 643 printf("%s: trying to unbind from stolen memory", 644 sc->as_dev.dv_xname); 645 #endif 646 return EINVAL; 647 } 648 } 649 650 WRITEGTT(offset, 0); 651 return 0; 652 } 653 654 /* 655 * Writing via memory mapped registers already flushes all TLBs. 656 */ 657 static void 658 agp_i810_flush_tlb(struct agp_softc *sc) 659 { 660 } 661 662 static int 663 agp_i810_enable(struct agp_softc *sc, u_int32_t mode) 664 { 665 666 return 0; 667 } 668 669 static struct agp_memory * 670 agp_i810_alloc_memory(struct agp_softc *sc, int type, vsize_t size) 671 { 672 struct agp_i810_softc *isc = sc->as_chipc; 673 struct agp_memory *mem; 674 675 #ifdef AGP_DEBUG 676 printf("AGP: alloc(%d, 0x%x)\n", type, (int) size); 677 #endif 678 679 if ((size & (AGP_PAGE_SIZE - 1)) != 0) 680 return 0; 681 682 if (sc->as_allocated + size > sc->as_maxmem) 683 return 0; 684 685 if (type == 1) { 686 /* 687 * Mapping local DRAM into GATT. 688 */ 689 if (isc->chiptype != CHIP_I810 ) 690 return 0; 691 if (size != isc->dcache_size) 692 return 0; 693 } else if (type == 2) { 694 /* 695 * Bogus mapping for the hardware cursor. 696 */ 697 if (size != AGP_PAGE_SIZE && size != 4 * AGP_PAGE_SIZE) 698 return 0; 699 } 700 701 mem = malloc(sizeof *mem, M_AGP, M_WAITOK|M_ZERO); 702 if (mem == NULL) 703 return NULL; 704 mem->am_id = sc->as_nextid++; 705 mem->am_size = size; 706 mem->am_type = type; 707 708 if (type == 2) { 709 /* 710 * Allocate and wire down the memory now so that we can 711 * get its physical address. 712 */ 713 mem->am_dmaseg = malloc(sizeof *mem->am_dmaseg, M_AGP, 714 M_WAITOK); 715 if (mem->am_dmaseg == NULL) { 716 free(mem, M_AGP); 717 return NULL; 718 } 719 if (agp_alloc_dmamem(sc->as_dmat, size, 0, 720 &mem->am_dmamap, &mem->am_virtual, &mem->am_physical, 721 mem->am_dmaseg, 1, &mem->am_nseg) != 0) { 722 free(mem->am_dmaseg, M_AGP); 723 free(mem, M_AGP); 724 return NULL; 725 } 726 memset(mem->am_virtual, 0, size); 727 } else if (type != 1) { 728 if (bus_dmamap_create(sc->as_dmat, size, size / PAGE_SIZE + 1, 729 size, 0, BUS_DMA_NOWAIT, 730 &mem->am_dmamap) != 0) { 731 free(mem, M_AGP); 732 return NULL; 733 } 734 } 735 736 TAILQ_INSERT_TAIL(&sc->as_memory, mem, am_link); 737 sc->as_allocated += size; 738 739 return mem; 740 } 741 742 static int 743 agp_i810_free_memory(struct agp_softc *sc, struct agp_memory *mem) 744 { 745 if (mem->am_is_bound) 746 return EBUSY; 747 748 if (mem->am_type == 2) { 749 agp_free_dmamem(sc->as_dmat, mem->am_size, mem->am_dmamap, 750 mem->am_virtual, mem->am_dmaseg, mem->am_nseg); 751 free(mem->am_dmaseg, M_AGP); 752 } 753 754 sc->as_allocated -= mem->am_size; 755 TAILQ_REMOVE(&sc->as_memory, mem, am_link); 756 free(mem, M_AGP); 757 return 0; 758 } 759 760 static int 761 agp_i810_bind_memory(struct agp_softc *sc, struct agp_memory *mem, 762 off_t offset) 763 { 764 struct agp_i810_softc *isc = sc->as_chipc; 765 u_int32_t regval, i; 766 767 /* 768 * XXX evil hack: the PGTBL_CTL appearently gets overwritten by the 769 * X server for mysterious reasons which leads to crashes if we write 770 * to the GTT through the MMIO window. 771 * Until the issue is solved, simply restore it. 772 */ 773 774 #if 0 775 regval = bus_space_read_4(isc->bst, isc->bsh, AGP_I810_PGTBL_CTL); 776 if (regval != (isc->gatt->ag_physical | 1)) { 777 printf("agp_i810_bind_memory: PGTBL_CTL is 0x%x - fixing\n", 778 regval); 779 bus_space_write_4(isc->bst, isc->bsh, AGP_I810_PGTBL_CTL, 780 isc->gatt->ag_physical | 1); 781 } 782 #endif 783 regval = 0; 784 785 if (mem->am_type == 2) { 786 WRITEGTT(offset, mem->am_physical | 1); 787 mem->am_offset = offset; 788 mem->am_is_bound = 1; 789 return 0; 790 } 791 792 if (mem->am_type != 1) 793 return agp_generic_bind_memory(sc, mem, offset); 794 795 if (isc->chiptype != CHIP_I810) 796 return EINVAL; 797 798 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) 799 WRITEGTT(offset, i | 3); 800 mem->am_is_bound = 1; 801 return 0; 802 } 803 804 static int 805 agp_i810_unbind_memory(struct agp_softc *sc, struct agp_memory *mem) 806 { 807 struct agp_i810_softc *isc = sc->as_chipc; 808 u_int32_t i; 809 810 if (mem->am_type == 2) { 811 WRITEGTT(mem->am_offset, 0); 812 mem->am_offset = 0; 813 mem->am_is_bound = 0; 814 return 0; 815 } 816 817 if (mem->am_type != 1) 818 return agp_generic_unbind_memory(sc, mem); 819 820 if (isc->chiptype != CHIP_I810) 821 return EINVAL; 822 823 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) 824 WRITEGTT(i, 0); 825 mem->am_is_bound = 0; 826 return 0; 827 } 828 829 static void 830 agp_i810_powerhook(int why, void *arg) 831 { 832 struct agp_softc *sc = (struct agp_softc *)arg; 833 struct agp_i810_softc *isc = sc->as_chipc; 834 835 if (why == PWR_RESUME) { 836 pci_conf_restore(sc->as_pc, sc->as_tag, &isc->sc_pciconf); 837 agp_flush_cache(); 838 } else if ((why == PWR_STANDBY) || (why == PWR_SUSPEND)) 839 pci_conf_capture(sc->as_pc, sc->as_tag, &isc->sc_pciconf); 840 841 return; 842 } 843