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