agp_i810.c revision 158655
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: head/sys/dev/agp/agp_i810.c 158655 2006-05-16 16:19:48Z anholt $"); 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 63MALLOC_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 75struct 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 void *argb_cursor; /* contigmalloc area for ARGB cursor */ 93}; 94 95static const char* 96agp_i810_match(device_t dev) 97{ 98 if (pci_get_class(dev) != PCIC_DISPLAY 99 || pci_get_subclass(dev) != PCIS_DISPLAY_VGA) 100 return NULL; 101 102 switch (pci_get_devid(dev)) { 103 case 0x71218086: 104 return ("Intel 82810 (i810 GMCH) SVGA controller"); 105 106 case 0x71238086: 107 return ("Intel 82810-DC100 (i810-DC100 GMCH) SVGA controller"); 108 109 case 0x71258086: 110 return ("Intel 82810E (i810E GMCH) SVGA controller"); 111 112 case 0x11328086: 113 return ("Intel 82815 (i815 GMCH) SVGA controller"); 114 115 case 0x35778086: 116 return ("Intel 82830M (830M GMCH) SVGA controller"); 117 118 case 0x25628086: 119 return ("Intel 82845G (845G GMCH) SVGA controller"); 120 121 case 0x35828086: 122 switch (pci_read_config(dev, AGP_I85X_CAPID, 1)) { 123 case AGP_I855_GME: 124 return ("Intel 82855GME (855GME GMCH) SVGA controller"); 125 126 case AGP_I855_GM: 127 return ("Intel 82855GM (855GM GMCH) SVGA controller"); 128 129 case AGP_I852_GME: 130 return ("Intel 82852GME (852GME GMCH) SVGA controller"); 131 132 case AGP_I852_GM: 133 return ("Intel 82852GM (852GM GMCH) SVGA controller"); 134 135 default: 136 return ("Intel 8285xM (85xGM GMCH) SVGA controller"); 137 } 138 139 case 0x25728086: 140 return ("Intel 82865G (865G GMCH) SVGA controller"); 141 142 case 0x25828086: 143 return ("Intel 82915G (915G GMCH) SVGA controller"); 144 145 case 0x25928086: 146 return ("Intel 82915GM (915GM GMCH) SVGA controller"); 147 }; 148 149 return NULL; 150} 151 152/* 153 * Find bridge device. 154 */ 155static device_t 156agp_i810_find_bridge(device_t dev) 157{ 158 device_t *children, child; 159 int nchildren, i; 160 u_int32_t devid; 161 162 /* 163 * Calculate bridge device's ID. 164 */ 165 devid = pci_get_devid(dev); 166 switch (devid) { 167 case 0x71218086: 168 case 0x71238086: 169 case 0x71258086: 170 devid -= 0x10000; 171 break; 172 173 case 0x11328086: 174 case 0x35778086: 175 case 0x25628086: 176 case 0x35828086: 177 case 0x25728086: 178 case 0x25828086: 179 case 0x25928086: 180 devid -= 0x20000; 181 break; 182 }; 183 if (device_get_children(device_get_parent(device_get_parent(dev)), 184 &children, &nchildren)) 185 return 0; 186 187 for (i = 0; i < nchildren; i++) { 188 child = children[i]; 189 190 if (pci_get_devid(child) == devid) { 191 free(children, M_TEMP); 192 return child; 193 } 194 } 195 free(children, M_TEMP); 196 return 0; 197} 198 199static void 200agp_i810_identify(driver_t *driver, device_t parent) 201{ 202 203 if (device_find_child(parent, "agp", -1) == NULL && 204 agp_i810_match(parent)) 205 device_add_child(parent, "agp", -1); 206} 207 208static int 209agp_i810_probe(device_t dev) 210{ 211 const char *desc; 212 213 if (resource_disabled("agp", device_get_unit(dev))) 214 return (ENXIO); 215 desc = agp_i810_match(dev); 216 if (desc) { 217 device_t bdev; 218 u_int8_t smram; 219 unsigned int gcc1; 220 int devid = pci_get_devid(dev); 221 222 bdev = agp_i810_find_bridge(dev); 223 if (!bdev) { 224 if (bootverbose) 225 printf("I810: can't find bridge device\n"); 226 return ENXIO; 227 } 228 229 /* 230 * checking whether internal graphics device has been activated. 231 */ 232 switch (devid) { 233 /* i810 */ 234 case 0x71218086: 235 case 0x71238086: 236 case 0x71258086: 237 case 0x11328086: 238 smram = pci_read_config(bdev, AGP_I810_SMRAM, 1); 239 if ((smram & AGP_I810_SMRAM_GMS) 240 == AGP_I810_SMRAM_GMS_DISABLED) { 241 if (bootverbose) 242 printf("I810: disabled, not probing\n"); 243 return ENXIO; 244 } 245 break; 246 247 /* i830 */ 248 case 0x35778086: 249 case 0x35828086: 250 case 0x25628086: 251 case 0x25728086: 252 gcc1 = pci_read_config(bdev, AGP_I830_GCC1, 1); 253 if ((gcc1 & AGP_I830_GCC1_DEV2) == AGP_I830_GCC1_DEV2_DISABLED) { 254 if (bootverbose) 255 printf("I830: disabled, not probing\n"); 256 return ENXIO; 257 } 258 break; 259 260 /* i915 */ 261 case 0x25828086: 262 case 0x25928086: 263 gcc1 = pci_read_config(bdev, AGP_I915_DEVEN, 4); 264 if ((gcc1 & AGP_I915_DEVEN_D2F0) == 265 AGP_I915_DEVEN_D2F0_DISABLED) { 266 if (bootverbose) 267 printf("I915: disabled, not probing\n"); 268 return ENXIO; 269 } 270 break; 271 272 default: 273 return ENXIO; 274 } 275 276 device_set_desc(dev, desc); 277 return BUS_PROBE_DEFAULT; 278 } 279 280 return ENXIO; 281} 282 283static int 284agp_i810_attach(device_t dev) 285{ 286 struct agp_i810_softc *sc = device_get_softc(dev); 287 struct agp_gatt *gatt; 288 int error, rid; 289 290 sc->bdev = agp_i810_find_bridge(dev); 291 if (!sc->bdev) 292 return ENOENT; 293 294 error = agp_generic_attach(dev); 295 if (error) 296 return error; 297 298 switch (pci_get_devid(dev)) { 299 case 0x71218086: 300 case 0x71238086: 301 case 0x71258086: 302 case 0x11328086: 303 sc->chiptype = CHIP_I810; 304 break; 305 case 0x35778086: 306 case 0x25628086: 307 sc->chiptype = CHIP_I830; 308 break; 309 case 0x35828086: 310 case 0x25728086: 311 sc->chiptype = CHIP_I855; 312 break; 313 case 0x25828086: 314 case 0x25928086: 315 sc->chiptype = CHIP_I915; 316 break; 317 }; 318 319 /* Same for i810 and i830 */ 320 if (sc->chiptype == CHIP_I915) 321 rid = AGP_I915_MMADR; 322 else 323 rid = AGP_I810_MMADR; 324 325 sc->regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 326 RF_ACTIVE); 327 if (!sc->regs) { 328 agp_generic_detach(dev); 329 return ENODEV; 330 } 331 sc->bst = rman_get_bustag(sc->regs); 332 sc->bsh = rman_get_bushandle(sc->regs); 333 334 if (sc->chiptype == CHIP_I915) { 335 rid = AGP_I915_GTTADR; 336 sc->gtt = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 337 RF_ACTIVE); 338 if (!sc->gtt) { 339 bus_release_resource(dev, SYS_RES_MEMORY, 340 AGP_I810_MMADR, sc->regs); 341 agp_generic_detach(dev); 342 return ENODEV; 343 } 344 sc->gtt_bst = rman_get_bustag(sc->gtt); 345 sc->gtt_bsh = rman_get_bushandle(sc->gtt); 346 } 347 348 sc->initial_aperture = AGP_GET_APERTURE(dev); 349 350 gatt = malloc( sizeof(struct agp_gatt), M_AGP, M_NOWAIT); 351 if (!gatt) { 352 agp_generic_detach(dev); 353 return ENOMEM; 354 } 355 sc->gatt = gatt; 356 357 gatt->ag_entries = AGP_GET_APERTURE(dev) >> AGP_PAGE_SHIFT; 358 359 if ( sc->chiptype == CHIP_I810 ) { 360 /* Some i810s have on-chip memory called dcache */ 361 if (READ1(AGP_I810_DRT) & AGP_I810_DRT_POPULATED) 362 sc->dcache_size = 4 * 1024 * 1024; 363 else 364 sc->dcache_size = 0; 365 366 /* According to the specs the gatt on the i810 must be 64k */ 367 gatt->ag_virtual = contigmalloc( 64 * 1024, M_AGP, 0, 368 0, ~0, PAGE_SIZE, 0); 369 if (!gatt->ag_virtual) { 370 if (bootverbose) 371 device_printf(dev, "contiguous allocation failed\n"); 372 free(gatt, M_AGP); 373 agp_generic_detach(dev); 374 return ENOMEM; 375 } 376 bzero(gatt->ag_virtual, gatt->ag_entries * sizeof(u_int32_t)); 377 378 gatt->ag_physical = vtophys((vm_offset_t) gatt->ag_virtual); 379 agp_flush_cache(); 380 /* Install the GATT. */ 381 WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1); 382 } else if ( sc->chiptype == CHIP_I830 ) { 383 /* The i830 automatically initializes the 128k gatt on boot. */ 384 unsigned int gcc1, pgtblctl; 385 386 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 1); 387 switch (gcc1 & AGP_I830_GCC1_GMS) { 388 case AGP_I830_GCC1_GMS_STOLEN_512: 389 sc->stolen = (512 - 132) * 1024 / 4096; 390 break; 391 case AGP_I830_GCC1_GMS_STOLEN_1024: 392 sc->stolen = (1024 - 132) * 1024 / 4096; 393 break; 394 case AGP_I830_GCC1_GMS_STOLEN_8192: 395 sc->stolen = (8192 - 132) * 1024 / 4096; 396 break; 397 default: 398 sc->stolen = 0; 399 device_printf(dev, "unknown memory configuration, disabling\n"); 400 agp_generic_detach(dev); 401 return EINVAL; 402 } 403 if (sc->stolen > 0) 404 device_printf(dev, "detected %dk stolen memory\n", sc->stolen * 4); 405 device_printf(dev, "aperture size is %dM\n", sc->initial_aperture / 1024 / 1024); 406 407 /* GATT address is already in there, make sure it's enabled */ 408 pgtblctl = READ4(AGP_I810_PGTBL_CTL); 409 pgtblctl |= 1; 410 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl); 411 412 gatt->ag_physical = pgtblctl & ~1; 413 } else if (sc->chiptype == CHIP_I855 || sc->chiptype == CHIP_I915) { /* CHIP_I855 */ 414 unsigned int gcc1, pgtblctl, stolen; 415 416 /* Stolen memory is set up at the beginning of the aperture by 417 * the BIOS, consisting of the GATT followed by 4kb for the BIOS 418 * display. 419 */ 420 if (sc->chiptype == CHIP_I855) 421 stolen = 132; 422 else 423 stolen = 260; 424 425 gcc1 = pci_read_config(sc->bdev, AGP_I855_GCC1, 1); 426 switch (gcc1 & AGP_I855_GCC1_GMS) { 427 case AGP_I855_GCC1_GMS_STOLEN_1M: 428 sc->stolen = (1024 - stolen) * 1024 / 4096; 429 break; 430 case AGP_I855_GCC1_GMS_STOLEN_4M: 431 sc->stolen = (4096 - stolen) * 1024 / 4096; 432 break; 433 case AGP_I855_GCC1_GMS_STOLEN_8M: 434 sc->stolen = (8192 - stolen) * 1024 / 4096; 435 break; 436 case AGP_I855_GCC1_GMS_STOLEN_16M: 437 sc->stolen = (16384 - stolen) * 1024 / 4096; 438 break; 439 case AGP_I855_GCC1_GMS_STOLEN_32M: 440 sc->stolen = (32768 - stolen) * 1024 / 4096; 441 break; 442 case AGP_I915_GCC1_GMS_STOLEN_48M: 443 sc->stolen = (49152 - stolen) * 1024 / 4096; 444 break; 445 case AGP_I915_GCC1_GMS_STOLEN_64M: 446 sc->stolen = (65536 - stolen) * 1024 / 4096; 447 break; 448 default: 449 sc->stolen = 0; 450 device_printf(dev, "unknown memory configuration, disabling\n"); 451 agp_generic_detach(dev); 452 return EINVAL; 453 } 454 if (sc->stolen > 0) 455 device_printf(dev, "detected %dk stolen memory\n", sc->stolen * 4); 456 device_printf(dev, "aperture size is %dM\n", sc->initial_aperture / 1024 / 1024); 457 458 /* GATT address is already in there, make sure it's enabled */ 459 pgtblctl = READ4(AGP_I810_PGTBL_CTL); 460 pgtblctl |= 1; 461 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl); 462 463 gatt->ag_physical = pgtblctl & ~1; 464 } 465 466 return 0; 467} 468 469static int 470agp_i810_detach(device_t dev) 471{ 472 struct agp_i810_softc *sc = device_get_softc(dev); 473 int error; 474 475 error = agp_generic_detach(dev); 476 if (error) 477 return error; 478 479 /* Clear the GATT base. */ 480 if ( sc->chiptype == CHIP_I810 ) { 481 WRITE4(AGP_I810_PGTBL_CTL, 0); 482 } else { 483 unsigned int pgtblctl; 484 pgtblctl = READ4(AGP_I810_PGTBL_CTL); 485 pgtblctl &= ~1; 486 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl); 487 } 488 489 /* Put the aperture back the way it started. */ 490 AGP_SET_APERTURE(dev, sc->initial_aperture); 491 492 if ( sc->chiptype == CHIP_I810 ) { 493 contigfree(sc->gatt->ag_virtual, 64 * 1024, M_AGP); 494 } 495 free(sc->gatt, M_AGP); 496 497 if (sc->chiptype == CHIP_I915) { 498 bus_release_resource(dev, SYS_RES_MEMORY, AGP_I915_GTTADR, 499 sc->gtt); 500 bus_release_resource(dev, SYS_RES_MEMORY, AGP_I915_MMADR, 501 sc->regs); 502 } else { 503 bus_release_resource(dev, SYS_RES_MEMORY, AGP_I810_MMADR, 504 sc->regs); 505 } 506 507 return 0; 508} 509 510static u_int32_t 511agp_i810_get_aperture(device_t dev) 512{ 513 struct agp_i810_softc *sc = device_get_softc(dev); 514 uint32_t temp; 515 u_int16_t miscc; 516 517 switch (sc->chiptype) { 518 case CHIP_I810: 519 miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2); 520 if ((miscc & AGP_I810_MISCC_WINSIZE) == AGP_I810_MISCC_WINSIZE_32) 521 return 32 * 1024 * 1024; 522 else 523 return 64 * 1024 * 1024; 524 case CHIP_I830: 525 temp = pci_read_config(sc->bdev, AGP_I830_GCC1, 2); 526 if ((temp & AGP_I830_GCC1_GMASIZE) == AGP_I830_GCC1_GMASIZE_64) 527 return 64 * 1024 * 1024; 528 else 529 return 128 * 1024 * 1024; 530 case CHIP_I855: 531 return 128 * 1024 * 1024; 532 case CHIP_I915: 533 temp = pci_read_config(dev, AGP_I915_MSAC, 1); 534 if ((temp & AGP_I915_MSAC_GMASIZE) == 535 AGP_I915_MSAC_GMASIZE_128) { 536 return 128 * 1024 * 1024; 537 } else { 538 return 256 * 1024 * 1024; 539 } 540 } 541 542 return 0; 543} 544 545static int 546agp_i810_set_aperture(device_t dev, u_int32_t aperture) 547{ 548 struct agp_i810_softc *sc = device_get_softc(dev); 549 u_int16_t miscc, gcc1; 550 u_int32_t temp; 551 552 switch (sc->chiptype) { 553 case CHIP_I810: 554 /* 555 * Double check for sanity. 556 */ 557 if (aperture != 32 * 1024 * 1024 && aperture != 64 * 1024 * 1024) { 558 device_printf(dev, "bad aperture size %d\n", aperture); 559 return EINVAL; 560 } 561 562 miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2); 563 miscc &= ~AGP_I810_MISCC_WINSIZE; 564 if (aperture == 32 * 1024 * 1024) 565 miscc |= AGP_I810_MISCC_WINSIZE_32; 566 else 567 miscc |= AGP_I810_MISCC_WINSIZE_64; 568 569 pci_write_config(sc->bdev, AGP_I810_MISCC, miscc, 2); 570 break; 571 case CHIP_I830: 572 if (aperture != 64 * 1024 * 1024 && 573 aperture != 128 * 1024 * 1024) { 574 device_printf(dev, "bad aperture size %d\n", aperture); 575 return EINVAL; 576 } 577 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2); 578 gcc1 &= ~AGP_I830_GCC1_GMASIZE; 579 if (aperture == 64 * 1024 * 1024) 580 gcc1 |= AGP_I830_GCC1_GMASIZE_64; 581 else 582 gcc1 |= AGP_I830_GCC1_GMASIZE_128; 583 584 pci_write_config(sc->bdev, AGP_I830_GCC1, gcc1, 2); 585 break; 586 case CHIP_I855: 587 if (aperture != 128 * 1024 * 1024) { 588 device_printf(dev, "bad aperture size %d\n", aperture); 589 return EINVAL; 590 } 591 break; 592 case CHIP_I915: 593 temp = pci_read_config(dev, AGP_I915_MSAC, 1); 594 temp &= ~AGP_I915_MSAC_GMASIZE; 595 596 switch (aperture) { 597 case 128 * 1024 * 1024: 598 temp |= AGP_I915_MSAC_GMASIZE_128; 599 break; 600 case 256 * 1024 * 1024: 601 temp |= AGP_I915_MSAC_GMASIZE_256; 602 break; 603 default: 604 device_printf(dev, "bad aperture size %d\n", aperture); 605 return EINVAL; 606 } 607 608 pci_write_config(dev, AGP_I915_MSAC, temp, 1); 609 break; 610 } 611 612 return 0; 613} 614 615static int 616agp_i810_bind_page(device_t dev, int offset, vm_offset_t physical) 617{ 618 struct agp_i810_softc *sc = device_get_softc(dev); 619 620 if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) { 621 device_printf(dev, "failed: offset is 0x%08x, shift is %d, entries is %d\n", offset, AGP_PAGE_SHIFT, sc->gatt->ag_entries); 622 return EINVAL; 623 } 624 625 if ( sc->chiptype != CHIP_I810 ) { 626 if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) { 627 device_printf(dev, "trying to bind into stolen memory"); 628 return EINVAL; 629 } 630 } 631 632 if (sc->chiptype == CHIP_I915) { 633 WRITEGTT((offset >> AGP_PAGE_SHIFT) * 4, physical | 1); 634 } else { 635 WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, physical | 1); 636 } 637 638 return 0; 639} 640 641static int 642agp_i810_unbind_page(device_t dev, int offset) 643{ 644 struct agp_i810_softc *sc = device_get_softc(dev); 645 646 if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) 647 return EINVAL; 648 649 if ( sc->chiptype != CHIP_I810 ) { 650 if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) { 651 device_printf(dev, "trying to unbind from stolen memory"); 652 return EINVAL; 653 } 654 } 655 656 if (sc->chiptype == CHIP_I915) { 657 WRITEGTT((offset >> AGP_PAGE_SHIFT) * 4, 0); 658 } else { 659 WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, 0); 660 } 661 662 return 0; 663} 664 665/* 666 * Writing via memory mapped registers already flushes all TLBs. 667 */ 668static void 669agp_i810_flush_tlb(device_t dev) 670{ 671} 672 673static int 674agp_i810_enable(device_t dev, u_int32_t mode) 675{ 676 677 return 0; 678} 679 680static struct agp_memory * 681agp_i810_alloc_memory(device_t dev, int type, vm_size_t size) 682{ 683 struct agp_i810_softc *sc = device_get_softc(dev); 684 struct agp_memory *mem; 685 686 if ((size & (AGP_PAGE_SIZE - 1)) != 0) 687 return 0; 688 689 if (sc->agp.as_allocated + size > sc->agp.as_maxmem) 690 return 0; 691 692 if (type == 1) { 693 /* 694 * Mapping local DRAM into GATT. 695 */ 696 if ( sc->chiptype != CHIP_I810 ) 697 return 0; 698 if (size != sc->dcache_size) 699 return 0; 700 } else if (type == 2) { 701 /* 702 * Type 2 is the contiguous physical memory type, that hands 703 * back a physical address. This is used for cursors on i810. 704 * Hand back as many single pages with physical as the user 705 * wants, but only allow one larger allocation (ARGB cursor) 706 * for simplicity. 707 */ 708 if (size != AGP_PAGE_SIZE) { 709 if (sc->argb_cursor != NULL) 710 return 0; 711 712 /* Allocate memory for ARGB cursor, if we can. */ 713 sc->argb_cursor = contigmalloc(size, M_AGP, 714 0, 0, ~0, PAGE_SIZE, 0); 715 if (sc->argb_cursor == NULL) 716 return 0; 717 } 718 } 719 720 mem = malloc(sizeof *mem, M_AGP, M_WAITOK); 721 mem->am_id = sc->agp.as_nextid++; 722 mem->am_size = size; 723 mem->am_type = type; 724 if (type != 1 && (type != 2 || size == AGP_PAGE_SIZE)) 725 mem->am_obj = vm_object_allocate(OBJT_DEFAULT, 726 atop(round_page(size))); 727 else 728 mem->am_obj = 0; 729 730 if (type == 2) { 731 if (size == AGP_PAGE_SIZE) { 732 /* 733 * Allocate and wire down the page now so that we can 734 * get its physical address. 735 */ 736 vm_page_t m; 737 738 VM_OBJECT_LOCK(mem->am_obj); 739 m = vm_page_grab(mem->am_obj, 0, VM_ALLOC_NOBUSY | 740 VM_ALLOC_WIRED | VM_ALLOC_ZERO | VM_ALLOC_RETRY); 741 VM_OBJECT_UNLOCK(mem->am_obj); 742 mem->am_physical = VM_PAGE_TO_PHYS(m); 743 } else { 744 /* Our allocation is already nicely wired down for us. 745 * Just grab the physical address. 746 */ 747 mem->am_physical = vtophys(sc->argb_cursor); 748 } 749 } else { 750 mem->am_physical = 0; 751 } 752 753 mem->am_offset = 0; 754 mem->am_is_bound = 0; 755 TAILQ_INSERT_TAIL(&sc->agp.as_memory, mem, am_link); 756 sc->agp.as_allocated += size; 757 758 return mem; 759} 760 761static int 762agp_i810_free_memory(device_t dev, struct agp_memory *mem) 763{ 764 struct agp_i810_softc *sc = device_get_softc(dev); 765 766 if (mem->am_is_bound) 767 return EBUSY; 768 769 if (mem->am_type == 2) { 770 if (mem->am_size == AGP_PAGE_SIZE) { 771 /* 772 * Unwire the page which we wired in alloc_memory. 773 */ 774 vm_page_t m; 775 776 VM_OBJECT_LOCK(mem->am_obj); 777 m = vm_page_lookup(mem->am_obj, 0); 778 VM_OBJECT_UNLOCK(mem->am_obj); 779 vm_page_lock_queues(); 780 vm_page_unwire(m, 0); 781 vm_page_unlock_queues(); 782 } else { 783 contigfree(sc->argb_cursor, mem->am_size, M_AGP); 784 sc->argb_cursor = NULL; 785 } 786 } 787 788 sc->agp.as_allocated -= mem->am_size; 789 TAILQ_REMOVE(&sc->agp.as_memory, mem, am_link); 790 if (mem->am_obj) 791 vm_object_deallocate(mem->am_obj); 792 free(mem, M_AGP); 793 return 0; 794} 795 796static int 797agp_i810_bind_memory(device_t dev, struct agp_memory *mem, 798 vm_offset_t offset) 799{ 800 struct agp_i810_softc *sc = device_get_softc(dev); 801 vm_offset_t i; 802 803 /* Do some sanity checks first. */ 804 if (offset < 0 || (offset & (AGP_PAGE_SIZE - 1)) != 0 || 805 offset + mem->am_size > AGP_GET_APERTURE(dev)) { 806 device_printf(dev, "binding memory at bad offset %#x\n", 807 (int)offset); 808 return EINVAL; 809 } 810 811 if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) { 812 mtx_lock(&sc->agp.as_lock); 813 if (mem->am_is_bound) { 814 mtx_unlock(&sc->agp.as_lock); 815 return EINVAL; 816 } 817 /* The memory's already wired down, just stick it in the GTT. */ 818 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) { 819 u_int32_t physical = mem->am_physical + i; 820 821 if (sc->chiptype == CHIP_I915) { 822 WRITEGTT(((offset + i) >> AGP_PAGE_SHIFT) * 4, 823 physical | 1); 824 } else { 825 WRITE4(AGP_I810_GTT + 826 ((offset + i) >> AGP_PAGE_SHIFT) * 4, 827 physical | 1); 828 } 829 } 830 agp_flush_cache(); 831 mem->am_offset = offset; 832 mem->am_is_bound = 1; 833 mtx_unlock(&sc->agp.as_lock); 834 return 0; 835 } 836 837 if (mem->am_type != 1) 838 return agp_generic_bind_memory(dev, mem, offset); 839 840 if ( sc->chiptype != CHIP_I810 ) 841 return EINVAL; 842 843 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) { 844 WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, 845 i | 3); 846 } 847 848 return 0; 849} 850 851static int 852agp_i810_unbind_memory(device_t dev, struct agp_memory *mem) 853{ 854 struct agp_i810_softc *sc = device_get_softc(dev); 855 vm_offset_t i; 856 857 if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) { 858 mtx_lock(&sc->agp.as_lock); 859 if (!mem->am_is_bound) { 860 mtx_unlock(&sc->agp.as_lock); 861 return EINVAL; 862 } 863 864 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) { 865 vm_offset_t offset = mem->am_offset; 866 867 if (sc->chiptype == CHIP_I915) { 868 WRITEGTT(((offset + i) >> AGP_PAGE_SHIFT) * 4, 869 0); 870 } else { 871 WRITE4(AGP_I810_GTT + 872 ((offset + i) >> AGP_PAGE_SHIFT) * 4, 0); 873 } 874 } 875 agp_flush_cache(); 876 mem->am_is_bound = 0; 877 mtx_unlock(&sc->agp.as_lock); 878 return 0; 879 } 880 881 if (mem->am_type != 1) 882 return agp_generic_unbind_memory(dev, mem); 883 884 if ( sc->chiptype != CHIP_I810 ) 885 return EINVAL; 886 887 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) 888 WRITE4(AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, 0); 889 890 return 0; 891} 892 893static device_method_t agp_i810_methods[] = { 894 /* Device interface */ 895 DEVMETHOD(device_identify, agp_i810_identify), 896 DEVMETHOD(device_probe, agp_i810_probe), 897 DEVMETHOD(device_attach, agp_i810_attach), 898 DEVMETHOD(device_detach, agp_i810_detach), 899 900 /* AGP interface */ 901 DEVMETHOD(agp_get_aperture, agp_i810_get_aperture), 902 DEVMETHOD(agp_set_aperture, agp_i810_set_aperture), 903 DEVMETHOD(agp_bind_page, agp_i810_bind_page), 904 DEVMETHOD(agp_unbind_page, agp_i810_unbind_page), 905 DEVMETHOD(agp_flush_tlb, agp_i810_flush_tlb), 906 DEVMETHOD(agp_enable, agp_i810_enable), 907 DEVMETHOD(agp_alloc_memory, agp_i810_alloc_memory), 908 DEVMETHOD(agp_free_memory, agp_i810_free_memory), 909 DEVMETHOD(agp_bind_memory, agp_i810_bind_memory), 910 DEVMETHOD(agp_unbind_memory, agp_i810_unbind_memory), 911 912 { 0, 0 } 913}; 914 915static driver_t agp_i810_driver = { 916 "agp", 917 agp_i810_methods, 918 sizeof(struct agp_i810_softc), 919}; 920 921static devclass_t agp_devclass; 922 923DRIVER_MODULE(agp_i810, vgapci, agp_i810_driver, agp_devclass, 0, 0); 924MODULE_DEPEND(agp_i810, agp, 1, 1, 1); 925MODULE_DEPEND(agp_i810, pci, 1, 1, 1); 926