1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2009, Intel Corporation. 24 * All Rights Reserved. 25 */ 26 27 /* 28 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 29 * Use is subject to license terms. 30 */ 31 32 /* 33 * Misc module for AGP master device support 34 */ 35 36 #include <sys/modctl.h> 37 #include <sys/pci.h> 38 #include <sys/stat.h> 39 #include <sys/file.h> 40 #include <sys/types.h> 41 #include <sys/dditypes.h> 42 #include <sys/sunddi.h> 43 #include <sys/agpgart.h> 44 #include <sys/agp/agpdefs.h> 45 #include <sys/agp/agpmaster_io.h> 46 47 #define PGTBL_CTL 0x2020 /* Page table control register */ 48 #define I8XX_FB_BAR 1 49 #define I8XX_MMIO_BAR 2 50 #define I8XX_PTE_OFFSET 0x10000 51 #define I915_MMADR 1 /* mem-mapped registers BAR */ 52 #define I915_GMADR 3 /* graphics mem BAR */ 53 #define I915_GTTADDR 4 /* GTT BAR */ 54 #define I965_GTTMMADR 1 /* mem-mapped registers BAR + GTT */ 55 /* In 965 1MB GTTMMADR, GTT reside in the latter 512KB */ 56 #define I965_GTT_OFFSET 0x80000 57 #define GM45_GTT_OFFSET 0x200000 58 #define GTT_SIZE_MASK 0xe 59 #define GTT_512KB (0 << 1) 60 #define GTT_256KB (1 << 1) 61 #define GTT_128KB (2 << 1) 62 #define GTT_1MB (3 << 1) 63 #define GTT_2MB (4 << 1) 64 #define GTT_1_5MB (5 << 1) 65 66 #define MMIO_BASE(x) (x)->agpm_data.agpm_gtt.gtt_mmio_base 67 #define MMIO_HANDLE(x) (x)->agpm_data.agpm_gtt.gtt_mmio_handle 68 #define GTT_HANDLE(x) (x)->agpm_data.agpm_gtt.gtt_handle 69 /* Base address of GTT */ 70 #define GTT_ADDR(x) (x)->agpm_data.agpm_gtt.gtt_addr 71 /* Graphics memory base address */ 72 #define APER_BASE(x) (x)->agpm_data.agpm_gtt.gtt_info.igd_aperbase 73 74 #define AGPM_WRITE(x, off, val) \ 75 ddi_put32(MMIO_HANDLE(x), (uint32_t *)(MMIO_BASE(x) + (off)), (val)); 76 77 #define AGPM_READ(x, off) \ 78 ddi_get32(MMIO_HANDLE(x), (uint32_t *)(MMIO_BASE(x) + (off))); 79 80 #ifdef DEBUG 81 #define CONFIRM(value) ASSERT(value) 82 #else 83 #define CONFIRM(value) if (!(value)) return (EINVAL) 84 #endif 85 86 int agpm_debug = 0; 87 #define AGPM_DEBUG(args) if (agpm_debug >= 1) cmn_err args 88 89 /* 90 * Whether it is a Intel integrated graphics card 91 */ 92 #define IS_IGD(agpmaster) ((agpmaster->agpm_dev_type == DEVICE_IS_I810) || \ 93 (agpmaster->agpm_dev_type == DEVICE_IS_I830)) 94 95 static struct modlmisc modlmisc = { 96 &mod_miscops, "AGP master interfaces" 97 }; 98 99 static struct modlinkage modlinkage = { 100 MODREV_1, (void *)&modlmisc, NULL 101 }; 102 103 static ddi_device_acc_attr_t i8xx_dev_access = { 104 DDI_DEVICE_ATTR_V0, 105 DDI_NEVERSWAP_ACC, 106 DDI_STRICTORDER_ACC 107 }; 108 109 static off_t agpmaster_cap_find(ddi_acc_handle_t); 110 static int detect_i8xx_device(agp_master_softc_t *); 111 static int detect_agp_devcice(agp_master_softc_t *, ddi_acc_handle_t); 112 static int i8xx_add_to_gtt(gtt_impl_t *, igd_gtt_seg_t); 113 static void i8xx_remove_from_gtt(gtt_impl_t *, igd_gtt_seg_t); 114 115 int 116 _init(void) 117 { 118 int err; 119 120 if ((err = mod_install(&modlinkage)) != 0) 121 return (err); 122 123 return (0); 124 } 125 126 int 127 _fini(void) 128 { 129 int err; 130 131 if ((err = mod_remove(&modlinkage)) != 0) 132 return (err); 133 134 return (0); 135 } 136 137 int 138 _info(struct modinfo *modinfop) 139 { 140 return (mod_info(&modlinkage, modinfop)); 141 } 142 143 /* 144 * Minor node is not removed here, since the caller (xx_attach) is 145 * responsible for removing all nodes. 146 */ 147 void 148 agpmaster_detach(agp_master_softc_t **master_softcp) 149 { 150 agp_master_softc_t *master_softc; 151 152 ASSERT(master_softcp); 153 master_softc = *master_softcp; 154 155 /* intel integrated device */ 156 if (IS_IGD(master_softc) && 157 ((MMIO_HANDLE(master_softc) != NULL) || 158 (GTT_HANDLE(master_softc) != NULL))) { 159 /* 160 * for some chipsets, mmap handle is shared between both mmio 161 * and GTT table. 162 */ 163 if ((GTT_HANDLE(master_softc) != MMIO_HANDLE(master_softc)) && 164 (GTT_HANDLE(master_softc) != NULL)) 165 ddi_regs_map_free(>T_HANDLE(master_softc)); 166 if (MMIO_HANDLE(master_softc) != NULL) 167 ddi_regs_map_free(&MMIO_HANDLE(master_softc)); 168 } 169 170 kmem_free(master_softc, sizeof (agp_master_softc_t)); 171 master_softc = NULL; 172 173 return; 174 175 } 176 177 /* 178 * 965 has a fixed GTT table size (512KB), so check to see the actual aperture 179 * size. Aperture size = GTT table size * 1024. 180 */ 181 static off_t 182 i965_apersize(agp_master_softc_t *agpmaster) 183 { 184 off_t apersize; 185 186 apersize = AGPM_READ(agpmaster, PGTBL_CTL); 187 AGPM_DEBUG((CE_NOTE, "i965_apersize: PGTBL_CTL = %lx", apersize)); 188 switch (apersize & GTT_SIZE_MASK) { 189 case GTT_2MB: 190 apersize = 2048; 191 break; 192 case GTT_1_5MB: 193 apersize = 1536; 194 break; 195 case GTT_1MB: 196 apersize = 1024; 197 break; 198 case GTT_512KB: 199 apersize = 512; 200 break; 201 case GTT_256KB: 202 apersize = 256; 203 break; 204 case GTT_128KB: 205 apersize = 128; 206 break; 207 default: 208 apersize = 0; 209 AGPM_DEBUG((CE_WARN, 210 "i965_apersize: invalid GTT size in PGTBL_CTL")); 211 } 212 return (apersize); 213 } 214 215 /* 216 * For Intel 3 series, we need to get GTT size from the GGMS field in GMCH 217 * Graphics Control Register. Return aperture size in MB. 218 */ 219 static off_t 220 i3XX_apersize(ddi_acc_handle_t pci_acc_hdl) 221 { 222 uint16_t value; 223 off_t apersize; 224 225 /* 226 * Get the value of configuration register MGGC "Mirror of Dev0 GMCH 227 * Graphics Control" from Internal Graphics #2 (Device2:Function0). 228 */ 229 value = pci_config_get16(pci_acc_hdl, I8XX_CONF_GC); 230 AGPM_DEBUG((CE_NOTE, "i3XX_apersize: MGGC = 0x%x", value)); 231 /* computing aperture size using the pre-allocated GTT size */ 232 switch (value & IX33_GGMS_MASK) { 233 case IX33_GGMS_1M: 234 apersize = 1024; 235 break; 236 case IX33_GGMS_2M: 237 apersize = 2048; 238 break; 239 default: 240 apersize = 0; /* no memory pre-allocated */ 241 AGPM_DEBUG((CE_WARN, 242 "i3XX_apersize: no memory allocated for GTT")); 243 } 244 AGPM_DEBUG((CE_NOTE, "i3xx_apersize: apersize = %ldM", apersize)); 245 return (apersize); 246 } 247 248 #define CHECK_STATUS(status) \ 249 if (status != DDI_SUCCESS) { \ 250 AGPM_DEBUG((CE_WARN, \ 251 "set_gtt_mmio: regs_map_setup error")); \ 252 return (-1); \ 253 } 254 /* 255 * Set gtt_addr, gtt_mmio_base, igd_apersize, igd_aperbase and igd_devid 256 * according to chipset. 257 */ 258 static int 259 set_gtt_mmio(dev_info_t *devi, agp_master_softc_t *agpmaster, 260 ddi_acc_handle_t pci_acc_hdl) 261 { 262 off_t apersize; /* size of graphics mem (MB) == GTT size (KB) */ 263 uint32_t value; 264 off_t gmadr_off; /* GMADR offset in PCI config space */ 265 int status; 266 267 if (IS_INTEL_X33(agpmaster->agpm_id)) { 268 /* Intel 3 series are similar with 915/945 series */ 269 status = ddi_regs_map_setup(devi, I915_GTTADDR, 270 >T_ADDR(agpmaster), 0, 0, &i8xx_dev_access, 271 >T_HANDLE(agpmaster)); 272 CHECK_STATUS(status); 273 274 status = ddi_regs_map_setup(devi, I915_MMADR, 275 &MMIO_BASE(agpmaster), 0, 0, &i8xx_dev_access, 276 &MMIO_HANDLE(agpmaster)); 277 CHECK_STATUS(status); 278 279 gmadr_off = I915_CONF_GMADR; 280 /* Different computing method used in getting aperture size. */ 281 apersize = i3XX_apersize(pci_acc_hdl); 282 } else if (IS_INTEL_965(agpmaster->agpm_id)) { 283 status = ddi_regs_map_setup(devi, I965_GTTMMADR, 284 &MMIO_BASE(agpmaster), 0, 0, &i8xx_dev_access, 285 &MMIO_HANDLE(agpmaster)); 286 CHECK_STATUS(status); 287 if ((agpmaster->agpm_id == INTEL_IGD_GM45) || 288 IS_INTEL_G4X(agpmaster->agpm_id)) 289 GTT_ADDR(agpmaster) = 290 MMIO_BASE(agpmaster) + GM45_GTT_OFFSET; 291 else 292 GTT_ADDR(agpmaster) = 293 MMIO_BASE(agpmaster) + I965_GTT_OFFSET; 294 GTT_HANDLE(agpmaster) = MMIO_HANDLE(agpmaster); 295 296 gmadr_off = I915_CONF_GMADR; 297 apersize = i965_apersize(agpmaster); 298 } else if (IS_INTEL_915(agpmaster->agpm_id)) { 299 /* I915/945 series */ 300 status = ddi_regs_map_setup(devi, I915_GTTADDR, 301 >T_ADDR(agpmaster), 0, 0, &i8xx_dev_access, 302 >T_HANDLE(agpmaster)); 303 CHECK_STATUS(status); 304 305 status = ddi_regs_map_setup(devi, I915_MMADR, 306 &MMIO_BASE(agpmaster), 0, 0, &i8xx_dev_access, 307 &MMIO_HANDLE(agpmaster)); 308 CHECK_STATUS(status); 309 310 gmadr_off = I915_CONF_GMADR; 311 status = ddi_dev_regsize(devi, I915_GMADR, &apersize); 312 apersize = BYTES2MB(apersize); 313 } else { 314 /* I8XX series */ 315 status = ddi_regs_map_setup(devi, I8XX_MMIO_BAR, 316 &MMIO_BASE(agpmaster), 0, 0, &i8xx_dev_access, 317 &MMIO_HANDLE(agpmaster)); 318 CHECK_STATUS(status); 319 320 GTT_ADDR(agpmaster) = MMIO_BASE(agpmaster) + I8XX_PTE_OFFSET; 321 GTT_HANDLE(agpmaster) = MMIO_HANDLE(agpmaster); 322 gmadr_off = I8XX_CONF_GMADR; 323 status = ddi_dev_regsize(devi, I8XX_FB_BAR, &apersize); 324 apersize = BYTES2MB(apersize); 325 CHECK_STATUS(status); 326 } 327 328 /* 329 * If memory size is smaller than a certain value, it means 330 * the register set number for graphics memory range might 331 * be wrong 332 */ 333 if (status != DDI_SUCCESS || apersize < 4) { 334 AGPM_DEBUG((CE_WARN, 335 "set_gtt_mmio: error in getting graphics memory")); 336 return (-1); 337 } 338 339 agpmaster->agpm_data.agpm_gtt.gtt_info.igd_apersize = apersize; 340 341 /* get graphics memory base address from GMADR */ 342 value = pci_config_get32(pci_acc_hdl, gmadr_off); 343 APER_BASE(agpmaster) = value & GTT_BASE_MASK; 344 AGPM_DEBUG((CE_NOTE, "set_gtt_mmio: aperbase = 0x%x, apersize = %ldM, " 345 "gtt_addr = %p, mmio_base = %p", APER_BASE(agpmaster), apersize, 346 (void *)GTT_ADDR(agpmaster), (void *)MMIO_BASE(agpmaster))); 347 return (0); 348 } 349 350 /* 351 * Try to initialize agp master. 352 * 0 is returned if the device is successfully initialized. AGP master soft 353 * state is returned in master_softcp if needed. 354 * Otherwise -1 is returned and *master_softcp is set to NULL. 355 */ 356 int 357 agpmaster_attach(dev_info_t *devi, agp_master_softc_t **master_softcp, 358 ddi_acc_handle_t pci_acc_hdl, minor_t minor) 359 { 360 int instance; 361 int status; 362 agp_master_softc_t *agpmaster; 363 char buf[80]; 364 365 366 ASSERT(pci_acc_hdl); 367 *master_softcp = NULL; 368 agpmaster = (agp_master_softc_t *) 369 kmem_zalloc(sizeof (agp_master_softc_t), KM_SLEEP); 370 371 agpmaster->agpm_id = 372 pci_config_get32(pci_acc_hdl, PCI_CONF_VENID); 373 agpmaster->agpm_acc_hdl = pci_acc_hdl; 374 375 if (!detect_i8xx_device(agpmaster)) { 376 /* Intel 8XX, 915, 945 and 965 series */ 377 if (set_gtt_mmio(devi, agpmaster, pci_acc_hdl) != 0) 378 goto fail; 379 } else if (detect_agp_devcice(agpmaster, pci_acc_hdl)) { 380 /* non IGD or AGP devices, AMD64 gart */ 381 AGPM_DEBUG((CE_WARN, 382 "agpmaster_attach: neither IGD or AGP devices exists")); 383 agpmaster_detach(&agpmaster); 384 return (0); 385 } 386 387 agpmaster->agpm_data.agpm_gtt.gtt_info.igd_devid = 388 agpmaster->agpm_id; 389 390 /* create minor node for IGD or AGP device */ 391 instance = ddi_get_instance(devi); 392 393 (void) sprintf(buf, "%s%d", AGPMASTER_NAME, instance); 394 status = ddi_create_minor_node(devi, buf, S_IFCHR, minor, 395 DDI_NT_AGP_MASTER, 0); 396 397 if (status != DDI_SUCCESS) { 398 AGPM_DEBUG((CE_WARN, 399 "agpmaster_attach: create agpmaster node failed")); 400 goto fail; 401 } 402 403 *master_softcp = agpmaster; 404 return (0); 405 fail: 406 agpmaster_detach(&agpmaster); 407 return (-1); 408 } 409 410 /* 411 * Currently, it handles ioctl requests related with agp master device for 412 * layered driver (agpgart) only. 413 */ 414 /*ARGSUSED*/ 415 int 416 agpmaster_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *cred, 417 int *rval, agp_master_softc_t *softc) 418 { 419 uint32_t base; 420 uint32_t addr; 421 igd_gtt_seg_t seg; 422 agp_info_t info; 423 uint32_t value; 424 off_t cap; 425 uint32_t command; 426 static char kernel_only[] = 427 "agpmaster_ioctl: %s is a kernel only ioctl"; 428 429 CONFIRM(softc); 430 431 switch (cmd) { 432 case DEVICE_DETECT: 433 if (!(mode & FKIOCTL)) { 434 AGPM_DEBUG((CE_CONT, kernel_only, "DEVICE_DETECT")); 435 return (ENXIO); 436 } 437 438 if (ddi_copyout(&softc->agpm_dev_type, 439 (void *)data, sizeof (int), mode)) 440 return (EFAULT); 441 break; 442 case AGP_MASTER_SETCMD: 443 if (!(mode & FKIOCTL)) { 444 AGPM_DEBUG((CE_CONT, kernel_only, "AGP_MASTER_SETCMD")); 445 return (ENXIO); 446 } 447 448 CONFIRM(softc->agpm_dev_type == DEVICE_IS_AGP); 449 CONFIRM(softc->agpm_data.agpm_acaptr); 450 451 if (ddi_copyin((void *)data, &command, 452 sizeof (uint32_t), mode)) 453 return (EFAULT); 454 455 pci_config_put32(softc->agpm_acc_hdl, 456 softc->agpm_data.agpm_acaptr + AGP_CONF_COMMAND, 457 command); 458 break; 459 case AGP_MASTER_GETINFO: 460 if (!(mode & FKIOCTL)) { 461 AGPM_DEBUG((CE_CONT, kernel_only, 462 "AGP_MASTER_GETINFO")); 463 return (ENXIO); 464 } 465 466 CONFIRM(softc->agpm_dev_type == DEVICE_IS_AGP); 467 CONFIRM(softc->agpm_data.agpm_acaptr); 468 469 cap = softc->agpm_data.agpm_acaptr; 470 value = pci_config_get32(softc->agpm_acc_hdl, cap); 471 info.agpi_version.agpv_major = (uint16_t)((value >> 20) & 0xf); 472 info.agpi_version.agpv_minor = (uint16_t)((value >> 16) & 0xf); 473 info.agpi_devid = softc->agpm_id; 474 info.agpi_mode = pci_config_get32( 475 softc->agpm_acc_hdl, cap + AGP_CONF_STATUS); 476 477 if (ddi_copyout(&info, (void *)data, 478 sizeof (agp_info_t), mode)) 479 return (EFAULT); 480 break; 481 case I810_SET_GTT_BASE: 482 if (!(mode & FKIOCTL)) { 483 AGPM_DEBUG((CE_CONT, kernel_only, "I810_SET_GTT_ADDR")); 484 return (ENXIO); 485 } 486 487 CONFIRM(softc->agpm_dev_type == DEVICE_IS_I810); 488 489 if (ddi_copyin((void *)data, &base, sizeof (uint32_t), mode)) 490 return (EFAULT); 491 492 /* enables page table */ 493 addr = (base & GTT_BASE_MASK) | GTT_TABLE_VALID; 494 495 AGPM_WRITE(softc, PGTBL_CTL, addr); 496 break; 497 case I8XX_GET_INFO: 498 if (!(mode & FKIOCTL)) { 499 AGPM_DEBUG((CE_CONT, kernel_only, "I8XX_GET_INFO")); 500 return (ENXIO); 501 } 502 503 CONFIRM(IS_IGD(softc)); 504 505 if (ddi_copyout(&softc->agpm_data.agpm_gtt.gtt_info, 506 (void *)data, sizeof (igd_info_t), mode)) 507 return (EFAULT); 508 break; 509 case I8XX_ADD2GTT: 510 if (!(mode & FKIOCTL)) { 511 AGPM_DEBUG((CE_CONT, kernel_only, "I8XX_ADD2GTT")); 512 return (ENXIO); 513 } 514 515 CONFIRM(IS_IGD(softc)); 516 517 if (ddi_copyin((void *)data, &seg, 518 sizeof (igd_gtt_seg_t), mode)) 519 return (EFAULT); 520 521 if (i8xx_add_to_gtt(&softc->agpm_data.agpm_gtt, seg)) 522 return (EINVAL); 523 break; 524 case I8XX_REM_GTT: 525 if (!(mode & FKIOCTL)) { 526 AGPM_DEBUG((CE_CONT, kernel_only, "I8XX_REM_GTT")); 527 return (ENXIO); 528 } 529 530 CONFIRM(IS_IGD(softc)); 531 532 if (ddi_copyin((void *)data, &seg, 533 sizeof (igd_gtt_seg_t), mode)) 534 return (EFAULT); 535 536 i8xx_remove_from_gtt(&softc->agpm_data.agpm_gtt, seg); 537 break; 538 case I8XX_UNCONFIG: 539 if (!(mode & FKIOCTL)) { 540 AGPM_DEBUG((CE_CONT, kernel_only, "I8XX_UNCONFIG")); 541 return (ENXIO); 542 } 543 544 CONFIRM(IS_IGD(softc)); 545 546 if (softc->agpm_dev_type == DEVICE_IS_I810) 547 AGPM_WRITE(softc, PGTBL_CTL, 0); 548 /* 549 * may need to clear all gtt entries here for i830 series, 550 * but may not be necessary 551 */ 552 break; 553 } 554 return (0); 555 } 556 557 /* 558 * If AGP cap pointer is successfully found, none-zero value is returned. 559 * Otherwise 0 is returned. 560 */ 561 static off_t 562 agpmaster_cap_find(ddi_acc_handle_t acc_handle) 563 { 564 off_t nextcap; 565 uint32_t ncapid; 566 uint8_t value; 567 568 /* check if this device supports capibility pointer */ 569 value = (uint8_t)(pci_config_get16(acc_handle, PCI_CONF_STAT) 570 & PCI_CONF_CAP_MASK); 571 572 if (!value) 573 return (0); 574 /* get the offset of the first capability pointer from CAPPTR */ 575 nextcap = (off_t)(pci_config_get8(acc_handle, AGP_CONF_CAPPTR)); 576 577 /* check AGP capability from the first capability pointer */ 578 while (nextcap) { 579 ncapid = pci_config_get32(acc_handle, nextcap); 580 if ((ncapid & PCI_CONF_CAPID_MASK) 581 == AGP_CAP_ID) /* find AGP cap */ 582 break; 583 584 nextcap = (off_t)((ncapid & PCI_CONF_NCAPID_MASK) >> 8); 585 } 586 587 return (nextcap); 588 589 } 590 591 /* 592 * If i8xx device is successfully detected, 0 is returned. 593 * Otherwise -1 is returned. 594 */ 595 static int 596 detect_i8xx_device(agp_master_softc_t *master_softc) 597 { 598 599 switch (master_softc->agpm_id) { 600 case INTEL_IGD_810: 601 case INTEL_IGD_810DC: 602 case INTEL_IGD_810E: 603 case INTEL_IGD_815: 604 master_softc->agpm_dev_type = DEVICE_IS_I810; 605 break; 606 case INTEL_IGD_830M: 607 case INTEL_IGD_845G: 608 case INTEL_IGD_855GM: 609 case INTEL_IGD_865G: 610 case INTEL_IGD_915: 611 case INTEL_IGD_915GM: 612 case INTEL_IGD_945: 613 case INTEL_IGD_945GM: 614 case INTEL_IGD_945GME: 615 case INTEL_IGD_946GZ: 616 case INTEL_IGD_965G1: 617 case INTEL_IGD_965G2: 618 case INTEL_IGD_965GM: 619 case INTEL_IGD_965GME: 620 case INTEL_IGD_965Q: 621 case INTEL_IGD_Q35: 622 case INTEL_IGD_G33: 623 case INTEL_IGD_Q33: 624 case INTEL_IGD_GM45: 625 case INTEL_IGD_EL: 626 case INTEL_IGD_Q45: 627 case INTEL_IGD_G45: 628 case INTEL_IGD_G41: 629 case INTEL_IGD_B43: 630 master_softc->agpm_dev_type = DEVICE_IS_I830; 631 break; 632 default: /* unknown id */ 633 return (-1); 634 } 635 636 return (0); 637 } 638 639 /* 640 * If agp master is succssfully detected, 0 is returned. 641 * Otherwise -1 is returned. 642 */ 643 static int 644 detect_agp_devcice(agp_master_softc_t *master_softc, 645 ddi_acc_handle_t acc_handle) 646 { 647 off_t cap; 648 649 cap = agpmaster_cap_find(acc_handle); 650 if (cap) { 651 master_softc->agpm_dev_type = DEVICE_IS_AGP; 652 master_softc->agpm_data.agpm_acaptr = cap; 653 return (0); 654 } else { 655 return (-1); 656 } 657 658 } 659 660 /* 661 * Please refer to GART and GTT entry format table in agpdefs.h for 662 * intel GTT entry format. 663 */ 664 static int 665 phys2entry(uint32_t type, uint32_t physaddr, uint32_t *entry) 666 { 667 uint32_t value; 668 669 switch (type) { 670 case AGP_PHYSICAL: 671 case AGP_NORMAL: 672 value = (physaddr & GTT_PTE_MASK) | GTT_PTE_VALID; 673 break; 674 default: 675 return (-1); 676 } 677 678 *entry = value; 679 680 return (0); 681 } 682 683 static int 684 i8xx_add_to_gtt(gtt_impl_t *gtt, igd_gtt_seg_t seg) 685 { 686 int i; 687 uint32_t *paddr; 688 uint32_t entry; 689 uint32_t maxpages; 690 691 maxpages = gtt->gtt_info.igd_apersize; 692 maxpages = GTT_MB_TO_PAGES(maxpages); 693 694 paddr = seg.igs_phyaddr; 695 696 /* check if gtt max page number is reached */ 697 if ((seg.igs_pgstart + seg.igs_npage) > maxpages) 698 return (-1); 699 700 paddr = seg.igs_phyaddr; 701 for (i = seg.igs_pgstart; i < (seg.igs_pgstart + seg.igs_npage); 702 i++, paddr++) { 703 if (phys2entry(seg.igs_type, *paddr, &entry)) 704 return (-1); 705 ddi_put32(gtt->gtt_handle, 706 (uint32_t *)(gtt->gtt_addr + i * sizeof (uint32_t)), 707 entry); 708 } 709 710 return (0); 711 } 712 713 static void 714 i8xx_remove_from_gtt(gtt_impl_t *gtt, igd_gtt_seg_t seg) 715 { 716 int i; 717 uint32_t maxpages; 718 719 maxpages = gtt->gtt_info.igd_apersize; 720 maxpages = GTT_MB_TO_PAGES(maxpages); 721 722 /* check if gtt max page number is reached */ 723 if ((seg.igs_pgstart + seg.igs_npage) > maxpages) 724 return; 725 726 for (i = seg.igs_pgstart; i < (seg.igs_pgstart + seg.igs_npage); i++) { 727 ddi_put32(gtt->gtt_handle, 728 (uint32_t *)(gtt->gtt_addr + i * sizeof (uint32_t)), 0); 729 } 730 } 731