Home | History | Annotate | Download | only in agpgart
      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 }
    954