1 /* $NetBSD: agp_i810.c,v 1.23 2004/11/06 07:43:30 xtraeme 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.23 2004/11/06 07:43:30 xtraeme 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 <machine/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 62 #define CHIP_I810 0 /* i810/i815 */ 63 #define CHIP_I830 1 /* 830M/845G */ 64 #define CHIP_I855 2 /* 852GM/855GM/865G */ 65 66 struct agp_i810_softc { 67 u_int32_t initial_aperture; /* aperture size at startup */ 68 struct agp_gatt *gatt; 69 int chiptype; /* i810-like or i830 */ 70 u_int32_t dcache_size; /* i810 only */ 71 u_int32_t stolen; /* number of i830/845 gtt entries 72 for stolen memory */ 73 bus_space_tag_t bst; /* bus_space tag */ 74 bus_space_handle_t bsh; /* bus_space handle */ 75 struct pci_attach_args vga_pa; 76 }; 77 78 static u_int32_t agp_i810_get_aperture(struct agp_softc *); 79 static int agp_i810_set_aperture(struct agp_softc *, u_int32_t); 80 static int agp_i810_bind_page(struct agp_softc *, off_t, bus_addr_t); 81 static int agp_i810_unbind_page(struct agp_softc *, off_t); 82 static void agp_i810_flush_tlb(struct agp_softc *); 83 static int agp_i810_enable(struct agp_softc *, u_int32_t mode); 84 static struct agp_memory *agp_i810_alloc_memory(struct agp_softc *, int, 85 vsize_t); 86 static int agp_i810_free_memory(struct agp_softc *, struct agp_memory *); 87 static int agp_i810_bind_memory(struct agp_softc *, struct agp_memory *, off_t); 88 static int agp_i810_unbind_memory(struct agp_softc *, struct agp_memory *); 89 90 struct agp_methods agp_i810_methods = { 91 agp_i810_get_aperture, 92 agp_i810_set_aperture, 93 agp_i810_bind_page, 94 agp_i810_unbind_page, 95 agp_i810_flush_tlb, 96 agp_i810_enable, 97 agp_i810_alloc_memory, 98 agp_i810_free_memory, 99 agp_i810_bind_memory, 100 agp_i810_unbind_memory, 101 }; 102 103 /* XXXthorpej -- duplicated code (see arch/i386/pci/pchb.c) */ 104 static int 105 agp_i810_vgamatch(struct pci_attach_args *pa) 106 { 107 108 if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY || 109 PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_VGA) 110 return (0); 111 112 switch (PCI_PRODUCT(pa->pa_id)) { 113 case PCI_PRODUCT_INTEL_82810_GC: 114 case PCI_PRODUCT_INTEL_82810_DC100_GC: 115 case PCI_PRODUCT_INTEL_82810E_GC: 116 case PCI_PRODUCT_INTEL_82815_FULL_GRAPH: 117 case PCI_PRODUCT_INTEL_82830MP_IV: 118 case PCI_PRODUCT_INTEL_82845G_IGD: 119 case PCI_PRODUCT_INTEL_82855GM_IGD: 120 case PCI_PRODUCT_INTEL_82865_IGD: 121 return (1); 122 } 123 124 return (0); 125 } 126 127 int 128 agp_i810_attach(struct device *parent, struct device *self, void *aux) 129 { 130 struct agp_softc *sc = (void *)self; 131 struct agp_i810_softc *isc; 132 struct agp_gatt *gatt; 133 int error; 134 135 isc = malloc(sizeof *isc, M_AGP, M_NOWAIT|M_ZERO); 136 if (isc == NULL) { 137 aprint_error(": can't allocate chipset-specific softc\n"); 138 return ENOMEM; 139 } 140 sc->as_chipc = isc; 141 sc->as_methods = &agp_i810_methods; 142 143 if (pci_find_device(&isc->vga_pa, agp_i810_vgamatch) == 0) { 144 #if NAGP_INTEL > 0 145 const struct pci_attach_args *pa = aux; 146 147 switch (PCI_PRODUCT(pa->pa_id)) { 148 case PCI_PRODUCT_INTEL_82840_HB: 149 case PCI_PRODUCT_INTEL_82865_HB: 150 case PCI_PRODUCT_INTEL_82845G_DRAM: 151 case PCI_PRODUCT_INTEL_82815_FULL_HUB: 152 return agp_intel_attach(parent, self, aux); 153 } 154 #endif 155 aprint_error(": can't find internal VGA device config space\n"); 156 free(isc, M_AGP); 157 return ENOENT; 158 } 159 160 /* XXXfvdl */ 161 sc->as_dmat = isc->vga_pa.pa_dmat; 162 163 error = agp_map_aperture(&isc->vga_pa, sc); 164 if (error != 0) { 165 aprint_error(": can't map aperture\n"); 166 free(isc, M_AGP); 167 return error; 168 } 169 170 switch (PCI_PRODUCT(isc->vga_pa.pa_id)) { 171 case PCI_PRODUCT_INTEL_82810_GC: 172 case PCI_PRODUCT_INTEL_82810_DC100_GC: 173 case PCI_PRODUCT_INTEL_82810E_GC: 174 case PCI_PRODUCT_INTEL_82815_FULL_GRAPH: 175 isc->chiptype = CHIP_I810; 176 break; 177 case PCI_PRODUCT_INTEL_82830MP_IV: 178 case PCI_PRODUCT_INTEL_82845G_IGD: 179 isc->chiptype = CHIP_I830; 180 break; 181 case PCI_PRODUCT_INTEL_82855GM_IGD: 182 case PCI_PRODUCT_INTEL_82865_IGD: 183 isc->chiptype = CHIP_I855; 184 break; 185 } 186 187 error = pci_mapreg_map(&isc->vga_pa, AGP_I810_MMADR, 188 PCI_MAPREG_TYPE_MEM, 0, &isc->bst, &isc->bsh, NULL, NULL); 189 if (error != 0) { 190 aprint_error(": can't map mmadr registers\n"); 191 return error; 192 } 193 194 isc->initial_aperture = AGP_GET_APERTURE(sc); 195 196 gatt = malloc(sizeof(struct agp_gatt), M_AGP, M_NOWAIT); 197 if (!gatt) { 198 agp_generic_detach(sc); 199 return ENOMEM; 200 } 201 isc->gatt = gatt; 202 203 gatt->ag_entries = AGP_GET_APERTURE(sc) >> AGP_PAGE_SHIFT; 204 205 if (isc->chiptype == CHIP_I810) { 206 int dummyseg; 207 /* Some i810s have on-chip memory called dcache */ 208 if (READ1(AGP_I810_DRT) & AGP_I810_DRT_POPULATED) 209 isc->dcache_size = 4 * 1024 * 1024; 210 else 211 isc->dcache_size = 0; 212 213 /* According to the specs the gatt on the i810 must be 64k */ 214 if (agp_alloc_dmamem(sc->as_dmat, 64 * 1024, 215 0, &gatt->ag_dmamap, (caddr_t *)&gatt->ag_virtual, 216 &gatt->ag_physical, &gatt->ag_dmaseg, 1, &dummyseg) != 0) { 217 free(gatt, M_AGP); 218 agp_generic_detach(sc); 219 return ENOMEM; 220 } 221 222 gatt->ag_size = gatt->ag_entries * sizeof(u_int32_t); 223 memset(gatt->ag_virtual, 0, gatt->ag_size); 224 225 agp_flush_cache(); 226 /* Install the GATT. */ 227 WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1); 228 } else if (isc->chiptype == CHIP_I830) { 229 /* The i830 automatically initializes the 128k gatt on boot. */ 230 pcireg_t reg; 231 u_int32_t pgtblctl; 232 u_int16_t gcc1; 233 234 reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I830_GCC0); 235 gcc1 = (u_int16_t)(reg >> 16); 236 switch (gcc1 & AGP_I830_GCC1_GMS) { 237 case AGP_I830_GCC1_GMS_STOLEN_512: 238 isc->stolen = (512 - 132) * 1024 / 4096; 239 break; 240 case AGP_I830_GCC1_GMS_STOLEN_1024: 241 isc->stolen = (1024 - 132) * 1024 / 4096; 242 break; 243 case AGP_I830_GCC1_GMS_STOLEN_8192: 244 isc->stolen = (8192 - 132) * 1024 / 4096; 245 break; 246 default: 247 isc->stolen = 0; 248 aprint_error( 249 ": unknown memory configuration, disabling\n"); 250 agp_generic_detach(sc); 251 return EINVAL; 252 } 253 if (isc->stolen > 0) { 254 aprint_error(": detected %dk stolen memory\n%s", 255 isc->stolen * 4, sc->as_dev.dv_xname); 256 } 257 258 /* GATT address is already in there, make sure it's enabled */ 259 pgtblctl = READ4(AGP_I810_PGTBL_CTL); 260 pgtblctl |= 1; 261 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl); 262 263 gatt->ag_physical = pgtblctl & ~1; 264 } else { /* CHIP_I855 */ 265 /* The 855GM automatically initializes the 128k gatt on boot. */ 266 pcireg_t reg; 267 u_int32_t pgtblctl; 268 u_int16_t gcc1; 269 270 reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I855_GCC1); 271 gcc1 = (u_int16_t)(reg >> 16); 272 switch (gcc1 & AGP_I855_GCC1_GMS) { 273 case AGP_I855_GCC1_GMS_STOLEN_1M: 274 isc->stolen = (1024 - 132) * 1024 / 4096; 275 break; 276 case AGP_I855_GCC1_GMS_STOLEN_4M: 277 isc->stolen = (4096 - 132) * 1024 / 4096; 278 break; 279 case AGP_I855_GCC1_GMS_STOLEN_8M: 280 isc->stolen = (8192 - 132) * 1024 / 4096; 281 break; 282 case AGP_I855_GCC1_GMS_STOLEN_16M: 283 isc->stolen = (16384 - 132) * 1024 / 4096; 284 break; 285 case AGP_I855_GCC1_GMS_STOLEN_32M: 286 isc->stolen = (32768 - 132) * 1024 / 4096; 287 break; 288 default: 289 isc->stolen = 0; 290 aprint_error( 291 ": unknown memory configuration, disabling\n"); 292 agp_generic_detach(sc); 293 return EINVAL; 294 } 295 if (isc->stolen > 0) { 296 aprint_error(": detected %dk stolen memory\n%s", 297 isc->stolen * 4, sc->as_dev.dv_xname); 298 } 299 300 /* GATT address is already in there, make sure it's enabled */ 301 pgtblctl = READ4(AGP_I810_PGTBL_CTL); 302 pgtblctl |= 1; 303 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl); 304 305 gatt->ag_physical = pgtblctl & ~1; 306 } 307 308 /* 309 * Make sure the chipset can see everything. 310 */ 311 agp_flush_cache(); 312 313 return 0; 314 } 315 316 #if 0 317 static int 318 agp_i810_detach(struct agp_softc *sc) 319 { 320 int error; 321 struct agp_i810_softc *isc = sc->as_chipc; 322 323 error = agp_generic_detach(sc); 324 if (error) 325 return error; 326 327 /* Clear the GATT base. */ 328 if (sc->chiptype == CHIP_I810) { 329 WRITE4(AGP_I810_PGTBL_CTL, 0); 330 } else { 331 unsigned int pgtblctl; 332 pgtblctl = READ4(AGP_I810_PGTBL_CTL); 333 pgtblctl &= ~1; 334 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl); 335 } 336 337 /* Put the aperture back the way it started. */ 338 AGP_SET_APERTURE(sc, isc->initial_aperture); 339 340 if (sc->chiptype == CHIP_I810) { 341 agp_free_dmamem(sc->as_dmat, gatt->ag_size, gatt->ag_dmamap, 342 (caddr_t)gatt->ag_virtual, &gatt->ag_dmaseg, 1); 343 } 344 free(sc->gatt, M_AGP); 345 346 return 0; 347 } 348 #endif 349 350 static u_int32_t 351 agp_i810_get_aperture(struct agp_softc *sc) 352 { 353 struct agp_i810_softc *isc = sc->as_chipc; 354 pcireg_t reg; 355 356 if (isc->chiptype == CHIP_I810) { 357 u_int16_t miscc; 358 359 reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I810_SMRAM); 360 miscc = (u_int16_t)(reg >> 16); 361 if ((miscc & AGP_I810_MISCC_WINSIZE) == 362 AGP_I810_MISCC_WINSIZE_32) 363 return 32 * 1024 * 1024; 364 else 365 return 64 * 1024 * 1024; 366 } else if (isc->chiptype == CHIP_I830) { 367 u_int16_t gcc1; 368 369 reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I830_GCC0); 370 gcc1 = (u_int16_t)(reg >> 16); 371 if ((gcc1 & AGP_I830_GCC1_GMASIZE) == AGP_I830_GCC1_GMASIZE_64) 372 return 64 * 1024 * 1024; 373 else 374 return 128 * 1024 * 1024; 375 } else { /* CHIP_I855 */ 376 return 128 * 1024 * 1024; 377 } 378 } 379 380 static int 381 agp_i810_set_aperture(struct agp_softc *sc, u_int32_t aperture) 382 { 383 struct agp_i810_softc *isc = sc->as_chipc; 384 pcireg_t reg; 385 386 if (isc->chiptype == CHIP_I810) { 387 u_int16_t miscc; 388 389 /* 390 * Double check for sanity. 391 */ 392 if (aperture != (32 * 1024 * 1024) && 393 aperture != (64 * 1024 * 1024)) { 394 printf("%s: bad aperture size %d\n", 395 sc->as_dev.dv_xname, aperture); 396 return EINVAL; 397 } 398 399 reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I810_SMRAM); 400 miscc = (u_int16_t)(reg >> 16); 401 miscc &= ~AGP_I810_MISCC_WINSIZE; 402 if (aperture == 32 * 1024 * 1024) 403 miscc |= AGP_I810_MISCC_WINSIZE_32; 404 else 405 miscc |= AGP_I810_MISCC_WINSIZE_64; 406 407 reg &= 0x0000ffff; 408 reg |= ((pcireg_t)miscc) << 16; 409 pci_conf_write(sc->as_pc, sc->as_tag, AGP_I810_SMRAM, reg); 410 } if (isc->chiptype == CHIP_I830) { 411 u_int16_t gcc1; 412 413 if (aperture != (64 * 1024 * 1024) && 414 aperture != (128 * 1024 * 1024)) { 415 printf("%s: bad aperture size %d\n", 416 sc->as_dev.dv_xname, aperture); 417 return EINVAL; 418 } 419 reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I830_GCC0); 420 gcc1 = (u_int16_t)(reg >> 16); 421 gcc1 &= ~AGP_I830_GCC1_GMASIZE; 422 if (aperture == 64 * 1024 * 1024) 423 gcc1 |= AGP_I830_GCC1_GMASIZE_64; 424 else 425 gcc1 |= AGP_I830_GCC1_GMASIZE_128; 426 427 reg &= 0x0000ffff; 428 reg |= ((pcireg_t)gcc1) << 16; 429 pci_conf_write(sc->as_pc, sc->as_tag, AGP_I830_GCC0, reg); 430 } else { /* CHIP_I855 */ 431 if (aperture != 128 * 1024 * 1024) { 432 printf("%s: bad aperture size %d\n", 433 sc->as_dev.dv_xname, aperture); 434 return EINVAL; 435 } 436 } 437 438 return 0; 439 } 440 441 static int 442 agp_i810_bind_page(struct agp_softc *sc, off_t offset, bus_addr_t physical) 443 { 444 struct agp_i810_softc *isc = sc->as_chipc; 445 446 if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT)) { 447 #ifdef DEBUG 448 printf("%s: failed: offset 0x%08x, shift %d, entries %d\n", 449 sc->as_dev.dv_xname, (int)offset, AGP_PAGE_SHIFT, 450 isc->gatt->ag_entries); 451 #endif 452 return EINVAL; 453 } 454 455 if (isc->chiptype != CHIP_I830) { 456 if ((offset >> AGP_PAGE_SHIFT) < isc->stolen) { 457 #ifdef DEBUG 458 printf("%s: trying to bind into stolen memory", 459 sc->as_dev.dv_xname); 460 #endif 461 return EINVAL; 462 } 463 } 464 465 WRITE4(AGP_I810_GTT + (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4, 466 physical | 1); 467 return 0; 468 } 469 470 static int 471 agp_i810_unbind_page(struct agp_softc *sc, off_t offset) 472 { 473 struct agp_i810_softc *isc = sc->as_chipc; 474 475 if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT)) 476 return EINVAL; 477 478 if (isc->chiptype != CHIP_I810 ) { 479 if ((offset >> AGP_PAGE_SHIFT) < isc->stolen) { 480 #ifdef DEBUG 481 printf("%s: trying to unbind from stolen memory", 482 sc->as_dev.dv_xname); 483 #endif 484 return EINVAL; 485 } 486 } 487 488 WRITE4(AGP_I810_GTT + (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4, 0); 489 return 0; 490 } 491 492 /* 493 * Writing via memory mapped registers already flushes all TLBs. 494 */ 495 static void 496 agp_i810_flush_tlb(struct agp_softc *sc) 497 { 498 } 499 500 static int 501 agp_i810_enable(struct agp_softc *sc, u_int32_t mode) 502 { 503 504 return 0; 505 } 506 507 static struct agp_memory * 508 agp_i810_alloc_memory(struct agp_softc *sc, int type, vsize_t size) 509 { 510 struct agp_i810_softc *isc = sc->as_chipc; 511 struct agp_memory *mem; 512 513 if ((size & (AGP_PAGE_SIZE - 1)) != 0) 514 return 0; 515 516 if (sc->as_allocated + size > sc->as_maxmem) 517 return 0; 518 519 if (type == 1) { 520 /* 521 * Mapping local DRAM into GATT. 522 */ 523 if (isc->chiptype != CHIP_I810 ) 524 return 0; 525 if (size != isc->dcache_size) 526 return 0; 527 } else if (type == 2) { 528 /* 529 * Bogus mapping of a single page for the hardware cursor. 530 */ 531 if (size != AGP_PAGE_SIZE) 532 return 0; 533 } 534 535 mem = malloc(sizeof *mem, M_AGP, M_WAITOK|M_ZERO); 536 if (mem == NULL) 537 return NULL; 538 mem->am_id = sc->as_nextid++; 539 mem->am_size = size; 540 mem->am_type = type; 541 542 if (type == 2) { 543 /* 544 * Allocate and wire down the page now so that we can 545 * get its physical address. 546 */ 547 mem->am_dmaseg = malloc(sizeof *mem->am_dmaseg, M_AGP, 548 M_WAITOK); 549 if (mem->am_dmaseg == NULL) { 550 free(mem, M_AGP); 551 return NULL; 552 } 553 if (agp_alloc_dmamem(sc->as_dmat, size, 0, 554 &mem->am_dmamap, &mem->am_virtual, &mem->am_physical, 555 mem->am_dmaseg, 1, &mem->am_nseg) != 0) { 556 free(mem->am_dmaseg, M_AGP); 557 free(mem, M_AGP); 558 return NULL; 559 } 560 } else if (type != 1) { 561 if (bus_dmamap_create(sc->as_dmat, size, size / PAGE_SIZE + 1, 562 size, 0, BUS_DMA_NOWAIT, 563 &mem->am_dmamap) != 0) { 564 free(mem, M_AGP); 565 return NULL; 566 } 567 } 568 569 TAILQ_INSERT_TAIL(&sc->as_memory, mem, am_link); 570 sc->as_allocated += size; 571 572 return mem; 573 } 574 575 static int 576 agp_i810_free_memory(struct agp_softc *sc, struct agp_memory *mem) 577 { 578 if (mem->am_is_bound) 579 return EBUSY; 580 581 if (mem->am_type == 2) { 582 agp_free_dmamem(sc->as_dmat, mem->am_size, mem->am_dmamap, 583 mem->am_virtual, mem->am_dmaseg, mem->am_nseg); 584 free(mem->am_dmaseg, M_AGP); 585 } 586 587 sc->as_allocated -= mem->am_size; 588 TAILQ_REMOVE(&sc->as_memory, mem, am_link); 589 free(mem, M_AGP); 590 return 0; 591 } 592 593 static int 594 agp_i810_bind_memory(struct agp_softc *sc, struct agp_memory *mem, 595 off_t offset) 596 { 597 struct agp_i810_softc *isc = sc->as_chipc; 598 u_int32_t regval, i; 599 600 /* 601 * XXX evil hack: the PGTBL_CTL appearently gets overwritten by the 602 * X server for mysterious reasons which leads to crashes if we write 603 * to the GTT through the MMIO window. 604 * Until the issue is solved, simply restore it. 605 */ 606 regval = bus_space_read_4(isc->bst, isc->bsh, AGP_I810_PGTBL_CTL); 607 if (regval != (isc->gatt->ag_physical | 1)) { 608 printf("agp_i810_bind_memory: PGTBL_CTL is 0x%x - fixing\n", 609 regval); 610 bus_space_write_4(isc->bst, isc->bsh, AGP_I810_PGTBL_CTL, 611 isc->gatt->ag_physical | 1); 612 } 613 614 if (mem->am_type == 2) { 615 WRITE4(AGP_I810_GTT + (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4, 616 mem->am_physical | 1); 617 mem->am_offset = offset; 618 mem->am_is_bound = 1; 619 return 0; 620 } 621 622 if (mem->am_type != 1) 623 return agp_generic_bind_memory(sc, mem, offset); 624 625 if (isc->chiptype != CHIP_I810) 626 return EINVAL; 627 628 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) { 629 WRITE4(AGP_I810_GTT + (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4, 630 i | 3); 631 } 632 mem->am_is_bound = 1; 633 return 0; 634 } 635 636 static int 637 agp_i810_unbind_memory(struct agp_softc *sc, struct agp_memory *mem) 638 { 639 struct agp_i810_softc *isc = sc->as_chipc; 640 u_int32_t i; 641 642 if (mem->am_type == 2) { 643 WRITE4(AGP_I810_GTT + 644 (u_int32_t)(mem->am_offset >> AGP_PAGE_SHIFT) * 4, 645 0); 646 mem->am_offset = 0; 647 mem->am_is_bound = 0; 648 return 0; 649 } 650 651 if (mem->am_type != 1) 652 return agp_generic_unbind_memory(sc, mem); 653 654 if (isc->chiptype != CHIP_I810) 655 return EINVAL; 656 657 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) 658 WRITE4(AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, 0); 659 mem->am_is_bound = 0; 660 return 0; 661 } 662