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 * $FreeBSD$ 28 */ 29 30 /* 31 * Fixes for 830/845G support: David Dawes <dawes@xfree86.org> 32 * 852GM/855GM/865G support added by David Dawes <dawes@xfree86.org> 33 */ 34 35 #include "opt_bus.h" 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/malloc.h> 40 #include <sys/kernel.h> 41 #include <sys/bus.h> 42 #include <sys/lock.h> 43 #include <sys/lockmgr.h> 44 #include <sys/mutex.h> 45 #include <sys/proc.h> 46 47 #include <pci/pcivar.h> 48 #include <pci/pcireg.h> 49 #include <pci/agppriv.h> 50 #include <pci/agpreg.h> 51 52 #include <vm/vm.h> 53 #include <vm/vm_object.h> 54 #include <vm/vm_page.h> 55 #include <vm/vm_pageout.h> 56 #include <vm/pmap.h> 57 58 #include <machine/bus.h> 59 #include <machine/resource.h> 60 #include <sys/rman.h> 61 62 MALLOC_DECLARE(M_AGP); 63 64 #define READ1(off) bus_space_read_1(sc->bst, sc->bsh, off) 65 #define READ4(off) bus_space_read_4(sc->bst, sc->bsh, off) 66 #define WRITE4(off,v) bus_space_write_4(sc->bst, sc->bsh, off, v) 67 68 #define CHIP_I810 0 /* i810/i815 */ 69 #define CHIP_I830 1 /* 830M/845G */ 70 #define CHIP_I855 2 /* 852GM/855GM/865G */ 71 72 struct agp_i810_softc { 73 struct agp_softc agp; 74 u_int32_t initial_aperture; /* aperture size at startup */ 75 struct agp_gatt *gatt; 76 int chiptype; /* i810-like or i830 */ 77 u_int32_t dcache_size; /* i810 only */ 78 u_int32_t stolen; /* number of i830/845 gtt entries for stolen memory */ 79 device_t bdev; /* bridge device */ 80 struct resource *regs; /* memory mapped GC registers */ 81 bus_space_tag_t bst; /* bus_space tag */ 82 bus_space_handle_t bsh; /* bus_space handle */ 83 }; 84 85 static const char* 86 agp_i810_match(device_t dev) 87 { 88 if (pci_get_class(dev) != PCIC_DISPLAY 89 || pci_get_subclass(dev) != PCIS_DISPLAY_VGA) 90 return NULL; 91 92 switch (pci_get_devid(dev)) { 93 case 0x71218086: 94 return ("Intel 82810 (i810 GMCH) SVGA controller"); 95 96 case 0x71238086: 97 return ("Intel 82810-DC100 (i810-DC100 GMCH) SVGA controller"); 98 99 case 0x71258086: 100 return ("Intel 82810E (i810E GMCH) SVGA controller"); 101 102 case 0x11328086: 103 return ("Intel 82815 (i815 GMCH) SVGA controller"); 104 105 case 0x35778086: 106 return ("Intel 82830M (830M GMCH) SVGA controller"); 107 108 case 0x25628086: 109 return ("Intel 82845G (845G GMCH) SVGA controller"); 110 111 case 0x35828086: 112 switch (pci_read_config(dev, AGP_I85X_CAPID, 1)) { 113 case AGP_I855_GME: 114 return ("Intel 82855GME (855GME GMCH) SVGA controller"); 115 116 case AGP_I855_GM: 117 return ("Intel 82855GM (855GM GMCH) SVGA controller"); 118 119 case AGP_I852_GME: 120 return ("Intel 82852GME (852GME GMCH) SVGA controller"); 121 122 case AGP_I852_GM: 123 return ("Intel 82852GM (852GM GMCH) SVGA controller"); 124 125 default: 126 return ("Intel 8285xM (85xGM GMCH) SVGA controller"); 127 } 128 129 case 0x25728086: 130 return ("Intel 82865G (865G GMCH) SVGA controller"); 131 }; 132 133 return NULL; 134 } 135 136 /* 137 * Find bridge device. 138 */ 139 static device_t 140 agp_i810_find_bridge(device_t dev) 141 { 142 device_t *children, child; 143 int nchildren, i; 144 u_int32_t devid; 145 146 /* 147 * Calculate bridge device's ID. 148 */ 149 devid = pci_get_devid(dev); 150 switch (devid) { 151 case 0x71218086: 152 case 0x71238086: 153 case 0x71258086: 154 devid -= 0x10000; 155 break; 156 157 case 0x11328086: 158 case 0x35778086: 159 case 0x25628086: 160 case 0x35828086: 161 case 0x25728086: 162 devid -= 0x20000; 163 break; 164 }; 165 if (device_get_children(device_get_parent(dev), &children, &nchildren)) 166 return 0; 167 168 for (i = 0; i < nchildren; i++) { 169 child = children[i]; 170 171 if (pci_get_devid(child) == devid) { 172 free(children, M_TEMP); 173 return child; 174 } 175 } 176 free(children, M_TEMP); 177 return 0; 178 } 179 180 static int 181 agp_i810_probe(device_t dev) 182 { 183 const char *desc; 184 185 desc = agp_i810_match(dev); 186 if (desc) { 187 device_t bdev; 188 u_int8_t smram; 189 int devid = pci_get_devid(dev); 190 191 bdev = agp_i810_find_bridge(dev); 192 if (!bdev) { 193 if (bootverbose) 194 printf("I810: can't find bridge device\n"); 195 return ENXIO; 196 } 197 198 /* 199 * checking whether internal graphics device has been activated. 200 */ 201 if ( (devid == 0x71218086 ) || 202 (devid == 0x71238086 ) || 203 (devid == 0x71258086 ) || 204 (devid == 0x11328086 ) ) { 205 smram = pci_read_config(bdev, AGP_I810_SMRAM, 1); 206 if ((smram & AGP_I810_SMRAM_GMS) 207 == AGP_I810_SMRAM_GMS_DISABLED) { 208 if (bootverbose) 209 printf("I810: disabled, not probing\n"); 210 return ENXIO; 211 } 212 } else { /* I830MG */ 213 unsigned int gcc1; 214 gcc1 = pci_read_config(bdev, AGP_I830_GCC1, 1); 215 if ((gcc1 & AGP_I830_GCC1_DEV2) == AGP_I830_GCC1_DEV2_DISABLED) { 216 if (bootverbose) 217 printf("I830: disabled, not probing\n"); 218 return ENXIO; 219 } 220 } 221 222 device_verbose(dev); 223 device_set_desc(dev, desc); 224 return 0; 225 } 226 227 return ENXIO; 228 } 229 230 static int 231 agp_i810_attach(device_t dev) 232 { 233 struct agp_i810_softc *sc = device_get_softc(dev); 234 struct agp_gatt *gatt; 235 int error, rid; 236 237 sc->bdev = agp_i810_find_bridge(dev); 238 if (!sc->bdev) 239 return ENOENT; 240 241 error = agp_generic_attach(dev); 242 if (error) 243 return error; 244 245 switch (pci_get_devid(dev)) { 246 case 0x71218086: 247 case 0x71238086: 248 case 0x71258086: 249 case 0x11328086: 250 sc->chiptype = CHIP_I810; 251 break; 252 case 0x35778086: 253 case 0x25628086: 254 sc->chiptype = CHIP_I830; 255 break; 256 case 0x35828086: 257 case 0x25728086: 258 sc->chiptype = CHIP_I855; 259 break; 260 }; 261 262 /* Same for i810 and i830 */ 263 rid = AGP_I810_MMADR; 264 sc->regs = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 265 0, ~0, 1, RF_ACTIVE); 266 if (!sc->regs) { 267 agp_generic_detach(dev); 268 return ENOMEM; 269 } 270 sc->bst = rman_get_bustag(sc->regs); 271 sc->bsh = rman_get_bushandle(sc->regs); 272 273 sc->initial_aperture = AGP_GET_APERTURE(dev); 274 275 gatt = malloc( sizeof(struct agp_gatt), M_AGP, M_NOWAIT); 276 if (!gatt) { 277 agp_generic_detach(dev); 278 return ENOMEM; 279 } 280 sc->gatt = gatt; 281 282 gatt->ag_entries = AGP_GET_APERTURE(dev) >> AGP_PAGE_SHIFT; 283 284 if ( sc->chiptype == CHIP_I810 ) { 285 /* Some i810s have on-chip memory called dcache */ 286 if (READ1(AGP_I810_DRT) & AGP_I810_DRT_POPULATED) 287 sc->dcache_size = 4 * 1024 * 1024; 288 else 289 sc->dcache_size = 0; 290 291 /* According to the specs the gatt on the i810 must be 64k */ 292 gatt->ag_virtual = contigmalloc( 64 * 1024, M_AGP, 0, 293 0, ~0, PAGE_SIZE, 0); 294 if (!gatt->ag_virtual) { 295 if (bootverbose) 296 device_printf(dev, "contiguous allocation failed\n"); 297 free(gatt, M_AGP); 298 agp_generic_detach(dev); 299 return ENOMEM; 300 } 301 bzero(gatt->ag_virtual, gatt->ag_entries * sizeof(u_int32_t)); 302 303 gatt->ag_physical = vtophys((vm_offset_t) gatt->ag_virtual); 304 agp_flush_cache(); 305 /* Install the GATT. */ 306 WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1); 307 } else if ( sc->chiptype == CHIP_I830 ) { 308 /* The i830 automatically initializes the 128k gatt on boot. */ 309 unsigned int gcc1, pgtblctl; 310 311 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 1); 312 switch (gcc1 & AGP_I830_GCC1_GMS) { 313 case AGP_I830_GCC1_GMS_STOLEN_512: 314 sc->stolen = (512 - 132) * 1024 / 4096; 315 break; 316 case AGP_I830_GCC1_GMS_STOLEN_1024: 317 sc->stolen = (1024 - 132) * 1024 / 4096; 318 break; 319 case AGP_I830_GCC1_GMS_STOLEN_8192: 320 sc->stolen = (8192 - 132) * 1024 / 4096; 321 break; 322 default: 323 sc->stolen = 0; 324 device_printf(dev, "unknown memory configuration, disabling\n"); 325 agp_generic_detach(dev); 326 return EINVAL; 327 } 328 if (sc->stolen > 0) 329 device_printf(dev, "detected %dk stolen memory\n", sc->stolen * 4); 330 device_printf(dev, "aperture size is %dM\n", sc->initial_aperture / 1024 / 1024); 331 332 /* GATT address is already in there, make sure it's enabled */ 333 pgtblctl = READ4(AGP_I810_PGTBL_CTL); 334 pgtblctl |= 1; 335 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl); 336 337 gatt->ag_physical = pgtblctl & ~1; 338 } else { /* CHIP_I855 */ 339 /* The 855GM automatically initializes the 128k gatt on boot. */ 340 unsigned int gcc1, pgtblctl; 341 342 gcc1 = pci_read_config(sc->bdev, AGP_I855_GCC1, 1); 343 switch (gcc1 & AGP_I855_GCC1_GMS) { 344 case AGP_I855_GCC1_GMS_STOLEN_1M: 345 sc->stolen = (1024 - 132) * 1024 / 4096; 346 break; 347 case AGP_I855_GCC1_GMS_STOLEN_4M: 348 sc->stolen = (4096 - 132) * 1024 / 4096; 349 break; 350 case AGP_I855_GCC1_GMS_STOLEN_8M: 351 sc->stolen = (8192 - 132) * 1024 / 4096; 352 break; 353 case AGP_I855_GCC1_GMS_STOLEN_16M: 354 sc->stolen = (16384 - 132) * 1024 / 4096; 355 break; 356 case AGP_I855_GCC1_GMS_STOLEN_32M: 357 sc->stolen = (32768 - 132) * 1024 / 4096; 358 break; 359 default: 360 sc->stolen = 0; 361 device_printf(dev, "unknown memory configuration, disabling\n"); 362 agp_generic_detach(dev); 363 return EINVAL; 364 } 365 if (sc->stolen > 0) 366 device_printf(dev, "detected %dk stolen memory\n", sc->stolen * 4); 367 device_printf(dev, "aperture size is %dM\n", sc->initial_aperture / 1024 / 1024); 368 369 /* GATT address is already in there, make sure it's enabled */ 370 pgtblctl = READ4(AGP_I810_PGTBL_CTL); 371 pgtblctl |= 1; 372 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl); 373 374 gatt->ag_physical = pgtblctl & ~1; 375 } 376 377 return 0; 378 } 379 380 static int 381 agp_i810_detach(device_t dev) 382 { 383 struct agp_i810_softc *sc = device_get_softc(dev); 384 int error; 385 386 error = agp_generic_detach(dev); 387 if (error) 388 return error; 389 390 /* Clear the GATT base. */ 391 if ( sc->chiptype == CHIP_I810 ) { 392 WRITE4(AGP_I810_PGTBL_CTL, 0); 393 } else { 394 unsigned int pgtblctl; 395 pgtblctl = READ4(AGP_I810_PGTBL_CTL); 396 pgtblctl &= ~1; 397 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl); 398 } 399 400 /* Put the aperture back the way it started. */ 401 AGP_SET_APERTURE(dev, sc->initial_aperture); 402 403 if ( sc->chiptype == CHIP_I810 ) { 404 contigfree(sc->gatt->ag_virtual, 64 * 1024, M_AGP); 405 } 406 free(sc->gatt, M_AGP); 407 408 bus_release_resource(dev, SYS_RES_MEMORY, 409 AGP_I810_MMADR, sc->regs); 410 411 return 0; 412 } 413 414 static u_int32_t 415 agp_i810_get_aperture(device_t dev) 416 { 417 struct agp_i810_softc *sc = device_get_softc(dev); 418 419 if ( sc->chiptype == CHIP_I810 ) { 420 u_int16_t miscc; 421 miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2); 422 if ((miscc & AGP_I810_MISCC_WINSIZE) == AGP_I810_MISCC_WINSIZE_32) 423 return 32 * 1024 * 1024; 424 else 425 return 64 * 1024 * 1024; 426 } else if ( sc->chiptype == CHIP_I830 ) { 427 unsigned int gcc1; 428 429 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2); 430 if ((gcc1 & AGP_I830_GCC1_GMASIZE) == AGP_I830_GCC1_GMASIZE_64) 431 return 64 * 1024 * 1024; 432 else 433 return 128 * 1024 * 1024; 434 } else { /* CHIP_I855 */ 435 return 128 * 1024 * 1024; 436 } 437 } 438 439 static int 440 agp_i810_set_aperture(device_t dev, u_int32_t aperture) 441 { 442 struct agp_i810_softc *sc = device_get_softc(dev); 443 u_int16_t miscc; 444 445 if ( sc->chiptype == CHIP_I810 ) { 446 /* 447 * Double check for sanity. 448 */ 449 if (aperture != 32 * 1024 * 1024 && aperture != 64 * 1024 * 1024) { 450 device_printf(dev, "bad aperture size %d\n", aperture); 451 return EINVAL; 452 } 453 454 miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2); 455 miscc &= ~AGP_I810_MISCC_WINSIZE; 456 if (aperture == 32 * 1024 * 1024) 457 miscc |= AGP_I810_MISCC_WINSIZE_32; 458 else 459 miscc |= AGP_I810_MISCC_WINSIZE_64; 460 461 pci_write_config(sc->bdev, AGP_I810_MISCC, miscc, 2); 462 } else if ( sc->chiptype == CHIP_I830 ) { 463 unsigned int gcc1; 464 465 if (aperture != 64 * 1024 * 1024 && aperture != 128 * 1024 * 1024) { 466 device_printf(dev, "bad aperture size %d\n", aperture); 467 return EINVAL; 468 } 469 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2); 470 gcc1 &= ~AGP_I830_GCC1_GMASIZE; 471 if (aperture == 64 * 1024 * 1024) 472 gcc1 |= AGP_I830_GCC1_GMASIZE_64; 473 else 474 gcc1 |= AGP_I830_GCC1_GMASIZE_128; 475 476 pci_write_config(sc->bdev, AGP_I830_GCC1, gcc1, 2); 477 } else { /* CHIP_I855 */ 478 if (aperture != 128 * 1024 * 1024) { 479 device_printf(dev, "bad aperture size %d\n", aperture); 480 return EINVAL; 481 } 482 } 483 484 return 0; 485 } 486 487 static int 488 agp_i810_bind_page(device_t dev, int offset, vm_offset_t physical) 489 { 490 struct agp_i810_softc *sc = device_get_softc(dev); 491 492 if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) { 493 device_printf(dev, "failed: offset is 0x%08x, shift is %d, entries is %d\n", offset, AGP_PAGE_SHIFT, sc->gatt->ag_entries); 494 return EINVAL; 495 } 496 497 if ( sc->chiptype != CHIP_I810 ) { 498 if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) { 499 device_printf(dev, "trying to bind into stolen memory"); 500 return EINVAL; 501 } 502 } 503 504 WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, physical | 1); 505 return 0; 506 } 507 508 static int 509 agp_i810_unbind_page(device_t dev, int offset) 510 { 511 struct agp_i810_softc *sc = device_get_softc(dev); 512 513 if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) 514 return EINVAL; 515 516 if ( sc->chiptype != CHIP_I810 ) { 517 if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) { 518 device_printf(dev, "trying to unbind from stolen memory"); 519 return EINVAL; 520 } 521 } 522 523 WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, 0); 524 return 0; 525 } 526 527 /* 528 * Writing via memory mapped registers already flushes all TLBs. 529 */ 530 static void 531 agp_i810_flush_tlb(device_t dev) 532 { 533 } 534 535 static int 536 agp_i810_enable(device_t dev, u_int32_t mode) 537 { 538 539 return 0; 540 } 541 542 static struct agp_memory * 543 agp_i810_alloc_memory(device_t dev, int type, vm_size_t size) 544 { 545 struct agp_i810_softc *sc = device_get_softc(dev); 546 struct agp_memory *mem; 547 548 if ((size & (AGP_PAGE_SIZE - 1)) != 0) 549 return 0; 550 551 if (sc->agp.as_allocated + size > sc->agp.as_maxmem) 552 return 0; 553 554 if (type == 1) { 555 /* 556 * Mapping local DRAM into GATT. 557 */ 558 if ( sc->chiptype != CHIP_I810 ) 559 return 0; 560 if (size != sc->dcache_size) 561 return 0; 562 } else if (type == 2) { 563 /* 564 * Bogus mapping of a single page for the hardware cursor. 565 */ 566 if (size != AGP_PAGE_SIZE) 567 return 0; 568 } 569 570 mem = malloc(sizeof *mem, M_AGP, M_WAITOK); 571 mem->am_id = sc->agp.as_nextid++; 572 mem->am_size = size; 573 mem->am_type = type; 574 if (type != 1) 575 mem->am_obj = vm_object_allocate(OBJT_DEFAULT, 576 atop(round_page(size))); 577 else 578 mem->am_obj = 0; 579 580 if (type == 2) { 581 /* 582 * Allocate and wire down the page now so that we can 583 * get its physical address. 584 */ 585 vm_page_t m; 586 m = vm_page_grab(mem->am_obj, 0, 587 VM_ALLOC_WIRED | VM_ALLOC_ZERO | VM_ALLOC_RETRY); 588 if ((m->flags & PG_ZERO) == 0) 589 pmap_zero_page(m); 590 vm_page_lock_queues(); 591 mem->am_physical = VM_PAGE_TO_PHYS(m); 592 vm_page_wakeup(m); 593 vm_page_unlock_queues(); 594 } else { 595 mem->am_physical = 0; 596 } 597 598 mem->am_offset = 0; 599 mem->am_is_bound = 0; 600 TAILQ_INSERT_TAIL(&sc->agp.as_memory, mem, am_link); 601 sc->agp.as_allocated += size; 602 603 return mem; 604 } 605 606 static int 607 agp_i810_free_memory(device_t dev, struct agp_memory *mem) 608 { 609 struct agp_i810_softc *sc = device_get_softc(dev); 610 611 if (mem->am_is_bound) 612 return EBUSY; 613 614 if (mem->am_type == 2) { 615 /* 616 * Unwire the page which we wired in alloc_memory. 617 */ 618 vm_page_t m = vm_page_lookup(mem->am_obj, 0); 619 vm_page_lock_queues(); 620 vm_page_unwire(m, 0); 621 vm_page_unlock_queues(); 622 } 623 624 sc->agp.as_allocated -= mem->am_size; 625 TAILQ_REMOVE(&sc->agp.as_memory, mem, am_link); 626 if (mem->am_obj) 627 vm_object_deallocate(mem->am_obj); 628 free(mem, M_AGP); 629 return 0; 630 } 631 632 static int 633 agp_i810_bind_memory(device_t dev, struct agp_memory *mem, 634 vm_offset_t offset) 635 { 636 struct agp_i810_softc *sc = device_get_softc(dev); 637 vm_offset_t i; 638 639 if (mem->am_type != 1) 640 return agp_generic_bind_memory(dev, mem, offset); 641 642 if ( sc->chiptype != CHIP_I810 ) 643 return EINVAL; 644 645 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) { 646 WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, 647 i | 3); 648 } 649 650 return 0; 651 } 652 653 static int 654 agp_i810_unbind_memory(device_t dev, struct agp_memory *mem) 655 { 656 struct agp_i810_softc *sc = device_get_softc(dev); 657 vm_offset_t i; 658 659 if (mem->am_type != 1) 660 return agp_generic_unbind_memory(dev, mem); 661 662 if ( sc->chiptype != CHIP_I810 ) 663 return EINVAL; 664 665 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) 666 WRITE4(AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, 0); 667 668 return 0; 669 } 670 671 static device_method_t agp_i810_methods[] = { 672 /* Device interface */ 673 DEVMETHOD(device_probe, agp_i810_probe), 674 DEVMETHOD(device_attach, agp_i810_attach), 675 DEVMETHOD(device_detach, agp_i810_detach), 676 DEVMETHOD(device_shutdown, bus_generic_shutdown), 677 DEVMETHOD(device_suspend, bus_generic_suspend), 678 DEVMETHOD(device_resume, bus_generic_resume), 679 680 /* AGP interface */ 681 DEVMETHOD(agp_get_aperture, agp_i810_get_aperture), 682 DEVMETHOD(agp_set_aperture, agp_i810_set_aperture), 683 DEVMETHOD(agp_bind_page, agp_i810_bind_page), 684 DEVMETHOD(agp_unbind_page, agp_i810_unbind_page), 685 DEVMETHOD(agp_flush_tlb, agp_i810_flush_tlb), 686 DEVMETHOD(agp_enable, agp_i810_enable), 687 DEVMETHOD(agp_alloc_memory, agp_i810_alloc_memory), 688 DEVMETHOD(agp_free_memory, agp_i810_free_memory), 689 DEVMETHOD(agp_bind_memory, agp_i810_bind_memory), 690 DEVMETHOD(agp_unbind_memory, agp_i810_unbind_memory), 691 692 { 0, 0 } 693 }; 694 695 static driver_t agp_i810_driver = { 696 "agp", 697 agp_i810_methods, 698 sizeof(struct agp_i810_softc), 699 }; 700 701 static devclass_t agp_devclass; 702 703 DRIVER_MODULE(agp_i810, pci, agp_i810_driver, agp_devclass, 0, 0); 704