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