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 2010 Sun Microsystems, Inc.  All rights reserved.
  29  * Use is subject to license terms.
  30  */
  31 
  32 
  33 #include <sys/systm.h>
  34 #include <sys/conf.h>
  35 #include <sys/modctl.h>
  36 #include <sys/file.h>
  37 #include <sys/stat.h>
  38 #include <sys/ddi.h>
  39 #include <sys/sunddi.h>
  40 #include <sys/sunndi.h>
  41 #include <sys/modctl.h>
  42 #include <sys/sunldi.h>
  43 #include <sys/pci.h>
  44 #include <sys/agpgart.h>
  45 #include <sys/agp/agpdefs.h>
  46 #include <sys/agp/agptarget_io.h>
  47 
  48 int agptarget_debug_var = 0;
  49 #define TARGETDB_PRINT2(fmt)    if (agptarget_debug_var >= 1) cmn_err fmt
  50 #define INST2NODENUM(inst)      (inst)
  51 #define DEV2INST(dev)           (getminor(dev))
  52 
  53 #define I915_IFPADDR    0x60
  54 #define I965_IFPADDR    0x70
  55 
  56 #define HIADDR(n)       ((uint32_t)(((uint64_t)(n) & \
  57                         0xFFFFFFFF00000000ULL) >> 32))
  58 #define LOADDR(n)       ((uint32_t)((uint64_t)(n) & 0x00000000FFFFFFFF))
  59 
  60 typedef struct agp_target_softstate {
  61         dev_info_t              *tsoft_dip;
  62         ddi_acc_handle_t        tsoft_pcihdl;
  63         uint32_t                tsoft_devid;
  64         /* The offset of the ACAPID register */
  65         off_t                   tsoft_acaptr;
  66         kmutex_t                tsoft_lock;
  67         int                     tsoft_gms_off; /* GMS offset in config */
  68         uint32_t                tsoft_gms;
  69 }agp_target_softstate_t;
  70 
  71 /*
  72  * To get the pre-allocated graphics mem size using Graphics Mode Select
  73  * (GMS) value.
  74  */
  75 typedef struct gms_mode {
  76         uint32_t        gm_devid;       /* bridge vendor + device id */
  77         off_t           gm_regoff;      /* mode selection register offset */
  78         uint32_t        gm_mask;        /* GMS mask */
  79         uint32_t        gm_num;         /* number of modes in gm_vec */
  80         int             *gm_vec;        /* modes array */
  81 } gms_mode_t;
  82 
  83 static void *agptarget_glob_soft_handle;
  84 
  85 #define GETSOFTC(instance)      ((agp_target_softstate_t *)     \
  86     ddi_get_soft_state(agptarget_glob_soft_handle, instance));
  87 
  88 /*
  89  * The AMD8151 bridge is the only supported 64 bit hardware
  90  */
  91 static int
  92 is_64bit_aper(agp_target_softstate_t *softstate)
  93 {
  94         return (softstate->tsoft_devid == AMD_BR_8151);
  95 }
  96 
  97 /*
  98  * Check if it is an intel bridge
  99  */
 100 static int
 101 is_intel_br(agp_target_softstate_t *softstate)
 102 {
 103         return ((softstate->tsoft_devid & VENDOR_ID_MASK) ==
 104             INTEL_VENDOR_ID);
 105 }
 106 
 107 /*
 108  * agp_target_cap_find()
 109  *
 110  * Description:
 111  *      This function searches the linked capability list to find the offset
 112  *      of the AGP capability register. When it was not found, return 0.
 113  *      This works for standard AGP chipsets, but not for some Intel chipsets,
 114  *      like the I830M/I830MP/I852PM/I852GME/I855GME. It will return 0 for
 115  *      these chipsets even if AGP is supported. So the offset of acapid
 116  *      should be set manually in thoses cases.
 117  *
 118  * Arguments:
 119  *      pci_handle              ddi acc handle of pci config
 120  *
 121  * Returns:
 122  *      0                       No capability pointer register found
 123  *      nexcap                  The AGP capability pointer register offset
 124  */
 125 static off_t
 126 agp_target_cap_find(ddi_acc_handle_t pci_handle)
 127 {
 128         off_t           nextcap = 0;
 129         uint32_t        ncapid = 0;
 130         uint8_t         value = 0;
 131 
 132         /* Check if this device supports the capability pointer */
 133         value = (uint8_t)(pci_config_get16(pci_handle, PCI_CONF_STAT)
 134             & PCI_CONF_CAP_MASK);
 135 
 136         if (!value)
 137                 return (0);
 138         /* Get the offset of the first capability pointer from CAPPTR */
 139         nextcap = (off_t)(pci_config_get8(pci_handle, AGP_CONF_CAPPTR));
 140 
 141         /* Check the AGP capability from the first capability pointer */
 142         while (nextcap) {
 143                 ncapid = pci_config_get32(pci_handle, nextcap);
 144                 /*
 145                  * AGP3.0 rev1.0 127  the capid was assigned by the PCI SIG,
 146                  * 845 data sheet page 69
 147                  */
 148                 if ((ncapid & PCI_CONF_CAPID_MASK) ==
 149                     AGP_CAP_ID) /* The AGP cap was found */
 150                         break;
 151 
 152                 nextcap = (off_t)((ncapid & PCI_CONF_NCAPID_MASK) >> 8);
 153         }
 154 
 155         return (nextcap);
 156 
 157 }
 158 
 159 /*
 160  * agp_target_get_aperbase()
 161  *
 162  * Description:
 163  *      This function gets the AGP aperture base address from the AGP target
 164  *      register, the AGP aperture base register was programmed by the BIOS.
 165  *
 166  * Arguments:
 167  *      softstate               driver soft state pointer
 168  *
 169  * Returns:
 170  *      aper_base               AGP aperture base address
 171  *
 172  * Notes:
 173  *      If a 64bit bridge device is available, the AGP aperture base address
 174  *      can be 64 bit.
 175  */
 176 static uint64_t
 177 agp_target_get_apbase(agp_target_softstate_t *softstate)
 178 {
 179         uint64_t aper_base;
 180 
 181         if (is_intel_br(softstate)) {
 182                 aper_base = pci_config_get32(softstate->tsoft_pcihdl,
 183                     AGP_CONF_APERBASE) & AGP_32_APERBASE_MASK;
 184         } else if (is_64bit_aper(softstate)) {
 185                 aper_base = pci_config_get64(softstate->tsoft_pcihdl,
 186                     AGP_CONF_APERBASE);
 187                 /* 32-bit or 64-bit aperbase base pointer */
 188                 if ((aper_base & AGP_APER_TYPE_MASK) == 0)
 189                         aper_base &= AGP_32_APERBASE_MASK;
 190                 else
 191                         aper_base &= AGP_64_APERBASE_MASK;
 192         }
 193 
 194         return (aper_base);
 195 }
 196 
 197 /*
 198  * agp_target_get_apsize()
 199  *
 200  * Description:
 201  *      This function gets the AGP aperture size by reading the AGP aperture
 202  *      size register.
 203  * Arguments:
 204  *      softstate               driver soft state pointer
 205  *
 206  * Return:
 207  *      size            The AGP aperture size in megabytes
 208  *      0               an unexpected error
 209  */
 210 static size_t
 211 agp_target_get_apsize(agp_target_softstate_t *softstate)
 212 {
 213         off_t cap;
 214         uint16_t value;
 215         size_t size, regsize;
 216 
 217         ASSERT(softstate->tsoft_acaptr);
 218         cap = softstate->tsoft_acaptr;
 219 
 220         if (is_intel_br(softstate)) {
 221                 /* extend this value to 16 bit for later tests */
 222                 value = (uint16_t)pci_config_get8(softstate->tsoft_pcihdl,
 223                     cap + AGP_CONF_APERSIZE) | AGP_APER_SIZE_MASK;
 224         } else if (is_64bit_aper(softstate)) {
 225                 value = pci_config_get16(softstate->tsoft_pcihdl,
 226                     cap + AGP_CONF_APERSIZE);
 227         }
 228 
 229         if (value & AGP_APER_128M_MASK) {
 230                 switch (value & AGP_APER_128M_MASK) {
 231                         case AGP_APER_4M:
 232                                 size = 4; /* 4M */
 233                                 break;
 234                         case AGP_APER_8M:
 235                                 size = 8; /* 8M */
 236                                 break;
 237                         case AGP_APER_16M:
 238                                 size = 16; /* 16M */
 239                                 break;
 240                         case AGP_APER_32M:
 241                                 size = 32; /* 32M */
 242                                 break;
 243                         case AGP_APER_64M:
 244                                 size = 64; /* 64M */
 245                                 break;
 246                         case AGP_APER_128M:
 247                                 size = 128; /* 128M */
 248                                 break;
 249                         default:
 250                                 size = 0; /* not true */
 251                 }
 252         } else {
 253                 switch (value & AGP_APER_4G_MASK) {
 254                         case AGP_APER_256M:
 255                                 size = 256; /* 256 M */
 256                                 break;
 257                         case AGP_APER_512M:
 258                                 size = 512; /* 512 M */
 259                                 break;
 260                         case AGP_APER_1024M:
 261                                 size = 1024; /* 1024 M */
 262                                 break;
 263                         case AGP_APER_2048M:
 264                                 size = 2048; /* 2048 M */
 265                                 break;
 266                         case AGP_APER_4G:
 267                                 size = 4096; /* 4096 M */
 268                                 break;
 269                         default:
 270                                 size = 0; /* not true */
 271                 }
 272         }
 273         /*
 274          * In some cases, there is no APSIZE register, so the size value
 275          * of 256M could be wrong. Check the value by reading the size of
 276          * the first register which was set in the PCI configuration space.
 277          */
 278         if (size == 256) {
 279                 if (ddi_dev_regsize(softstate->tsoft_dip,
 280                     AGP_TARGET_BAR1, (off_t *)&regsize) == DDI_FAILURE)
 281                         return (0);
 282 
 283                 if (MB2BYTES(size) != regsize) {
 284                         TARGETDB_PRINT2((CE_WARN,
 285                             "APSIZE 256M doesn't match regsize %lx",
 286                             regsize));
 287                         TARGETDB_PRINT2((CE_WARN, "Use regsize instead"));
 288                         size = BYTES2MB(regsize);
 289                 }
 290         }
 291 
 292         return (size);
 293 }
 294 
 295 static void
 296 agp_target_set_gartaddr(agp_target_softstate_t *softstate, uint32_t gartaddr)
 297 {
 298         ASSERT(softstate->tsoft_acaptr);
 299 
 300         /* Disable the GTLB for Intel chipsets */
 301         pci_config_put16(softstate->tsoft_pcihdl,
 302             softstate->tsoft_acaptr + AGP_CONF_CONTROL, 0x0000);
 303 
 304         pci_config_put32(softstate->tsoft_pcihdl,
 305             softstate->tsoft_acaptr + AGP_CONF_ATTBASE,
 306             gartaddr & AGP_ATTBASE_MASK);
 307 }
 308 
 309 /*
 310  * Pre-allocated graphics memory for every type of Intel north bridge, mem size
 311  * are specified in kbytes.
 312  */
 313 #define GMS_MB(n)       ((n) * 1024)
 314 #define GMS_SHIFT       4
 315 #define GMS_SIZE(a)     (sizeof (a) / sizeof (int))
 316 
 317 /*
 318  * Since value zero always means "No memory pre-allocated", value of (GMS - 1)
 319  * is used to index these arrays, i.e. gms_xxx[1] contains the mem size (in kb)
 320  * that GMS value 0x1 corresponding to.
 321  *
 322  * Assuming all "reserved" GMS value as zero bytes of pre-allocated graphics
 323  * memory, unless some special BIOS settings exist.
 324  */
 325 static int gms_810[12] = {0, 0, 0, 0, 0, 0, 0, 512, 0, 0, 0, GMS_MB(1)};
 326 static int gms_830_845[4] = {0, 512, GMS_MB(1), GMS_MB(8)};
 327 static int gms_855GM[5] = {GMS_MB(1), GMS_MB(4), GMS_MB(8), GMS_MB(16),
 328         GMS_MB(32)};
 329 /* There is no modes for 16M in datasheet, but some BIOS add it. */
 330 static int gms_865_915GM[4] = {GMS_MB(1), 0, GMS_MB(8), GMS_MB(16)};
 331 static int gms_915_945_965[3] = {GMS_MB(1), 0, GMS_MB(8)};
 332 static int gms_965GM[7] = {GMS_MB(1), GMS_MB(4), GMS_MB(8), GMS_MB(16),
 333         GMS_MB(32), GMS_MB(48), GMS_MB(64)};
 334 static int gms_X33[9] = {GMS_MB(1), GMS_MB(4), GMS_MB(8), GMS_MB(16),
 335         GMS_MB(32), GMS_MB(48), GMS_MB(64), GMS_MB(128), GMS_MB(256)};
 336 static int gms_G4X[13] = {0, 0, 0, 0,
 337         GMS_MB(32), GMS_MB(48), GMS_MB(64), GMS_MB(128), GMS_MB(256),
 338         GMS_MB(96), GMS_MB(160), GMS_MB(224), GMS_MB(352)};
 339 
 340 static gms_mode_t gms_modes[] = {
 341         {INTEL_BR_810, I810_CONF_SMRAM, I810_GMS_MASK,
 342                 GMS_SIZE(gms_810), gms_810},
 343         {INTEL_BR_810DC, I810_CONF_SMRAM, I810_GMS_MASK,
 344                 GMS_SIZE(gms_810), gms_810},
 345         {INTEL_BR_810E, I810_CONF_SMRAM, I810_GMS_MASK,
 346                 GMS_SIZE(gms_810), gms_810},
 347         {INTEL_BR_830M, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 348                 GMS_SIZE(gms_830_845), gms_830_845},
 349         {INTEL_BR_845, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 350                 GMS_SIZE(gms_830_845), gms_830_845},
 351         {INTEL_BR_855GM, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 352                 GMS_SIZE(gms_855GM), gms_855GM},
 353         {INTEL_BR_865, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 354                 GMS_SIZE(gms_865_915GM), gms_865_915GM},
 355         {INTEL_BR_915GM, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 356                 GMS_SIZE(gms_865_915GM), gms_865_915GM},
 357         {INTEL_BR_915, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 358                 GMS_SIZE(gms_915_945_965), gms_915_945_965},
 359         {INTEL_BR_945, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 360                 GMS_SIZE(gms_915_945_965), gms_915_945_965},
 361         {INTEL_BR_945GM, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 362                 GMS_SIZE(gms_915_945_965), gms_915_945_965},
 363         {INTEL_BR_945GME, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 364                 GMS_SIZE(gms_915_945_965), gms_915_945_965},
 365         {INTEL_BR_946GZ, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 366                 GMS_SIZE(gms_915_945_965), gms_915_945_965},
 367         {INTEL_BR_965G1, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 368                 GMS_SIZE(gms_915_945_965), gms_915_945_965},
 369         {INTEL_BR_965G2, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 370                 GMS_SIZE(gms_915_945_965), gms_915_945_965},
 371         {INTEL_BR_965Q, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 372                 GMS_SIZE(gms_915_945_965), gms_915_945_965},
 373         {INTEL_BR_965GM, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 374                 GMS_SIZE(gms_965GM), gms_965GM},
 375         {INTEL_BR_965GME, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 376                 GMS_SIZE(gms_965GM), gms_965GM},
 377         {INTEL_BR_Q35, I8XX_CONF_GC, IX33_GC_MODE_MASK,
 378                 GMS_SIZE(gms_X33), gms_X33},
 379         {INTEL_BR_G33, I8XX_CONF_GC, IX33_GC_MODE_MASK,
 380                 GMS_SIZE(gms_X33), gms_X33},
 381         {INTEL_BR_Q33, I8XX_CONF_GC, IX33_GC_MODE_MASK,
 382                 GMS_SIZE(gms_X33), gms_X33},
 383         {INTEL_BR_GM45, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 384                 GMS_SIZE(gms_965GM), gms_965GM},
 385         {INTEL_BR_EL, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 386                 GMS_SIZE(gms_G4X), gms_G4X},
 387         {INTEL_BR_Q45, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 388                 GMS_SIZE(gms_G4X), gms_G4X},
 389         {INTEL_BR_G45, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 390                 GMS_SIZE(gms_G4X), gms_G4X},
 391         {INTEL_BR_G41, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 392                 GMS_SIZE(gms_G4X), gms_G4X},
 393         {INTEL_BR_IGDNG_D, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 394                 GMS_SIZE(gms_G4X), gms_G4X},
 395         {INTEL_BR_IGDNG_M, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 396                 GMS_SIZE(gms_G4X), gms_G4X},
 397         {INTEL_BR_IGDNG_MA, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 398                 GMS_SIZE(gms_G4X), gms_G4X},
 399         {INTEL_BR_IGDNG_MC2, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 400                 GMS_SIZE(gms_G4X), gms_G4X},
 401         {INTEL_BR_B43, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
 402                 GMS_SIZE(gms_G4X), gms_G4X}
 403 };
 404 static int
 405 get_chip_gms(uint32_t devid)
 406 {
 407         int num_modes;
 408         int i;
 409 
 410         num_modes = (sizeof (gms_modes) / sizeof (gms_mode_t));
 411 
 412         for (i = 0; i < num_modes; i++) {
 413                 if (gms_modes[i].gm_devid == devid)
 414                         break;
 415         }
 416 
 417         return ((i == num_modes) ? -1 : i);
 418 }
 419 
 420 /* Returns the size (kbytes) of pre-allocated graphics memory */
 421 static size_t
 422 i8xx_biosmem_detect(agp_target_softstate_t *softstate)
 423 {
 424         uint8_t memval;
 425         size_t kbytes;
 426         int     gms_off;
 427 
 428         kbytes = 0;
 429         gms_off = softstate->tsoft_gms_off;
 430 
 431         /* fetch the GMS value from DRAM controller */
 432         memval = pci_config_get8(softstate->tsoft_pcihdl,
 433             gms_modes[gms_off].gm_regoff);
 434         TARGETDB_PRINT2((CE_NOTE, "i8xx_biosmem_detect: memval = %x", memval));
 435         memval = (memval & gms_modes[gms_off].gm_mask) >> GMS_SHIFT;
 436         /* assuming zero byte for 0 or "reserved" GMS values */
 437         if (memval == 0 || memval > gms_modes[gms_off].gm_num) {
 438                 TARGETDB_PRINT2((CE_WARN, "i8xx_biosmem_detect: "
 439                     "devid = %x, GMS = %x. assuming zero byte of "
 440                     "pre-allocated memory",
 441                     gms_modes[gms_off].gm_devid, memval));
 442                 goto done;
 443         }
 444         memval--;       /* use (GMS_value - 1) as index */
 445         kbytes = (gms_modes[gms_off].gm_vec)[memval];
 446 
 447 done:
 448         TARGETDB_PRINT2((CE_NOTE,
 449             "i8xx_biosmem_detect: %ldKB BIOS pre-allocated memory detected",
 450             kbytes));
 451         return (kbytes);
 452 }
 453 
 454 /*ARGSUSED*/
 455 static int agptarget_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd,
 456     void *arg, void **resultp)
 457 {
 458         agp_target_softstate_t *st;
 459         int instance, rval = DDI_FAILURE;
 460         dev_t dev;
 461 
 462         switch (cmd) {
 463         case DDI_INFO_DEVT2DEVINFO:
 464                 dev = (dev_t)arg;
 465                 instance = DEV2INST(dev);
 466                 st = ddi_get_soft_state(agptarget_glob_soft_handle, instance);
 467                 if (st != NULL) {
 468                         mutex_enter(&st->tsoft_lock);
 469                         *resultp = st->tsoft_dip;
 470                         mutex_exit(&st->tsoft_lock);
 471                         rval = DDI_SUCCESS;
 472                 } else
 473                         *resultp = NULL;
 474 
 475                 break;
 476         case DDI_INFO_DEVT2INSTANCE:
 477                 dev = (dev_t)arg;
 478                 instance = DEV2INST(dev);
 479                 *resultp = (void *)(uintptr_t)instance;
 480                 rval = DDI_SUCCESS;
 481         default:
 482                 break;
 483         }
 484 
 485         return (rval);
 486 }
 487 
 488 static int
 489 intel_br_resume(agp_target_softstate_t *softstate)
 490 {
 491         int gms_off;
 492 
 493         gms_off = softstate->tsoft_gms_off;
 494 
 495         /*
 496          * We recover the gmch graphics control register here
 497          */
 498         pci_config_put16(softstate->tsoft_pcihdl,
 499             gms_modes[gms_off].gm_regoff, softstate->tsoft_gms);
 500 
 501         return (DDI_SUCCESS);
 502 }
 503 static int
 504 intel_br_suspend(agp_target_softstate_t *softstate)
 505 {
 506         int gms_off;
 507 
 508         gms_off = softstate->tsoft_gms_off;
 509         softstate->tsoft_gms = pci_config_get16(softstate->tsoft_pcihdl,
 510             gms_modes[gms_off].gm_regoff);
 511 
 512         return (DDI_SUCCESS);
 513 }
 514 
 515 static int
 516 agp_target_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 517 {
 518         agp_target_softstate_t *softstate;
 519         int instance;
 520         int status;
 521 
 522         instance = ddi_get_instance(dip);
 523 
 524         switch (cmd) {
 525         case DDI_ATTACH:
 526                 break;
 527         case DDI_RESUME:
 528                 softstate =
 529                     ddi_get_soft_state(agptarget_glob_soft_handle, instance);
 530                 return (intel_br_resume(softstate));
 531         default:
 532                 TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
 533                     "only attach and resume ops are supported"));
 534                 return (DDI_FAILURE);
 535         }
 536 
 537         if (ddi_soft_state_zalloc(agptarget_glob_soft_handle,
 538             instance) != DDI_SUCCESS) {
 539                 TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
 540                     "soft state zalloc failed"));
 541                 return (DDI_FAILURE);
 542         }
 543 
 544         softstate = ddi_get_soft_state(agptarget_glob_soft_handle, instance);
 545         mutex_init(&softstate->tsoft_lock, NULL, MUTEX_DRIVER, NULL);
 546         softstate->tsoft_dip = dip;
 547         status = pci_config_setup(dip, &softstate->tsoft_pcihdl);
 548         if (status != DDI_SUCCESS) {
 549                 TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
 550                     "pci config setup failed"));
 551                 ddi_soft_state_free(agptarget_glob_soft_handle,
 552                     instance);
 553                 return (DDI_FAILURE);
 554         }
 555 
 556         softstate->tsoft_devid = pci_config_get32(softstate->tsoft_pcihdl,
 557             PCI_CONF_VENID);
 558         softstate->tsoft_gms_off = get_chip_gms(softstate->tsoft_devid);
 559         if (softstate->tsoft_gms_off < 0) {
 560                 TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
 561                     "read gms offset failed"));
 562                 pci_config_teardown(&softstate->tsoft_pcihdl);
 563                 ddi_soft_state_free(agptarget_glob_soft_handle,
 564                     instance);
 565                 return (DDI_FAILURE);
 566         }
 567         softstate->tsoft_acaptr = agp_target_cap_find(softstate->tsoft_pcihdl);
 568         if (softstate->tsoft_acaptr == 0) {
 569                 /* Make a correction for some Intel chipsets */
 570                 if (is_intel_br(softstate))
 571                         softstate->tsoft_acaptr = AGP_CAP_OFF_DEF;
 572                 else {
 573                         TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
 574                             "Not a supposed corretion"));
 575                         pci_config_teardown(&softstate->tsoft_pcihdl);
 576                         ddi_soft_state_free(agptarget_glob_soft_handle,
 577                             instance);
 578                         return (DDI_FAILURE);
 579                 }
 580         }
 581 
 582         status = ddi_create_minor_node(dip, AGPTARGET_NAME, S_IFCHR,
 583             INST2NODENUM(instance), DDI_NT_AGP_TARGET, 0);
 584 
 585         if (status != DDI_SUCCESS) {
 586                 TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
 587                     "Create minor node failed"));
 588                 pci_config_teardown(&softstate->tsoft_pcihdl);
 589                 ddi_soft_state_free(agptarget_glob_soft_handle, instance);
 590                 return (DDI_FAILURE);
 591         }
 592 
 593         return (DDI_SUCCESS);
 594 }
 595 
 596 /*ARGSUSED*/
 597 static int
 598 agp_target_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 599 {
 600         int instance;
 601         agp_target_softstate_t *softstate;
 602 
 603         instance = ddi_get_instance(dip);
 604         softstate = ddi_get_soft_state(agptarget_glob_soft_handle, instance);
 605 
 606         if (cmd == DDI_SUSPEND) {
 607                 /* get GMS modes list entry */
 608                 return (intel_br_suspend(softstate));
 609         }
 610 
 611         if (cmd != DDI_DETACH) {
 612                 TARGETDB_PRINT2((CE_WARN, "agp_target_detach:"
 613                     "only detach and suspend ops are supported"));
 614                 return (DDI_FAILURE);
 615         }
 616 
 617         ddi_remove_minor_node(dip, AGPTARGET_NAME);
 618         pci_config_teardown(&softstate->tsoft_pcihdl);
 619         mutex_destroy(&softstate->tsoft_lock);
 620         ddi_soft_state_free(agptarget_glob_soft_handle, instance);
 621         return (DDI_SUCCESS);
 622 }
 623 
 624 /*ARGSUSED*/
 625 static int
 626 agp_target_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
 627     cred_t *cred, int *rval)
 628 {
 629         int instance = DEV2INST(dev);
 630         agp_target_softstate_t *st;
 631         static char kernel_only[] =
 632             "amd64_gart_ioctl: is a kernel only ioctl";
 633 
 634         if (!(mode & FKIOCTL)) {
 635                 TARGETDB_PRINT2((CE_CONT, kernel_only));
 636                 return (ENXIO);
 637         }
 638         st = GETSOFTC(instance);
 639 
 640         if (st == NULL)
 641                 return (ENXIO);
 642 
 643         mutex_enter(&st->tsoft_lock);
 644 
 645         switch (cmd) {
 646         case CHIP_DETECT:
 647         {
 648                 int type = 0;
 649 
 650                 if (is_intel_br(st))
 651                         type = CHIP_IS_INTEL;
 652                 else if (is_64bit_aper(st))
 653                         type = CHIP_IS_AMD;
 654                 else {
 655                         type = 0;
 656                         TARGETDB_PRINT2((CE_WARN, "Unknown bridge!"));
 657                 }
 658 
 659                 if (ddi_copyout(&type, (void *)data, sizeof (int), mode)) {
 660                         mutex_exit(&st->tsoft_lock);
 661                         return (EFAULT);
 662                 }
 663 
 664                 break;
 665         }
 666         case I8XX_GET_PREALLOC_SIZE:
 667         {
 668                 size_t prealloc_size;
 669 
 670                 if (!is_intel_br(st)) {
 671                         mutex_exit(&st->tsoft_lock);
 672                         return (EINVAL);
 673                 }
 674 
 675                 prealloc_size = i8xx_biosmem_detect(st);
 676                 if (ddi_copyout(&prealloc_size, (void *)data,
 677                     sizeof (size_t), mode)) {
 678                         mutex_exit(&st->tsoft_lock);
 679                         return (EFAULT);
 680                 }
 681 
 682                 break;
 683         }
 684         case AGP_TARGET_GETINFO:
 685         {
 686                 i_agp_info_t info;
 687                 uint32_t value;
 688                 off_t cap;
 689 
 690                 ASSERT(st->tsoft_acaptr);
 691 
 692                 cap = st->tsoft_acaptr;
 693                 value = pci_config_get32(st->tsoft_pcihdl, cap);
 694                 info.iagp_ver.agpv_major = (uint16_t)((value >> 20) & 0xf);
 695                 info.iagp_ver.agpv_minor = (uint16_t)((value >> 16) & 0xf);
 696                 info.iagp_devid = st->tsoft_devid;
 697                 info.iagp_mode = pci_config_get32(st->tsoft_pcihdl,
 698                     cap + AGP_CONF_STATUS);
 699                 info.iagp_aperbase = agp_target_get_apbase(st);
 700                 info.iagp_apersize = agp_target_get_apsize(st);
 701 
 702                 if (ddi_copyout(&info, (void *)data,
 703                     sizeof (i_agp_info_t), mode)) {
 704                         mutex_exit(&st->tsoft_lock);
 705                         return (EFAULT);
 706                 }
 707                 break;
 708 
 709         }
 710         /*
 711          * This ioctl is only for Intel AGP chipsets.
 712          * It is not necessary for the AMD8151 AGP bridge, because
 713          * this register in the AMD8151 does not control any hardware.
 714          * It is only provided for compatibility with an Intel AGP bridge.
 715          * Please refer to the <<AMD8151 data sheet>> page 24,
 716          * AGP device GART pointer.
 717          */
 718         case AGP_TARGET_SET_GATTADDR:
 719         {
 720                 uint32_t gartaddr;
 721 
 722                 if (ddi_copyin((void *)data, &gartaddr,
 723                     sizeof (uint32_t), mode)) {
 724                         mutex_exit(&st->tsoft_lock);
 725                         return (EFAULT);
 726                 }
 727 
 728                 agp_target_set_gartaddr(st, gartaddr);
 729                 break;
 730         }
 731         case AGP_TARGET_SETCMD:
 732         {
 733                 uint32_t command;
 734 
 735                 if (ddi_copyin((void *)data, &command,
 736                     sizeof (uint32_t), mode)) {
 737                         mutex_exit(&st->tsoft_lock);
 738                         return (EFAULT);
 739                 }
 740 
 741                 ASSERT(st->tsoft_acaptr);
 742 
 743                 pci_config_put32(st->tsoft_pcihdl,
 744                     st->tsoft_acaptr + AGP_CONF_COMMAND,
 745                     command);
 746                 break;
 747 
 748         }
 749         case AGP_TARGET_FLUSH_GTLB:
 750         {
 751                 uint16_t value;
 752 
 753                 ASSERT(st->tsoft_acaptr);
 754 
 755                 value = pci_config_get16(st->tsoft_pcihdl,
 756                     st->tsoft_acaptr + AGP_CONF_CONTROL);
 757                 value &= ~AGPCTRL_GTLBEN;
 758                 pci_config_put16(st->tsoft_pcihdl,
 759                     st->tsoft_acaptr + AGP_CONF_CONTROL, value);
 760                 value |= AGPCTRL_GTLBEN;
 761                 pci_config_put16(st->tsoft_pcihdl,
 762                     st->tsoft_acaptr + AGP_CONF_CONTROL, value);
 763 
 764                 break;
 765         }
 766         case AGP_TARGET_CONFIGURE:
 767         {
 768                 uint8_t value;
 769 
 770                 ASSERT(st->tsoft_acaptr);
 771 
 772                 /*
 773                  * In Intel agp bridges, agp misc register offset
 774                  * is indexed from 0 instead of capability register.
 775                  * AMD agp bridges have no such misc register
 776                  * to control the aperture access, and they have
 777                  * similar regsiters in CPU gart devices instead.
 778                  */
 779 
 780                 if (is_intel_br(st)) {
 781                         value = pci_config_get8(st->tsoft_pcihdl,
 782                             st->tsoft_acaptr + AGP_CONF_MISC);
 783                         value |= AGP_MISC_APEN;
 784                         pci_config_put8(st->tsoft_pcihdl,
 785                             st->tsoft_acaptr + AGP_CONF_MISC, value);
 786                 }
 787                 break;
 788 
 789         }
 790         case AGP_TARGET_UNCONFIG:
 791         {
 792                 uint32_t value1;
 793                 uint8_t value2;
 794 
 795                 ASSERT(st->tsoft_acaptr);
 796 
 797                 pci_config_put16(st->tsoft_pcihdl,
 798                     st->tsoft_acaptr + AGP_CONF_CONTROL, 0x0);
 799 
 800                 if (is_intel_br(st)) {
 801                         value2 = pci_config_get8(st->tsoft_pcihdl,
 802                             st->tsoft_acaptr + AGP_CONF_MISC);
 803                         value2 &= ~AGP_MISC_APEN;
 804                         pci_config_put8(st->tsoft_pcihdl,
 805                             st->tsoft_acaptr + AGP_CONF_MISC, value2);
 806                 }
 807 
 808                 value1 = pci_config_get32(st->tsoft_pcihdl,
 809                     st->tsoft_acaptr + AGP_CONF_COMMAND);
 810                 value1 &= ~AGPCMD_AGPEN;
 811                 pci_config_put32(st->tsoft_pcihdl,
 812                     st->tsoft_acaptr + AGP_CONF_COMMAND,
 813                     value1);
 814 
 815                 pci_config_put32(st->tsoft_pcihdl,
 816                     st->tsoft_acaptr + AGP_CONF_ATTBASE, 0x0);
 817 
 818                 break;
 819         }
 820 
 821         case INTEL_CHIPSET_FLUSH_SETUP:
 822         case INTEL_CHIPSET_FLUSH:
 823         case INTEL_CHIPSET_FLUSH_FREE:
 824                 break;
 825         default:
 826                 mutex_exit(&st->tsoft_lock);
 827                 return (ENXIO);
 828         } /* end switch */
 829 
 830         mutex_exit(&st->tsoft_lock);
 831 
 832         return (0);
 833 }
 834 
 835 /*ARGSUSED*/
 836 static int
 837 agp_target_open(dev_t *devp, int flag, int otyp, cred_t *cred)
 838 {
 839         int instance = DEV2INST(*devp);
 840         agp_target_softstate_t *st;
 841 
 842         if (!(flag & FKLYR))
 843                 return (ENXIO);
 844 
 845         st = GETSOFTC(instance);
 846 
 847         if (st == NULL)
 848                 return (ENXIO);
 849 
 850         return (0);
 851 }
 852 
 853 /*ARGSUSED*/
 854 static int
 855 agp_target_close(dev_t dev, int flag, int otyp, cred_t *cred)
 856 {
 857         int instance = DEV2INST(dev);
 858         agp_target_softstate_t *st;
 859 
 860         st = GETSOFTC(instance);
 861 
 862         if (st == NULL)
 863                 return (ENXIO);
 864 
 865         return (0);
 866 }
 867 
 868 static  struct  cb_ops  agp_target_cb_ops = {
 869         agp_target_open,                /* cb_open */
 870         agp_target_close,               /* cb_close */
 871         nodev,                          /* cb_strategy */
 872         nodev,                          /* cb_print */
 873         nodev,                          /* cb_dump */
 874         nodev,                          /* cb_read() */
 875         nodev,                          /* cb_write() */
 876         agp_target_ioctl,               /* cb_ioctl */
 877         nodev,                          /* cb_devmap */
 878         nodev,                          /* cb_mmap */
 879         nodev,                          /* cb_segmap */
 880         nochpoll,                       /* cb_chpoll */
 881         ddi_prop_op,                    /* cb_prop_op */
 882         0,                              /* cb_stream */
 883         D_NEW | D_MP,                   /* cb_flag */
 884         CB_REV,                         /* cb_ops version? */
 885         nodev,                          /* cb_aread() */
 886         nodev,                          /* cb_awrite() */
 887 };
 888 
 889 /* device operations */
 890 static struct dev_ops agp_target_ops = {
 891         DEVO_REV,               /* devo_rev */
 892         0,                      /* devo_refcnt */
 893         agptarget_getinfo,      /* devo_getinfo */
 894         nulldev,                /* devo_identify */
 895         nulldev,                /* devo_probe */
 896         agp_target_attach,      /* devo_attach */
 897         agp_target_detach,      /* devo_detach */
 898         nodev,                  /* devo_reset */
 899         &agp_target_cb_ops, /* devo_cb_ops */
 900         0,                      /* devo_bus_ops */
 901         0,                      /* devo_power */
 902         ddi_quiesce_not_needed, /* devo_quiesce */
 903 };
 904 
 905 static  struct modldrv modldrv = {
 906         &mod_driverops,
 907         "AGP target driver",
 908         &agp_target_ops,
 909 };
 910 
 911 static  struct modlinkage modlinkage = {
 912         MODREV_1,               /* MODREV_1 is indicated by manual */
 913         {&modldrv, NULL, NULL, NULL}
 914 };
 915 
 916 int
 917 _init(void)
 918 {
 919         int ret;
 920 
 921         ret = ddi_soft_state_init(&agptarget_glob_soft_handle,
 922             sizeof (agp_target_softstate_t), 1);
 923 
 924         if (ret)
 925                 goto err1;
 926 
 927         if ((ret = mod_install(&modlinkage)) != 0) {
 928                 goto err2;
 929         }
 930 
 931         return (DDI_SUCCESS);
 932 err2:
 933         ddi_soft_state_fini(&agptarget_glob_soft_handle);
 934 err1:
 935         return (ret);
 936 }
 937 
 938 int
 939 _info(struct  modinfo *modinfop)
 940 {
 941         return (mod_info(&modlinkage, modinfop));
 942 }
 943 
 944 int
 945 _fini(void)
 946 {
 947         int     ret;
 948 
 949         if ((ret = mod_remove(&modlinkage)) == 0) {
 950                 ddi_soft_state_fini(&agptarget_glob_soft_handle);
 951         }
 952         return (ret);
 953 }