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