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