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