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