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