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