1 /*- 2 * Copyright (c) 2000 Doug Rabson 3 * Copyright (c) 2000 Ruslan Ermilov 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 /* 29 * Fixes for 830/845G support: David Dawes <dawes@xfree86.org> 30 * 852GM/855GM/865G support added by David Dawes <dawes@xfree86.org> 31 */ 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 #include "opt_bus.h" 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/malloc.h> 41 #include <sys/kernel.h> 42 #include <sys/module.h> 43 #include <sys/bus.h> 44 #include <sys/lock.h> 45 #include <sys/mutex.h> 46 #include <sys/proc.h> 47 48 #include <dev/pci/pcivar.h> 49 #include <dev/pci/pcireg.h> 50 #include <pci/agppriv.h> 51 #include <pci/agpreg.h> 52 53 #include <vm/vm.h> 54 #include <vm/vm_object.h> 55 #include <vm/vm_page.h> 56 #include <vm/vm_pageout.h> 57 #include <vm/pmap.h> 58 59 #include <machine/bus.h> 60 #include <machine/resource.h> 61 #include <sys/rman.h> 62 63 MALLOC_DECLARE(M_AGP); 64 65 #define READ1(off) bus_space_read_1(sc->bst, sc->bsh, off) 66 #define READ4(off) bus_space_read_4(sc->bst, sc->bsh, off) 67 #define WRITE4(off,v) bus_space_write_4(sc->bst, sc->bsh, off, v) 68 #define WRITEGTT(off,v) bus_space_write_4(sc->gtt_bst, sc->gtt_bsh, off, v) 69 70 #define CHIP_I810 0 /* i810/i815 */ 71 #define CHIP_I830 1 /* 830M/845G */ 72 #define CHIP_I855 2 /* 852GM/855GM/865G */ 73 #define CHIP_I915 3 /* 915G/915GM */ 74 75 struct agp_i810_softc { 76 struct agp_softc agp; 77 u_int32_t initial_aperture; /* aperture size at startup */ 78 struct agp_gatt *gatt; 79 int chiptype; /* i810-like or i830 */ 80 u_int32_t dcache_size; /* i810 only */ 81 u_int32_t stolen; /* number of i830/845 gtt entries for stolen memory */ 82 device_t bdev; /* bridge device */ 83 84 struct resource *regs; /* memory mapped GC registers */ 85 bus_space_tag_t bst; /* bus_space tag */ 86 bus_space_handle_t bsh; /* bus_space handle */ 87 88 struct resource *gtt; /* memory mapped GATT entries */ 89 bus_space_tag_t gtt_bst; /* bus_space tag */ 90 bus_space_handle_t gtt_bsh; /* bus_space handle */ 91 }; 92 93 static const char* 94 agp_i810_match(device_t dev) 95 { 96 if (pci_get_class(dev) != PCIC_DISPLAY 97 || pci_get_subclass(dev) != PCIS_DISPLAY_VGA) 98 return NULL; 99 100 switch (pci_get_devid(dev)) { 101 case 0x71218086: 102 return ("Intel 82810 (i810 GMCH) SVGA controller"); 103 104 case 0x71238086: 105 return ("Intel 82810-DC100 (i810-DC100 GMCH) SVGA controller"); 106 107 case 0x71258086: 108 return ("Intel 82810E (i810E GMCH) SVGA controller"); 109 110 case 0x11328086: 111 return ("Intel 82815 (i815 GMCH) SVGA controller"); 112 113 case 0x35778086: 114 return ("Intel 82830M (830M GMCH) SVGA controller"); 115 116 case 0x25628086: 117 return ("Intel 82845G (845G GMCH) SVGA controller"); 118 119 case 0x35828086: 120 switch (pci_read_config(dev, AGP_I85X_CAPID, 1)) { 121 case AGP_I855_GME: 122 return ("Intel 82855GME (855GME GMCH) SVGA controller"); 123 124 case AGP_I855_GM: 125 return ("Intel 82855GM (855GM GMCH) SVGA controller"); 126 127 case AGP_I852_GME: 128 return ("Intel 82852GME (852GME GMCH) SVGA controller"); 129 130 case AGP_I852_GM: 131 return ("Intel 82852GM (852GM GMCH) SVGA controller"); 132 133 default: 134 return ("Intel 8285xM (85xGM GMCH) SVGA controller"); 135 } 136 137 case 0x25728086: 138 return ("Intel 82865G (865G GMCH) SVGA controller"); 139 140 case 0x25828086: 141 return ("Intel 82915G (915G GMCH) SVGA controller"); 142 143 case 0x25928086: 144 return ("Intel 82915GM (915GM GMCH) SVGA controller"); 145 }; 146 147 return NULL; 148 } 149 150 /* 151 * Find bridge device. 152 */ 153 static device_t 154 agp_i810_find_bridge(device_t dev) 155 { 156 device_t *children, child; 157 int nchildren, i; 158 u_int32_t devid; 159 160 /* 161 * Calculate bridge device's ID. 162 */ 163 devid = pci_get_devid(dev); 164 switch (devid) { 165 case 0x71218086: 166 case 0x71238086: 167 case 0x71258086: 168 devid -= 0x10000; 169 break; 170 171 case 0x11328086: 172 case 0x35778086: 173 case 0x25628086: 174 case 0x35828086: 175 case 0x25728086: 176 case 0x25828086: 177 case 0x25928086: 178 devid -= 0x20000; 179 break; 180 }; 181 if (device_get_children(device_get_parent(device_get_parent(dev)), 182 &children, &nchildren)) 183 return 0; 184 185 for (i = 0; i < nchildren; i++) { 186 child = children[i]; 187 188 if (pci_get_devid(child) == devid) { 189 free(children, M_TEMP); 190 return child; 191 } 192 } 193 free(children, M_TEMP); 194 return 0; 195 } 196 197 static int 198 agp_i810_probe(device_t dev) 199 { 200 const char *desc; 201 202 if (resource_disabled("agp", device_get_unit(dev))) 203 return (ENXIO); 204 desc = agp_i810_match(dev); 205 if (desc) { 206 device_t bdev; 207 u_int8_t smram; 208 unsigned int gcc1; 209 int devid = pci_get_devid(dev); 210 211 bdev = agp_i810_find_bridge(dev); 212 if (!bdev) { 213 if (bootverbose) 214 printf("I810: can't find bridge device\n"); 215 return ENXIO; 216 } 217 218 /* 219 * checking whether internal graphics device has been activated. 220 */ 221 switch (devid) { 222 /* i810 */ 223 case 0x71218086: 224 case 0x71238086: 225 case 0x71258086: 226 case 0x11328086: 227 smram = pci_read_config(bdev, AGP_I810_SMRAM, 1); 228 if ((smram & AGP_I810_SMRAM_GMS) 229 == AGP_I810_SMRAM_GMS_DISABLED) { 230 if (bootverbose) 231 printf("I810: disabled, not probing\n"); 232 return ENXIO; 233 } 234 break; 235 236 /* i830 */ 237 case 0x35778086: 238 case 0x35828086: 239 case 0x25628086: 240 case 0x25728086: 241 gcc1 = pci_read_config(bdev, AGP_I830_GCC1, 1); 242 if ((gcc1 & AGP_I830_GCC1_DEV2) == AGP_I830_GCC1_DEV2_DISABLED) { 243 if (bootverbose) 244 printf("I830: disabled, not probing\n"); 245 return ENXIO; 246 } 247 break; 248 249 /* i915 */ 250 case 0x25828086: 251 case 0x25928086: 252 gcc1 = pci_read_config(bdev, AGP_I915_DEVEN, 4); 253 if ((gcc1 & AGP_I915_DEVEN_D2F0) == 254 AGP_I915_DEVEN_D2F0_DISABLED) { 255 if (bootverbose) 256 printf("I915: disabled, not probing\n"); 257 return ENXIO; 258 } 259 break; 260 261 default: 262 return ENXIO; 263 } 264 265 device_set_desc(dev, desc); 266 return BUS_PROBE_DEFAULT; 267 } 268 269 return ENXIO; 270 } 271 272 static int 273 agp_i810_attach(device_t dev) 274 { 275 struct agp_i810_softc *sc = device_get_softc(dev); 276 struct agp_gatt *gatt; 277 int error, rid; 278 279 sc->bdev = agp_i810_find_bridge(dev); 280 if (!sc->bdev) 281 return ENOENT; 282 283 error = agp_generic_attach(dev); 284 if (error) 285 return error; 286 287 switch (pci_get_devid(dev)) { 288 case 0x71218086: 289 case 0x71238086: 290 case 0x71258086: 291 case 0x11328086: 292 sc->chiptype = CHIP_I810; 293 break; 294 case 0x35778086: 295 case 0x25628086: 296 sc->chiptype = CHIP_I830; 297 break; 298 case 0x35828086: 299 case 0x25728086: 300 sc->chiptype = CHIP_I855; 301 break; 302 case 0x25828086: 303 case 0x25928086: 304 sc->chiptype = CHIP_I915; 305 break; 306 }; 307 308 /* Same for i810 and i830 */ 309 if (sc->chiptype == CHIP_I915) 310 rid = AGP_I915_MMADR; 311 else 312 rid = AGP_I810_MMADR; 313 314 sc->regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 315 RF_ACTIVE); 316 if (!sc->regs) { 317 agp_generic_detach(dev); 318 return ENODEV; 319 } 320 sc->bst = rman_get_bustag(sc->regs); 321 sc->bsh = rman_get_bushandle(sc->regs); 322 323 if (sc->chiptype == CHIP_I915) { 324 rid = AGP_I915_GTTADR; 325 sc->gtt = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 326 RF_ACTIVE); 327 if (!sc->gtt) { 328 bus_release_resource(dev, SYS_RES_MEMORY, 329 AGP_I810_MMADR, sc->regs); 330 agp_generic_detach(dev); 331 return ENODEV; 332 } 333 sc->gtt_bst = rman_get_bustag(sc->gtt); 334 sc->gtt_bsh = rman_get_bushandle(sc->gtt); 335 } 336 337 sc->initial_aperture = AGP_GET_APERTURE(dev); 338 339 gatt = malloc( sizeof(struct agp_gatt), M_AGP, M_NOWAIT); 340 if (!gatt) { 341 agp_generic_detach(dev); 342 return ENOMEM; 343 } 344 sc->gatt = gatt; 345 346 gatt->ag_entries = AGP_GET_APERTURE(dev) >> AGP_PAGE_SHIFT; 347 348 if ( sc->chiptype == CHIP_I810 ) { 349 /* Some i810s have on-chip memory called dcache */ 350 if (READ1(AGP_I810_DRT) & AGP_I810_DRT_POPULATED) 351 sc->dcache_size = 4 * 1024 * 1024; 352 else 353 sc->dcache_size = 0; 354 355 /* According to the specs the gatt on the i810 must be 64k */ 356 gatt->ag_virtual = contigmalloc( 64 * 1024, M_AGP, 0, 357 0, ~0, PAGE_SIZE, 0); 358 if (!gatt->ag_virtual) { 359 if (bootverbose) 360 device_printf(dev, "contiguous allocation failed\n"); 361 free(gatt, M_AGP); 362 agp_generic_detach(dev); 363 return ENOMEM; 364 } 365 bzero(gatt->ag_virtual, gatt->ag_entries * sizeof(u_int32_t)); 366 367 gatt->ag_physical = vtophys((vm_offset_t) gatt->ag_virtual); 368 agp_flush_cache(); 369 /* Install the GATT. */ 370 WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1); 371 } else if ( sc->chiptype == CHIP_I830 ) { 372 /* The i830 automatically initializes the 128k gatt on boot. */ 373 unsigned int gcc1, pgtblctl; 374 375 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 1); 376 switch (gcc1 & AGP_I830_GCC1_GMS) { 377 case AGP_I830_GCC1_GMS_STOLEN_512: 378 sc->stolen = (512 - 132) * 1024 / 4096; 379 break; 380 case AGP_I830_GCC1_GMS_STOLEN_1024: 381 sc->stolen = (1024 - 132) * 1024 / 4096; 382 break; 383 case AGP_I830_GCC1_GMS_STOLEN_8192: 384 sc->stolen = (8192 - 132) * 1024 / 4096; 385 break; 386 default: 387 sc->stolen = 0; 388 device_printf(dev, "unknown memory configuration, disabling\n"); 389 agp_generic_detach(dev); 390 return EINVAL; 391 } 392 if (sc->stolen > 0) 393 device_printf(dev, "detected %dk stolen memory\n", sc->stolen * 4); 394 device_printf(dev, "aperture size is %dM\n", sc->initial_aperture / 1024 / 1024); 395 396 /* GATT address is already in there, make sure it's enabled */ 397 pgtblctl = READ4(AGP_I810_PGTBL_CTL); 398 pgtblctl |= 1; 399 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl); 400 401 gatt->ag_physical = pgtblctl & ~1; 402 } else if (sc->chiptype == CHIP_I855 || sc->chiptype == CHIP_I915) { /* CHIP_I855 */ 403 unsigned int gcc1, pgtblctl, stolen; 404 405 /* Stolen memory is set up at the beginning of the aperture by 406 * the BIOS, consisting of the GATT followed by 4kb for the BIOS 407 * display. 408 */ 409 if (sc->chiptype == CHIP_I855) 410 stolen = 132; 411 else 412 stolen = 260; 413 414 gcc1 = pci_read_config(sc->bdev, AGP_I855_GCC1, 1); 415 switch (gcc1 & AGP_I855_GCC1_GMS) { 416 case AGP_I855_GCC1_GMS_STOLEN_1M: 417 sc->stolen = (1024 - stolen) * 1024 / 4096; 418 break; 419 case AGP_I855_GCC1_GMS_STOLEN_4M: 420 sc->stolen = (4096 - stolen) * 1024 / 4096; 421 break; 422 case AGP_I855_GCC1_GMS_STOLEN_8M: 423 sc->stolen = (8192 - stolen) * 1024 / 4096; 424 break; 425 case AGP_I855_GCC1_GMS_STOLEN_16M: 426 sc->stolen = (16384 - stolen) * 1024 / 4096; 427 break; 428 case AGP_I855_GCC1_GMS_STOLEN_32M: 429 sc->stolen = (32768 - stolen) * 1024 / 4096; 430 break; 431 case AGP_I915_GCC1_GMS_STOLEN_48M: 432 sc->stolen = (49152 - stolen) * 1024 / 4096; 433 break; 434 case AGP_I915_GCC1_GMS_STOLEN_64M: 435 sc->stolen = (65536 - stolen) * 1024 / 4096; 436 break; 437 default: 438 sc->stolen = 0; 439 device_printf(dev, "unknown memory configuration, disabling\n"); 440 agp_generic_detach(dev); 441 return EINVAL; 442 } 443 if (sc->stolen > 0) 444 device_printf(dev, "detected %dk stolen memory\n", sc->stolen * 4); 445 device_printf(dev, "aperture size is %dM\n", sc->initial_aperture / 1024 / 1024); 446 447 /* GATT address is already in there, make sure it's enabled */ 448 pgtblctl = READ4(AGP_I810_PGTBL_CTL); 449 pgtblctl |= 1; 450 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl); 451 452 gatt->ag_physical = pgtblctl & ~1; 453 } 454 455 return 0; 456 } 457 458 static int 459 agp_i810_detach(device_t dev) 460 { 461 struct agp_i810_softc *sc = device_get_softc(dev); 462 int error; 463 464 error = agp_generic_detach(dev); 465 if (error) 466 return error; 467 468 /* Clear the GATT base. */ 469 if ( sc->chiptype == CHIP_I810 ) { 470 WRITE4(AGP_I810_PGTBL_CTL, 0); 471 } else { 472 unsigned int pgtblctl; 473 pgtblctl = READ4(AGP_I810_PGTBL_CTL); 474 pgtblctl &= ~1; 475 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl); 476 } 477 478 /* Put the aperture back the way it started. */ 479 AGP_SET_APERTURE(dev, sc->initial_aperture); 480 481 if ( sc->chiptype == CHIP_I810 ) { 482 contigfree(sc->gatt->ag_virtual, 64 * 1024, M_AGP); 483 } 484 free(sc->gatt, M_AGP); 485 486 if (sc->chiptype == CHIP_I915) { 487 bus_release_resource(dev, SYS_RES_MEMORY, AGP_I915_GTTADR, 488 sc->gtt); 489 bus_release_resource(dev, SYS_RES_MEMORY, AGP_I915_MMADR, 490 sc->regs); 491 } else { 492 bus_release_resource(dev, SYS_RES_MEMORY, AGP_I810_MMADR, 493 sc->regs); 494 } 495 496 return 0; 497 } 498 499 static u_int32_t 500 agp_i810_get_aperture(device_t dev) 501 { 502 struct agp_i810_softc *sc = device_get_softc(dev); 503 uint32_t temp; 504 u_int16_t miscc; 505 506 switch (sc->chiptype) { 507 case CHIP_I810: 508 miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2); 509 if ((miscc & AGP_I810_MISCC_WINSIZE) == AGP_I810_MISCC_WINSIZE_32) 510 return 32 * 1024 * 1024; 511 else 512 return 64 * 1024 * 1024; 513 case CHIP_I830: 514 temp = pci_read_config(sc->bdev, AGP_I830_GCC1, 2); 515 if ((temp & AGP_I830_GCC1_GMASIZE) == AGP_I830_GCC1_GMASIZE_64) 516 return 64 * 1024 * 1024; 517 else 518 return 128 * 1024 * 1024; 519 case CHIP_I855: 520 return 128 * 1024 * 1024; 521 case CHIP_I915: 522 temp = pci_read_config(dev, AGP_I915_MSAC, 1); 523 if ((temp & AGP_I915_MSAC_GMASIZE) == 524 AGP_I915_MSAC_GMASIZE_128) { 525 return 128 * 1024 * 1024; 526 } else { 527 return 256 * 1024 * 1024; 528 } 529 } 530 531 return 0; 532 } 533 534 static int 535 agp_i810_set_aperture(device_t dev, u_int32_t aperture) 536 { 537 struct agp_i810_softc *sc = device_get_softc(dev); 538 u_int16_t miscc, gcc1; 539 u_int32_t temp; 540 541 switch (sc->chiptype) { 542 case CHIP_I810: 543 /* 544 * Double check for sanity. 545 */ 546 if (aperture != 32 * 1024 * 1024 && aperture != 64 * 1024 * 1024) { 547 device_printf(dev, "bad aperture size %d\n", aperture); 548 return EINVAL; 549 } 550 551 miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2); 552 miscc &= ~AGP_I810_MISCC_WINSIZE; 553 if (aperture == 32 * 1024 * 1024) 554 miscc |= AGP_I810_MISCC_WINSIZE_32; 555 else 556 miscc |= AGP_I810_MISCC_WINSIZE_64; 557 558 pci_write_config(sc->bdev, AGP_I810_MISCC, miscc, 2); 559 break; 560 case CHIP_I830: 561 if (aperture != 64 * 1024 * 1024 && 562 aperture != 128 * 1024 * 1024) { 563 device_printf(dev, "bad aperture size %d\n", aperture); 564 return EINVAL; 565 } 566 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2); 567 gcc1 &= ~AGP_I830_GCC1_GMASIZE; 568 if (aperture == 64 * 1024 * 1024) 569 gcc1 |= AGP_I830_GCC1_GMASIZE_64; 570 else 571 gcc1 |= AGP_I830_GCC1_GMASIZE_128; 572 573 pci_write_config(sc->bdev, AGP_I830_GCC1, gcc1, 2); 574 break; 575 case CHIP_I855: 576 if (aperture != 128 * 1024 * 1024) { 577 device_printf(dev, "bad aperture size %d\n", aperture); 578 return EINVAL; 579 } 580 break; 581 case CHIP_I915: 582 temp = pci_read_config(dev, AGP_I915_MSAC, 1); 583 temp &= ~AGP_I915_MSAC_GMASIZE; 584 585 switch (aperture) { 586 case 128 * 1024 * 1024: 587 temp |= AGP_I915_MSAC_GMASIZE_128; 588 break; 589 case 256 * 1024 * 1024: 590 temp |= AGP_I915_MSAC_GMASIZE_256; 591 break; 592 default: 593 device_printf(dev, "bad aperture size %d\n", aperture); 594 return EINVAL; 595 } 596 597 pci_write_config(dev, AGP_I915_MSAC, temp, 1); 598 break; 599 } 600 601 return 0; 602 } 603 604 static int 605 agp_i810_bind_page(device_t dev, int offset, vm_offset_t physical) 606 { 607 struct agp_i810_softc *sc = device_get_softc(dev); 608 609 if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) { 610 device_printf(dev, "failed: offset is 0x%08x, shift is %d, entries is %d\n", offset, AGP_PAGE_SHIFT, sc->gatt->ag_entries); 611 return EINVAL; 612 } 613 614 if ( sc->chiptype != CHIP_I810 ) { 615 if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) { 616 device_printf(dev, "trying to bind into stolen memory"); 617 return EINVAL; 618 } 619 } 620 621 if (sc->chiptype == CHIP_I915) { 622 WRITEGTT((offset >> AGP_PAGE_SHIFT) * 4, physical | 1); 623 } else { 624 WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, physical | 1); 625 } 626 627 return 0; 628 } 629 630 static int 631 agp_i810_unbind_page(device_t dev, int offset) 632 { 633 struct agp_i810_softc *sc = device_get_softc(dev); 634 635 if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) 636 return EINVAL; 637 638 if ( sc->chiptype != CHIP_I810 ) { 639 if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) { 640 device_printf(dev, "trying to unbind from stolen memory"); 641 return EINVAL; 642 } 643 } 644 645 if (sc->chiptype == CHIP_I915) { 646 WRITEGTT((offset >> AGP_PAGE_SHIFT) * 4, 0); 647 } else { 648 WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, 0); 649 } 650 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(device_t dev) 659 { 660 } 661 662 static int 663 agp_i810_enable(device_t dev, u_int32_t mode) 664 { 665 666 return 0; 667 } 668 669 static struct agp_memory * 670 agp_i810_alloc_memory(device_t dev, int type, vm_size_t size) 671 { 672 struct agp_i810_softc *sc = device_get_softc(dev); 673 struct agp_memory *mem; 674 675 if ((size & (AGP_PAGE_SIZE - 1)) != 0) 676 return 0; 677 678 if (sc->agp.as_allocated + size > sc->agp.as_maxmem) 679 return 0; 680 681 if (type == 1) { 682 /* 683 * Mapping local DRAM into GATT. 684 */ 685 if ( sc->chiptype != CHIP_I810 ) 686 return 0; 687 if (size != sc->dcache_size) 688 return 0; 689 } else if (type == 2) { 690 /* 691 * Bogus mapping of a single page for the hardware cursor. 692 */ 693 if (size != AGP_PAGE_SIZE) 694 return 0; 695 } 696 697 mem = malloc(sizeof *mem, M_AGP, M_WAITOK); 698 mem->am_id = sc->agp.as_nextid++; 699 mem->am_size = size; 700 mem->am_type = type; 701 if (type != 1) 702 mem->am_obj = vm_object_allocate(OBJT_DEFAULT, 703 atop(round_page(size))); 704 else 705 mem->am_obj = 0; 706 707 if (type == 2) { 708 /* 709 * Allocate and wire down the page now so that we can 710 * get its physical address. 711 */ 712 vm_page_t m; 713 714 VM_OBJECT_LOCK(mem->am_obj); 715 m = vm_page_grab(mem->am_obj, 0, VM_ALLOC_NOBUSY | 716 VM_ALLOC_WIRED | VM_ALLOC_ZERO | VM_ALLOC_RETRY); 717 VM_OBJECT_UNLOCK(mem->am_obj); 718 mem->am_physical = VM_PAGE_TO_PHYS(m); 719 } else { 720 mem->am_physical = 0; 721 } 722 723 mem->am_offset = 0; 724 mem->am_is_bound = 0; 725 TAILQ_INSERT_TAIL(&sc->agp.as_memory, mem, am_link); 726 sc->agp.as_allocated += size; 727 728 return mem; 729 } 730 731 static int 732 agp_i810_free_memory(device_t dev, struct agp_memory *mem) 733 { 734 struct agp_i810_softc *sc = device_get_softc(dev); 735 736 if (mem->am_is_bound) 737 return EBUSY; 738 739 if (mem->am_type == 2) { 740 /* 741 * Unwire the page which we wired in alloc_memory. 742 */ 743 vm_page_t m; 744 745 VM_OBJECT_LOCK(mem->am_obj); 746 m = vm_page_lookup(mem->am_obj, 0); 747 VM_OBJECT_UNLOCK(mem->am_obj); 748 vm_page_lock_queues(); 749 vm_page_unwire(m, 0); 750 vm_page_unlock_queues(); 751 } 752 753 sc->agp.as_allocated -= mem->am_size; 754 TAILQ_REMOVE(&sc->agp.as_memory, mem, am_link); 755 if (mem->am_obj) 756 vm_object_deallocate(mem->am_obj); 757 free(mem, M_AGP); 758 return 0; 759 } 760 761 static int 762 agp_i810_bind_memory(device_t dev, struct agp_memory *mem, 763 vm_offset_t offset) 764 { 765 struct agp_i810_softc *sc = device_get_softc(dev); 766 vm_offset_t i; 767 768 if (mem->am_type != 1) 769 return agp_generic_bind_memory(dev, mem, offset); 770 771 if ( sc->chiptype != CHIP_I810 ) 772 return EINVAL; 773 774 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) { 775 WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, 776 i | 3); 777 } 778 779 return 0; 780 } 781 782 static int 783 agp_i810_unbind_memory(device_t dev, struct agp_memory *mem) 784 { 785 struct agp_i810_softc *sc = device_get_softc(dev); 786 vm_offset_t i; 787 788 if (mem->am_type != 1) 789 return agp_generic_unbind_memory(dev, mem); 790 791 if ( sc->chiptype != CHIP_I810 ) 792 return EINVAL; 793 794 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) 795 WRITE4(AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, 0); 796 797 return 0; 798 } 799 800 static device_method_t agp_i810_methods[] = { 801 /* Device interface */ 802 DEVMETHOD(device_probe, agp_i810_probe), 803 DEVMETHOD(device_attach, agp_i810_attach), 804 DEVMETHOD(device_detach, agp_i810_detach), 805 806 /* AGP interface */ 807 DEVMETHOD(agp_get_aperture, agp_i810_get_aperture), 808 DEVMETHOD(agp_set_aperture, agp_i810_set_aperture), 809 DEVMETHOD(agp_bind_page, agp_i810_bind_page), 810 DEVMETHOD(agp_unbind_page, agp_i810_unbind_page), 811 DEVMETHOD(agp_flush_tlb, agp_i810_flush_tlb), 812 DEVMETHOD(agp_enable, agp_i810_enable), 813 DEVMETHOD(agp_alloc_memory, agp_i810_alloc_memory), 814 DEVMETHOD(agp_free_memory, agp_i810_free_memory), 815 DEVMETHOD(agp_bind_memory, agp_i810_bind_memory), 816 DEVMETHOD(agp_unbind_memory, agp_i810_unbind_memory), 817 818 { 0, 0 } 819 }; 820 821 static driver_t agp_i810_driver = { 822 "agp", 823 agp_i810_methods, 824 sizeof(struct agp_i810_softc), 825 }; 826 827 static devclass_t agp_devclass; 828 829 DRIVER_MODULE(agp_i810, vgapci, agp_i810_driver, agp_devclass, 0, 0); 830 MODULE_DEPEND(agp_i810, agp, 1, 1, 1); 831 MODULE_DEPEND(agp_i810, pci, 1, 1, 1); 832