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