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