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