1ae115bc7Smrj /*
2543414e0Skz151634 * CDDL HEADER START
3543414e0Skz151634 *
4543414e0Skz151634 * The contents of this file are subject to the terms of the
5543414e0Skz151634 * Common Development and Distribution License (the "License").
6543414e0Skz151634 * You may not use this file except in compliance with the License.
7543414e0Skz151634 *
8543414e0Skz151634 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9543414e0Skz151634 * or http://www.opensolaris.org/os/licensing.
10543414e0Skz151634 * See the License for the specific language governing permissions
11543414e0Skz151634 * and limitations under the License.
12543414e0Skz151634 *
13543414e0Skz151634 * When distributing Covered Code, include this CDDL HEADER in each
14543414e0Skz151634 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15543414e0Skz151634 * If applicable, add the following below this CDDL HEADER, with the
16543414e0Skz151634 * fields enclosed by brackets "[]" replaced with your own identifying
17543414e0Skz151634 * information: Portions Copyright [yyyy] [name of copyright owner]
18543414e0Skz151634 *
19543414e0Skz151634 * CDDL HEADER END
20543414e0Skz151634 */
21543414e0Skz151634
22543414e0Skz151634 /*
230035d21cSmiao chen - Sun Microsystems - Beijing China * Copyright (c) 2009, Intel Corporation.
240035d21cSmiao chen - Sun Microsystems - Beijing China * All Rights Reserved.
250035d21cSmiao chen - Sun Microsystems - Beijing China */
260035d21cSmiao chen - Sun Microsystems - Beijing China
270035d21cSmiao chen - Sun Microsystems - Beijing China /*
28*92d2c9e8SEdward Shu * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
29ae115bc7Smrj * Use is subject to license terms.
30ae115bc7Smrj */
31ae115bc7Smrj
32ae115bc7Smrj
33ae115bc7Smrj #include <sys/systm.h>
34ae115bc7Smrj #include <sys/conf.h>
35ae115bc7Smrj #include <sys/modctl.h>
36ae115bc7Smrj #include <sys/file.h>
37ae115bc7Smrj #include <sys/stat.h>
38ae115bc7Smrj #include <sys/ddi.h>
39ae115bc7Smrj #include <sys/sunddi.h>
400035d21cSmiao chen - Sun Microsystems - Beijing China #include <sys/sunndi.h>
41ae115bc7Smrj #include <sys/modctl.h>
42ae115bc7Smrj #include <sys/sunldi.h>
43ae115bc7Smrj #include <sys/pci.h>
44ae115bc7Smrj #include <sys/agpgart.h>
45ae115bc7Smrj #include <sys/agp/agpdefs.h>
46ae115bc7Smrj #include <sys/agp/agptarget_io.h>
47ae115bc7Smrj
48ae115bc7Smrj int agptarget_debug_var = 0;
49ae115bc7Smrj #define TARGETDB_PRINT2(fmt) if (agptarget_debug_var >= 1) cmn_err fmt
50ae115bc7Smrj #define INST2NODENUM(inst) (inst)
51ae115bc7Smrj #define DEV2INST(dev) (getminor(dev))
52ae115bc7Smrj
530035d21cSmiao chen - Sun Microsystems - Beijing China #define I915_IFPADDR 0x60
540035d21cSmiao chen - Sun Microsystems - Beijing China #define I965_IFPADDR 0x70
550035d21cSmiao chen - Sun Microsystems - Beijing China
560035d21cSmiao chen - Sun Microsystems - Beijing China #define HIADDR(n) ((uint32_t)(((uint64_t)(n) & \
570035d21cSmiao chen - Sun Microsystems - Beijing China 0xFFFFFFFF00000000ULL) >> 32))
580035d21cSmiao chen - Sun Microsystems - Beijing China #define LOADDR(n) ((uint32_t)((uint64_t)(n) & 0x00000000FFFFFFFF))
590035d21cSmiao chen - Sun Microsystems - Beijing China
60ae115bc7Smrj typedef struct agp_target_softstate {
61ae115bc7Smrj dev_info_t *tsoft_dip;
62ae115bc7Smrj ddi_acc_handle_t tsoft_pcihdl;
63ae115bc7Smrj uint32_t tsoft_devid;
64ae115bc7Smrj /* The offset of the ACAPID register */
65ae115bc7Smrj off_t tsoft_acaptr;
66ae115bc7Smrj kmutex_t tsoft_lock;
6731c83a1bSms148562 int tsoft_gms_off; /* GMS offset in config */
6831c83a1bSms148562 uint32_t tsoft_gms;
69ae115bc7Smrj }agp_target_softstate_t;
70ae115bc7Smrj
71c4f91784Skz151634 /*
72c4f91784Skz151634 * To get the pre-allocated graphics mem size using Graphics Mode Select
73c4f91784Skz151634 * (GMS) value.
74c4f91784Skz151634 */
75c4f91784Skz151634 typedef struct gms_mode {
76c4f91784Skz151634 uint32_t gm_devid; /* bridge vendor + device id */
77c4f91784Skz151634 off_t gm_regoff; /* mode selection register offset */
78c4f91784Skz151634 uint32_t gm_mask; /* GMS mask */
79c4f91784Skz151634 uint32_t gm_num; /* number of modes in gm_vec */
80c4f91784Skz151634 int *gm_vec; /* modes array */
81c4f91784Skz151634 } gms_mode_t;
82c4f91784Skz151634
83ae115bc7Smrj static void *agptarget_glob_soft_handle;
84ae115bc7Smrj
85ae115bc7Smrj #define GETSOFTC(instance) ((agp_target_softstate_t *) \
86ae115bc7Smrj ddi_get_soft_state(agptarget_glob_soft_handle, instance));
87ae115bc7Smrj
88ae115bc7Smrj /*
89ae115bc7Smrj * The AMD8151 bridge is the only supported 64 bit hardware
90ae115bc7Smrj */
91ae115bc7Smrj static int
is_64bit_aper(agp_target_softstate_t * softstate)92ae115bc7Smrj is_64bit_aper(agp_target_softstate_t *softstate)
93ae115bc7Smrj {
94ae115bc7Smrj return (softstate->tsoft_devid == AMD_BR_8151);
95ae115bc7Smrj }
9631c83a1bSms148562
973deb7cedSms148562 /*
983deb7cedSms148562 * Check if it is an intel bridge
993deb7cedSms148562 */
1003deb7cedSms148562 static int
is_intel_br(agp_target_softstate_t * softstate)1013deb7cedSms148562 is_intel_br(agp_target_softstate_t *softstate)
1023deb7cedSms148562 {
1033deb7cedSms148562 return ((softstate->tsoft_devid & VENDOR_ID_MASK) ==
1043deb7cedSms148562 INTEL_VENDOR_ID);
1053deb7cedSms148562 }
106ae115bc7Smrj
107ae115bc7Smrj /*
108ae115bc7Smrj * agp_target_cap_find()
109ae115bc7Smrj *
110ae115bc7Smrj * Description:
111ae115bc7Smrj * This function searches the linked capability list to find the offset
112ae115bc7Smrj * of the AGP capability register. When it was not found, return 0.
113ae115bc7Smrj * This works for standard AGP chipsets, but not for some Intel chipsets,
114ae115bc7Smrj * like the I830M/I830MP/I852PM/I852GME/I855GME. It will return 0 for
115ae115bc7Smrj * these chipsets even if AGP is supported. So the offset of acapid
116ae115bc7Smrj * should be set manually in thoses cases.
117ae115bc7Smrj *
118ae115bc7Smrj * Arguments:
119ae115bc7Smrj * pci_handle ddi acc handle of pci config
120ae115bc7Smrj *
121ae115bc7Smrj * Returns:
122ae115bc7Smrj * 0 No capability pointer register found
123ae115bc7Smrj * nexcap The AGP capability pointer register offset
124ae115bc7Smrj */
125ae115bc7Smrj static off_t
agp_target_cap_find(ddi_acc_handle_t pci_handle)126ae115bc7Smrj agp_target_cap_find(ddi_acc_handle_t pci_handle)
127ae115bc7Smrj {
128ae115bc7Smrj off_t nextcap = 0;
129ae115bc7Smrj uint32_t ncapid = 0;
130ae115bc7Smrj uint8_t value = 0;
131ae115bc7Smrj
132ae115bc7Smrj /* Check if this device supports the capability pointer */
133ae115bc7Smrj value = (uint8_t)(pci_config_get16(pci_handle, PCI_CONF_STAT)
134ae115bc7Smrj & PCI_CONF_CAP_MASK);
135ae115bc7Smrj
136ae115bc7Smrj if (!value)
137ae115bc7Smrj return (0);
138ae115bc7Smrj /* Get the offset of the first capability pointer from CAPPTR */
139ae115bc7Smrj nextcap = (off_t)(pci_config_get8(pci_handle, AGP_CONF_CAPPTR));
140ae115bc7Smrj
141ae115bc7Smrj /* Check the AGP capability from the first capability pointer */
142ae115bc7Smrj while (nextcap) {
143ae115bc7Smrj ncapid = pci_config_get32(pci_handle, nextcap);
144ae115bc7Smrj /*
145ae115bc7Smrj * AGP3.0 rev1.0 127 the capid was assigned by the PCI SIG,
146ae115bc7Smrj * 845 data sheet page 69
147ae115bc7Smrj */
148ae115bc7Smrj if ((ncapid & PCI_CONF_CAPID_MASK) ==
149ae115bc7Smrj AGP_CAP_ID) /* The AGP cap was found */
150ae115bc7Smrj break;
151ae115bc7Smrj
152ae115bc7Smrj nextcap = (off_t)((ncapid & PCI_CONF_NCAPID_MASK) >> 8);
153ae115bc7Smrj }
154ae115bc7Smrj
155ae115bc7Smrj return (nextcap);
156ae115bc7Smrj
157ae115bc7Smrj }
158ae115bc7Smrj
159ae115bc7Smrj /*
160ae115bc7Smrj * agp_target_get_aperbase()
161ae115bc7Smrj *
162ae115bc7Smrj * Description:
163ae115bc7Smrj * This function gets the AGP aperture base address from the AGP target
164ae115bc7Smrj * register, the AGP aperture base register was programmed by the BIOS.
165ae115bc7Smrj *
166ae115bc7Smrj * Arguments:
167ae115bc7Smrj * softstate driver soft state pointer
168ae115bc7Smrj *
169ae115bc7Smrj * Returns:
170ae115bc7Smrj * aper_base AGP aperture base address
171ae115bc7Smrj *
172ae115bc7Smrj * Notes:
173ae115bc7Smrj * If a 64bit bridge device is available, the AGP aperture base address
174ae115bc7Smrj * can be 64 bit.
175ae115bc7Smrj */
176ae115bc7Smrj static uint64_t
agp_target_get_apbase(agp_target_softstate_t * softstate)177ae115bc7Smrj agp_target_get_apbase(agp_target_softstate_t *softstate)
178ae115bc7Smrj {
179ae115bc7Smrj uint64_t aper_base;
180ae115bc7Smrj
1813deb7cedSms148562 if (is_intel_br(softstate)) {
182ae115bc7Smrj aper_base = pci_config_get32(softstate->tsoft_pcihdl,
183ae115bc7Smrj AGP_CONF_APERBASE) & AGP_32_APERBASE_MASK;
1843deb7cedSms148562 } else if (is_64bit_aper(softstate)) {
185ae115bc7Smrj aper_base = pci_config_get64(softstate->tsoft_pcihdl,
186ae115bc7Smrj AGP_CONF_APERBASE);
187ae115bc7Smrj /* 32-bit or 64-bit aperbase base pointer */
188ae115bc7Smrj if ((aper_base & AGP_APER_TYPE_MASK) == 0)
189ae115bc7Smrj aper_base &= AGP_32_APERBASE_MASK;
190ae115bc7Smrj else
191ae115bc7Smrj aper_base &= AGP_64_APERBASE_MASK;
192ae115bc7Smrj }
1933deb7cedSms148562
194ae115bc7Smrj return (aper_base);
195ae115bc7Smrj }
196ae115bc7Smrj
197ae115bc7Smrj /*
198ae115bc7Smrj * agp_target_get_apsize()
199ae115bc7Smrj *
200ae115bc7Smrj * Description:
201ae115bc7Smrj * This function gets the AGP aperture size by reading the AGP aperture
202ae115bc7Smrj * size register.
203ae115bc7Smrj * Arguments:
204ae115bc7Smrj * softstate driver soft state pointer
205ae115bc7Smrj *
206ae115bc7Smrj * Return:
207ae115bc7Smrj * size The AGP aperture size in megabytes
208ae115bc7Smrj * 0 an unexpected error
209ae115bc7Smrj */
210ae115bc7Smrj static size_t
agp_target_get_apsize(agp_target_softstate_t * softstate)211ae115bc7Smrj agp_target_get_apsize(agp_target_softstate_t *softstate)
212ae115bc7Smrj {
213ae115bc7Smrj off_t cap;
214ae115bc7Smrj uint16_t value;
215ae115bc7Smrj size_t size, regsize;
216ae115bc7Smrj
217ae115bc7Smrj ASSERT(softstate->tsoft_acaptr);
218ae115bc7Smrj cap = softstate->tsoft_acaptr;
219ae115bc7Smrj
2203deb7cedSms148562 if (is_intel_br(softstate)) {
221ae115bc7Smrj /* extend this value to 16 bit for later tests */
222ae115bc7Smrj value = (uint16_t)pci_config_get8(softstate->tsoft_pcihdl,
223ae115bc7Smrj cap + AGP_CONF_APERSIZE) | AGP_APER_SIZE_MASK;
2243deb7cedSms148562 } else if (is_64bit_aper(softstate)) {
225ae115bc7Smrj value = pci_config_get16(softstate->tsoft_pcihdl,
226ae115bc7Smrj cap + AGP_CONF_APERSIZE);
227ae115bc7Smrj }
228ae115bc7Smrj
229ae115bc7Smrj if (value & AGP_APER_128M_MASK) {
230ae115bc7Smrj switch (value & AGP_APER_128M_MASK) {
231ae115bc7Smrj case AGP_APER_4M:
232ae115bc7Smrj size = 4; /* 4M */
233ae115bc7Smrj break;
234ae115bc7Smrj case AGP_APER_8M:
235ae115bc7Smrj size = 8; /* 8M */
236ae115bc7Smrj break;
237ae115bc7Smrj case AGP_APER_16M:
238ae115bc7Smrj size = 16; /* 16M */
239ae115bc7Smrj break;
240ae115bc7Smrj case AGP_APER_32M:
241ae115bc7Smrj size = 32; /* 32M */
242ae115bc7Smrj break;
243ae115bc7Smrj case AGP_APER_64M:
244ae115bc7Smrj size = 64; /* 64M */
245ae115bc7Smrj break;
246ae115bc7Smrj case AGP_APER_128M:
247ae115bc7Smrj size = 128; /* 128M */
248ae115bc7Smrj break;
249ae115bc7Smrj default:
250ae115bc7Smrj size = 0; /* not true */
251ae115bc7Smrj }
252ae115bc7Smrj } else {
253ae115bc7Smrj switch (value & AGP_APER_4G_MASK) {
254ae115bc7Smrj case AGP_APER_256M:
255ae115bc7Smrj size = 256; /* 256 M */
256ae115bc7Smrj break;
257ae115bc7Smrj case AGP_APER_512M:
258ae115bc7Smrj size = 512; /* 512 M */
259ae115bc7Smrj break;
260ae115bc7Smrj case AGP_APER_1024M:
261ae115bc7Smrj size = 1024; /* 1024 M */
262ae115bc7Smrj break;
263ae115bc7Smrj case AGP_APER_2048M:
264ae115bc7Smrj size = 2048; /* 2048 M */
265ae115bc7Smrj break;
266ae115bc7Smrj case AGP_APER_4G:
267ae115bc7Smrj size = 4096; /* 4096 M */
268ae115bc7Smrj break;
269ae115bc7Smrj default:
270ae115bc7Smrj size = 0; /* not true */
271ae115bc7Smrj }
272ae115bc7Smrj }
273ae115bc7Smrj /*
274ae115bc7Smrj * In some cases, there is no APSIZE register, so the size value
275ae115bc7Smrj * of 256M could be wrong. Check the value by reading the size of
276ae115bc7Smrj * the first register which was set in the PCI configuration space.
277ae115bc7Smrj */
278ae115bc7Smrj if (size == 256) {
279ae115bc7Smrj if (ddi_dev_regsize(softstate->tsoft_dip,
280ae115bc7Smrj AGP_TARGET_BAR1, (off_t *)®size) == DDI_FAILURE)
281ae115bc7Smrj return (0);
282ae115bc7Smrj
283ae115bc7Smrj if (MB2BYTES(size) != regsize) {
284ae115bc7Smrj TARGETDB_PRINT2((CE_WARN,
285ae115bc7Smrj "APSIZE 256M doesn't match regsize %lx",
286ae115bc7Smrj regsize));
287ae115bc7Smrj TARGETDB_PRINT2((CE_WARN, "Use regsize instead"));
288ae115bc7Smrj size = BYTES2MB(regsize);
289ae115bc7Smrj }
290ae115bc7Smrj }
291ae115bc7Smrj
292ae115bc7Smrj return (size);
293ae115bc7Smrj }
294ae115bc7Smrj
295ae115bc7Smrj static void
agp_target_set_gartaddr(agp_target_softstate_t * softstate,uint32_t gartaddr)296ae115bc7Smrj agp_target_set_gartaddr(agp_target_softstate_t *softstate, uint32_t gartaddr)
297ae115bc7Smrj {
298ae115bc7Smrj ASSERT(softstate->tsoft_acaptr);
299ae115bc7Smrj
300ae115bc7Smrj /* Disable the GTLB for Intel chipsets */
301ae115bc7Smrj pci_config_put16(softstate->tsoft_pcihdl,
302ae115bc7Smrj softstate->tsoft_acaptr + AGP_CONF_CONTROL, 0x0000);
303ae115bc7Smrj
304ae115bc7Smrj pci_config_put32(softstate->tsoft_pcihdl,
305ae115bc7Smrj softstate->tsoft_acaptr + AGP_CONF_ATTBASE,
306ae115bc7Smrj gartaddr & AGP_ATTBASE_MASK);
307ae115bc7Smrj }
308ae115bc7Smrj
309c4f91784Skz151634 /*
310c4f91784Skz151634 * Pre-allocated graphics memory for every type of Intel north bridge, mem size
311c4f91784Skz151634 * are specified in kbytes.
312c4f91784Skz151634 */
313c4f91784Skz151634 #define GMS_MB(n) ((n) * 1024)
314c4f91784Skz151634 #define GMS_SHIFT 4
315c4f91784Skz151634 #define GMS_SIZE(a) (sizeof (a) / sizeof (int))
316c4f91784Skz151634
317c4f91784Skz151634 /*
318c4f91784Skz151634 * Since value zero always means "No memory pre-allocated", value of (GMS - 1)
319c4f91784Skz151634 * is used to index these arrays, i.e. gms_xxx[1] contains the mem size (in kb)
320c4f91784Skz151634 * that GMS value 0x1 corresponding to.
321c4f91784Skz151634 *
322c4f91784Skz151634 * Assuming all "reserved" GMS value as zero bytes of pre-allocated graphics
323c4f91784Skz151634 * memory, unless some special BIOS settings exist.
324c4f91784Skz151634 */
325c4f91784Skz151634 static int gms_810[12] = {0, 0, 0, 0, 0, 0, 0, 512, 0, 0, 0, GMS_MB(1)};
326c4f91784Skz151634 static int gms_830_845[4] = {0, 512, GMS_MB(1), GMS_MB(8)};
327c4f91784Skz151634 static int gms_855GM[5] = {GMS_MB(1), GMS_MB(4), GMS_MB(8), GMS_MB(16),
328c4f91784Skz151634 GMS_MB(32)};
329c4f91784Skz151634 /* There is no modes for 16M in datasheet, but some BIOS add it. */
330c4f91784Skz151634 static int gms_865_915GM[4] = {GMS_MB(1), 0, GMS_MB(8), GMS_MB(16)};
331c4f91784Skz151634 static int gms_915_945_965[3] = {GMS_MB(1), 0, GMS_MB(8)};
332c4f91784Skz151634 static int gms_965GM[7] = {GMS_MB(1), GMS_MB(4), GMS_MB(8), GMS_MB(16),
333c4f91784Skz151634 GMS_MB(32), GMS_MB(48), GMS_MB(64)};
334c4f91784Skz151634 static int gms_X33[9] = {GMS_MB(1), GMS_MB(4), GMS_MB(8), GMS_MB(16),
335c4f91784Skz151634 GMS_MB(32), GMS_MB(48), GMS_MB(64), GMS_MB(128), GMS_MB(256)};
336fc6df3bdSmiao chen - Sun Microsystems - Beijing China static int gms_G4X[13] = {0, 0, 0, 0,
337fc6df3bdSmiao chen - Sun Microsystems - Beijing China GMS_MB(32), GMS_MB(48), GMS_MB(64), GMS_MB(128), GMS_MB(256),
338fc6df3bdSmiao chen - Sun Microsystems - Beijing China GMS_MB(96), GMS_MB(160), GMS_MB(224), GMS_MB(352)};
339c4f91784Skz151634
340c4f91784Skz151634 static gms_mode_t gms_modes[] = {
341c4f91784Skz151634 {INTEL_BR_810, I810_CONF_SMRAM, I810_GMS_MASK,
342c4f91784Skz151634 GMS_SIZE(gms_810), gms_810},
343c4f91784Skz151634 {INTEL_BR_810DC, I810_CONF_SMRAM, I810_GMS_MASK,
344c4f91784Skz151634 GMS_SIZE(gms_810), gms_810},
345c4f91784Skz151634 {INTEL_BR_810E, I810_CONF_SMRAM, I810_GMS_MASK,
346c4f91784Skz151634 GMS_SIZE(gms_810), gms_810},
347c4f91784Skz151634 {INTEL_BR_830M, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
348c4f91784Skz151634 GMS_SIZE(gms_830_845), gms_830_845},
349c4f91784Skz151634 {INTEL_BR_845, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
350c4f91784Skz151634 GMS_SIZE(gms_830_845), gms_830_845},
351c4f91784Skz151634 {INTEL_BR_855GM, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
352c4f91784Skz151634 GMS_SIZE(gms_855GM), gms_855GM},
353c4f91784Skz151634 {INTEL_BR_865, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
354c4f91784Skz151634 GMS_SIZE(gms_865_915GM), gms_865_915GM},
355c4f91784Skz151634 {INTEL_BR_915GM, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
356c4f91784Skz151634 GMS_SIZE(gms_865_915GM), gms_865_915GM},
357c4f91784Skz151634 {INTEL_BR_915, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
358c4f91784Skz151634 GMS_SIZE(gms_915_945_965), gms_915_945_965},
359c4f91784Skz151634 {INTEL_BR_945, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
360c4f91784Skz151634 GMS_SIZE(gms_915_945_965), gms_915_945_965},
361c4f91784Skz151634 {INTEL_BR_945GM, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
362c4f91784Skz151634 GMS_SIZE(gms_915_945_965), gms_915_945_965},
36312db04d3Smiao chen - Sun Microsystems - Beijing China {INTEL_BR_945GME, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
36412db04d3Smiao chen - Sun Microsystems - Beijing China GMS_SIZE(gms_915_945_965), gms_915_945_965},
365c4f91784Skz151634 {INTEL_BR_946GZ, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
366c4f91784Skz151634 GMS_SIZE(gms_915_945_965), gms_915_945_965},
367c4f91784Skz151634 {INTEL_BR_965G1, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
368c4f91784Skz151634 GMS_SIZE(gms_915_945_965), gms_915_945_965},
369c4f91784Skz151634 {INTEL_BR_965G2, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
370c4f91784Skz151634 GMS_SIZE(gms_915_945_965), gms_915_945_965},
371c4f91784Skz151634 {INTEL_BR_965Q, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
372c4f91784Skz151634 GMS_SIZE(gms_915_945_965), gms_915_945_965},
373c4f91784Skz151634 {INTEL_BR_965GM, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
374c4f91784Skz151634 GMS_SIZE(gms_965GM), gms_965GM},
375c4f91784Skz151634 {INTEL_BR_965GME, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
376c4f91784Skz151634 GMS_SIZE(gms_965GM), gms_965GM},
377c4f91784Skz151634 {INTEL_BR_Q35, I8XX_CONF_GC, IX33_GC_MODE_MASK,
378c4f91784Skz151634 GMS_SIZE(gms_X33), gms_X33},
379c4f91784Skz151634 {INTEL_BR_G33, I8XX_CONF_GC, IX33_GC_MODE_MASK,
380c4f91784Skz151634 GMS_SIZE(gms_X33), gms_X33},
381c4f91784Skz151634 {INTEL_BR_Q33, I8XX_CONF_GC, IX33_GC_MODE_MASK,
382219cee99Smc196098 GMS_SIZE(gms_X33), gms_X33},
383219cee99Smc196098 {INTEL_BR_GM45, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
384fc6df3bdSmiao chen - Sun Microsystems - Beijing China GMS_SIZE(gms_965GM), gms_965GM},
385fc6df3bdSmiao chen - Sun Microsystems - Beijing China {INTEL_BR_EL, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
386fc6df3bdSmiao chen - Sun Microsystems - Beijing China GMS_SIZE(gms_G4X), gms_G4X},
387fc6df3bdSmiao chen - Sun Microsystems - Beijing China {INTEL_BR_Q45, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
388fc6df3bdSmiao chen - Sun Microsystems - Beijing China GMS_SIZE(gms_G4X), gms_G4X},
389fc6df3bdSmiao chen - Sun Microsystems - Beijing China {INTEL_BR_G45, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
390d0231070Smiao chen - Sun Microsystems - Beijing China GMS_SIZE(gms_G4X), gms_G4X},
391d0231070Smiao chen - Sun Microsystems - Beijing China {INTEL_BR_G41, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
3920035d21cSmiao chen - Sun Microsystems - Beijing China GMS_SIZE(gms_G4X), gms_G4X},
3932e6e901dSmiao chen - Sun Microsystems - Beijing China {INTEL_BR_IGDNG_D, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
3942e6e901dSmiao chen - Sun Microsystems - Beijing China GMS_SIZE(gms_G4X), gms_G4X},
3952e6e901dSmiao chen - Sun Microsystems - Beijing China {INTEL_BR_IGDNG_M, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
3962e6e901dSmiao chen - Sun Microsystems - Beijing China GMS_SIZE(gms_G4X), gms_G4X},
3972e6e901dSmiao chen - Sun Microsystems - Beijing China {INTEL_BR_IGDNG_MA, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
3982e6e901dSmiao chen - Sun Microsystems - Beijing China GMS_SIZE(gms_G4X), gms_G4X},
3992e6e901dSmiao chen - Sun Microsystems - Beijing China {INTEL_BR_IGDNG_MC2, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
4002e6e901dSmiao chen - Sun Microsystems - Beijing China GMS_SIZE(gms_G4X), gms_G4X},
4010035d21cSmiao chen - Sun Microsystems - Beijing China {INTEL_BR_B43, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
402fc6df3bdSmiao chen - Sun Microsystems - Beijing China GMS_SIZE(gms_G4X), gms_G4X}
403c4f91784Skz151634 };
40431c83a1bSms148562 static int
get_chip_gms(uint32_t devid)40531c83a1bSms148562 get_chip_gms(uint32_t devid)
40631c83a1bSms148562 {
40731c83a1bSms148562 int num_modes;
40831c83a1bSms148562 int i;
40931c83a1bSms148562
41031c83a1bSms148562 num_modes = (sizeof (gms_modes) / sizeof (gms_mode_t));
41131c83a1bSms148562
41231c83a1bSms148562 for (i = 0; i < num_modes; i++) {
41331c83a1bSms148562 if (gms_modes[i].gm_devid == devid)
41431c83a1bSms148562 break;
41531c83a1bSms148562 }
41631c83a1bSms148562
41731c83a1bSms148562 return ((i == num_modes) ? -1 : i);
41831c83a1bSms148562 }
419c4f91784Skz151634
420c4f91784Skz151634 /* Returns the size (kbytes) of pre-allocated graphics memory */
421ae115bc7Smrj static size_t
i8xx_biosmem_detect(agp_target_softstate_t * softstate)422ae115bc7Smrj i8xx_biosmem_detect(agp_target_softstate_t *softstate)
423ae115bc7Smrj {
424ae115bc7Smrj uint8_t memval;
425ae115bc7Smrj size_t kbytes;
42631c83a1bSms148562 int gms_off;
427ae115bc7Smrj
428ae115bc7Smrj kbytes = 0;
42931c83a1bSms148562 gms_off = softstate->tsoft_gms_off;
43031c83a1bSms148562
431c4f91784Skz151634 /* fetch the GMS value from DRAM controller */
432c4f91784Skz151634 memval = pci_config_get8(softstate->tsoft_pcihdl,
43331c83a1bSms148562 gms_modes[gms_off].gm_regoff);
434c4f91784Skz151634 TARGETDB_PRINT2((CE_NOTE, "i8xx_biosmem_detect: memval = %x", memval));
43531c83a1bSms148562 memval = (memval & gms_modes[gms_off].gm_mask) >> GMS_SHIFT;
436c4f91784Skz151634 /* assuming zero byte for 0 or "reserved" GMS values */
43731c83a1bSms148562 if (memval == 0 || memval > gms_modes[gms_off].gm_num) {
438c4f91784Skz151634 TARGETDB_PRINT2((CE_WARN, "i8xx_biosmem_detect: "
439c4f91784Skz151634 "devid = %x, GMS = %x. assuming zero byte of "
44031c83a1bSms148562 "pre-allocated memory",
44131c83a1bSms148562 gms_modes[gms_off].gm_devid, memval));
442c4f91784Skz151634 goto done;
443c4f91784Skz151634 }
444c4f91784Skz151634 memval--; /* use (GMS_value - 1) as index */
44531c83a1bSms148562 kbytes = (gms_modes[gms_off].gm_vec)[memval];
446ae115bc7Smrj
447c4f91784Skz151634 done:
448543414e0Skz151634 TARGETDB_PRINT2((CE_NOTE,
449543414e0Skz151634 "i8xx_biosmem_detect: %ldKB BIOS pre-allocated memory detected",
450543414e0Skz151634 kbytes));
451ae115bc7Smrj return (kbytes);
452ae115bc7Smrj }
453ae115bc7Smrj
454ae115bc7Smrj /*ARGSUSED*/
agptarget_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** resultp)455ae115bc7Smrj static int agptarget_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd,
456ae115bc7Smrj void *arg, void **resultp)
457ae115bc7Smrj {
458ae115bc7Smrj agp_target_softstate_t *st;
459ae115bc7Smrj int instance, rval = DDI_FAILURE;
460ae115bc7Smrj dev_t dev;
461ae115bc7Smrj
462ae115bc7Smrj switch (cmd) {
463ae115bc7Smrj case DDI_INFO_DEVT2DEVINFO:
464ae115bc7Smrj dev = (dev_t)arg;
465ae115bc7Smrj instance = DEV2INST(dev);
466ae115bc7Smrj st = ddi_get_soft_state(agptarget_glob_soft_handle, instance);
467ae115bc7Smrj if (st != NULL) {
468ae115bc7Smrj mutex_enter(&st->tsoft_lock);
469ae115bc7Smrj *resultp = st->tsoft_dip;
470ae115bc7Smrj mutex_exit(&st->tsoft_lock);
471ae115bc7Smrj rval = DDI_SUCCESS;
472ae115bc7Smrj } else
473ae115bc7Smrj *resultp = NULL;
474ae115bc7Smrj
475ae115bc7Smrj break;
476ae115bc7Smrj case DDI_INFO_DEVT2INSTANCE:
477ae115bc7Smrj dev = (dev_t)arg;
478ae115bc7Smrj instance = DEV2INST(dev);
479ae115bc7Smrj *resultp = (void *)(uintptr_t)instance;
480ae115bc7Smrj rval = DDI_SUCCESS;
481ae115bc7Smrj default:
482ae115bc7Smrj break;
483ae115bc7Smrj }
484ae115bc7Smrj
485ae115bc7Smrj return (rval);
486ae115bc7Smrj }
487ae115bc7Smrj
488ae115bc7Smrj static int
intel_br_resume(agp_target_softstate_t * softstate)48931c83a1bSms148562 intel_br_resume(agp_target_softstate_t *softstate)
49031c83a1bSms148562 {
49131c83a1bSms148562 int gms_off;
49231c83a1bSms148562
49331c83a1bSms148562 gms_off = softstate->tsoft_gms_off;
49431c83a1bSms148562
49531c83a1bSms148562 /*
49631c83a1bSms148562 * We recover the gmch graphics control register here
49731c83a1bSms148562 */
49831c83a1bSms148562 pci_config_put16(softstate->tsoft_pcihdl,
49931c83a1bSms148562 gms_modes[gms_off].gm_regoff, softstate->tsoft_gms);
50031c83a1bSms148562
50131c83a1bSms148562 return (DDI_SUCCESS);
50231c83a1bSms148562 }
50331c83a1bSms148562 static int
intel_br_suspend(agp_target_softstate_t * softstate)50431c83a1bSms148562 intel_br_suspend(agp_target_softstate_t *softstate)
50531c83a1bSms148562 {
50631c83a1bSms148562 int gms_off;
50731c83a1bSms148562
50831c83a1bSms148562 gms_off = softstate->tsoft_gms_off;
50931c83a1bSms148562 softstate->tsoft_gms = pci_config_get16(softstate->tsoft_pcihdl,
51031c83a1bSms148562 gms_modes[gms_off].gm_regoff);
51131c83a1bSms148562
51231c83a1bSms148562 return (DDI_SUCCESS);
51331c83a1bSms148562 }
51431c83a1bSms148562
51531c83a1bSms148562 static int
agp_target_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)516ae115bc7Smrj agp_target_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
517ae115bc7Smrj {
518ae115bc7Smrj agp_target_softstate_t *softstate;
519ae115bc7Smrj int instance;
520ae115bc7Smrj int status;
521ae115bc7Smrj
522ae115bc7Smrj instance = ddi_get_instance(dip);
523ae115bc7Smrj
52431c83a1bSms148562 switch (cmd) {
52531c83a1bSms148562 case DDI_ATTACH:
52631c83a1bSms148562 break;
52731c83a1bSms148562 case DDI_RESUME:
52831c83a1bSms148562 softstate =
52931c83a1bSms148562 ddi_get_soft_state(agptarget_glob_soft_handle, instance);
53031c83a1bSms148562 return (intel_br_resume(softstate));
53131c83a1bSms148562 default:
53231c83a1bSms148562 TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
53331c83a1bSms148562 "only attach and resume ops are supported"));
534ae115bc7Smrj return (DDI_FAILURE);
53531c83a1bSms148562 }
53631c83a1bSms148562
53731c83a1bSms148562 if (ddi_soft_state_zalloc(agptarget_glob_soft_handle,
53831c83a1bSms148562 instance) != DDI_SUCCESS) {
53931c83a1bSms148562 TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
54031c83a1bSms148562 "soft state zalloc failed"));
54131c83a1bSms148562 return (DDI_FAILURE);
54231c83a1bSms148562 }
543ae115bc7Smrj
544ae115bc7Smrj softstate = ddi_get_soft_state(agptarget_glob_soft_handle, instance);
545ae115bc7Smrj mutex_init(&softstate->tsoft_lock, NULL, MUTEX_DRIVER, NULL);
546ae115bc7Smrj softstate->tsoft_dip = dip;
547ae115bc7Smrj status = pci_config_setup(dip, &softstate->tsoft_pcihdl);
548ae115bc7Smrj if (status != DDI_SUCCESS) {
54931c83a1bSms148562 TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
55031c83a1bSms148562 "pci config setup failed"));
55131c83a1bSms148562 ddi_soft_state_free(agptarget_glob_soft_handle,
55231c83a1bSms148562 instance);
553ae115bc7Smrj return (DDI_FAILURE);
554ae115bc7Smrj }
555ae115bc7Smrj
556ae115bc7Smrj softstate->tsoft_devid = pci_config_get32(softstate->tsoft_pcihdl,
557ae115bc7Smrj PCI_CONF_VENID);
55831c83a1bSms148562 softstate->tsoft_gms_off = get_chip_gms(softstate->tsoft_devid);
55931c83a1bSms148562 if (softstate->tsoft_gms_off < 0) {
56031c83a1bSms148562 TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
56131c83a1bSms148562 "read gms offset failed"));
56231c83a1bSms148562 pci_config_teardown(&softstate->tsoft_pcihdl);
56331c83a1bSms148562 ddi_soft_state_free(agptarget_glob_soft_handle,
56431c83a1bSms148562 instance);
56531c83a1bSms148562 return (DDI_FAILURE);
56631c83a1bSms148562 }
567ae115bc7Smrj softstate->tsoft_acaptr = agp_target_cap_find(softstate->tsoft_pcihdl);
568ae115bc7Smrj if (softstate->tsoft_acaptr == 0) {
569ae115bc7Smrj /* Make a correction for some Intel chipsets */
5703deb7cedSms148562 if (is_intel_br(softstate))
571ae115bc7Smrj softstate->tsoft_acaptr = AGP_CAP_OFF_DEF;
57231c83a1bSms148562 else {
57331c83a1bSms148562 TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
57431c83a1bSms148562 "Not a supposed corretion"));
57531c83a1bSms148562 pci_config_teardown(&softstate->tsoft_pcihdl);
57631c83a1bSms148562 ddi_soft_state_free(agptarget_glob_soft_handle,
57731c83a1bSms148562 instance);
578ae115bc7Smrj return (DDI_FAILURE);
579ae115bc7Smrj }
58031c83a1bSms148562 }
581ae115bc7Smrj
582ae115bc7Smrj status = ddi_create_minor_node(dip, AGPTARGET_NAME, S_IFCHR,
583ae115bc7Smrj INST2NODENUM(instance), DDI_NT_AGP_TARGET, 0);
584ae115bc7Smrj
585ae115bc7Smrj if (status != DDI_SUCCESS) {
58631c83a1bSms148562 TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
58731c83a1bSms148562 "Create minor node failed"));
588ae115bc7Smrj pci_config_teardown(&softstate->tsoft_pcihdl);
589ae115bc7Smrj ddi_soft_state_free(agptarget_glob_soft_handle, instance);
590ae115bc7Smrj return (DDI_FAILURE);
591ae115bc7Smrj }
592ae115bc7Smrj
593ae115bc7Smrj return (DDI_SUCCESS);
594ae115bc7Smrj }
595ae115bc7Smrj
596ae115bc7Smrj /*ARGSUSED*/
597ae115bc7Smrj static int
agp_target_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)598ae115bc7Smrj agp_target_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
599ae115bc7Smrj {
600ae115bc7Smrj int instance;
601ae115bc7Smrj agp_target_softstate_t *softstate;
602ae115bc7Smrj
603ae115bc7Smrj instance = ddi_get_instance(dip);
604ae115bc7Smrj softstate = ddi_get_soft_state(agptarget_glob_soft_handle, instance);
605ae115bc7Smrj
60631c83a1bSms148562 if (cmd == DDI_SUSPEND) {
60731c83a1bSms148562 /* get GMS modes list entry */
60831c83a1bSms148562 return (intel_br_suspend(softstate));
60931c83a1bSms148562 }
61031c83a1bSms148562
61131c83a1bSms148562 if (cmd != DDI_DETACH) {
61231c83a1bSms148562 TARGETDB_PRINT2((CE_WARN, "agp_target_detach:"
61331c83a1bSms148562 "only detach and suspend ops are supported"));
61431c83a1bSms148562 return (DDI_FAILURE);
61531c83a1bSms148562 }
61631c83a1bSms148562
617ae115bc7Smrj ddi_remove_minor_node(dip, AGPTARGET_NAME);
618ae115bc7Smrj pci_config_teardown(&softstate->tsoft_pcihdl);
619ae115bc7Smrj mutex_destroy(&softstate->tsoft_lock);
620ae115bc7Smrj ddi_soft_state_free(agptarget_glob_soft_handle, instance);
621ae115bc7Smrj return (DDI_SUCCESS);
622ae115bc7Smrj }
623ae115bc7Smrj
624ae115bc7Smrj /*ARGSUSED*/
625ae115bc7Smrj static int
agp_target_ioctl(dev_t dev,int cmd,intptr_t data,int mode,cred_t * cred,int * rval)626ae115bc7Smrj agp_target_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
627ae115bc7Smrj cred_t *cred, int *rval)
628ae115bc7Smrj {
629ae115bc7Smrj int instance = DEV2INST(dev);
630ae115bc7Smrj agp_target_softstate_t *st;
631ae115bc7Smrj static char kernel_only[] =
632ae115bc7Smrj "amd64_gart_ioctl: is a kernel only ioctl";
633ae115bc7Smrj
634ae115bc7Smrj if (!(mode & FKIOCTL)) {
635ae115bc7Smrj TARGETDB_PRINT2((CE_CONT, kernel_only));
636ae115bc7Smrj return (ENXIO);
637ae115bc7Smrj }
638ae115bc7Smrj st = GETSOFTC(instance);
639ae115bc7Smrj
640ae115bc7Smrj if (st == NULL)
641ae115bc7Smrj return (ENXIO);
642ae115bc7Smrj
643ae115bc7Smrj mutex_enter(&st->tsoft_lock);
644ae115bc7Smrj
645ae115bc7Smrj switch (cmd) {
646ae115bc7Smrj case CHIP_DETECT:
647ae115bc7Smrj {
6483deb7cedSms148562 int type = 0;
6493deb7cedSms148562
6503deb7cedSms148562 if (is_intel_br(st))
651ae115bc7Smrj type = CHIP_IS_INTEL;
6523deb7cedSms148562 else if (is_64bit_aper(st))
653ae115bc7Smrj type = CHIP_IS_AMD;
6543deb7cedSms148562 else {
655ae115bc7Smrj type = 0;
6563deb7cedSms148562 TARGETDB_PRINT2((CE_WARN, "Unknown bridge!"));
657ae115bc7Smrj }
6583deb7cedSms148562
659ae115bc7Smrj if (ddi_copyout(&type, (void *)data, sizeof (int), mode)) {
660ae115bc7Smrj mutex_exit(&st->tsoft_lock);
661ae115bc7Smrj return (EFAULT);
662ae115bc7Smrj }
663ae115bc7Smrj
664ae115bc7Smrj break;
665ae115bc7Smrj }
666ae115bc7Smrj case I8XX_GET_PREALLOC_SIZE:
667ae115bc7Smrj {
668ae115bc7Smrj size_t prealloc_size;
669ae115bc7Smrj
6703deb7cedSms148562 if (!is_intel_br(st)) {
671ae115bc7Smrj mutex_exit(&st->tsoft_lock);
672ae115bc7Smrj return (EINVAL);
673ae115bc7Smrj }
674ae115bc7Smrj
675ae115bc7Smrj prealloc_size = i8xx_biosmem_detect(st);
676ae115bc7Smrj if (ddi_copyout(&prealloc_size, (void *)data,
677ae115bc7Smrj sizeof (size_t), mode)) {
678ae115bc7Smrj mutex_exit(&st->tsoft_lock);
679ae115bc7Smrj return (EFAULT);
680ae115bc7Smrj }
681ae115bc7Smrj
682ae115bc7Smrj break;
683ae115bc7Smrj }
684ae115bc7Smrj case AGP_TARGET_GETINFO:
685ae115bc7Smrj {
686ae115bc7Smrj i_agp_info_t info;
687ae115bc7Smrj uint32_t value;
688ae115bc7Smrj off_t cap;
689ae115bc7Smrj
690ae115bc7Smrj ASSERT(st->tsoft_acaptr);
691ae115bc7Smrj
692ae115bc7Smrj cap = st->tsoft_acaptr;
693ae115bc7Smrj value = pci_config_get32(st->tsoft_pcihdl, cap);
694ae115bc7Smrj info.iagp_ver.agpv_major = (uint16_t)((value >> 20) & 0xf);
695ae115bc7Smrj info.iagp_ver.agpv_minor = (uint16_t)((value >> 16) & 0xf);
696ae115bc7Smrj info.iagp_devid = st->tsoft_devid;
697ae115bc7Smrj info.iagp_mode = pci_config_get32(st->tsoft_pcihdl,
698ae115bc7Smrj cap + AGP_CONF_STATUS);
699ae115bc7Smrj info.iagp_aperbase = agp_target_get_apbase(st);
700ae115bc7Smrj info.iagp_apersize = agp_target_get_apsize(st);
701ae115bc7Smrj
702ae115bc7Smrj if (ddi_copyout(&info, (void *)data,
703ae115bc7Smrj sizeof (i_agp_info_t), mode)) {
704ae115bc7Smrj mutex_exit(&st->tsoft_lock);
705ae115bc7Smrj return (EFAULT);
706ae115bc7Smrj }
707ae115bc7Smrj break;
708ae115bc7Smrj
709ae115bc7Smrj }
710ae115bc7Smrj /*
711ae115bc7Smrj * This ioctl is only for Intel AGP chipsets.
712ae115bc7Smrj * It is not necessary for the AMD8151 AGP bridge, because
713ae115bc7Smrj * this register in the AMD8151 does not control any hardware.
714ae115bc7Smrj * It is only provided for compatibility with an Intel AGP bridge.
715ae115bc7Smrj * Please refer to the <<AMD8151 data sheet>> page 24,
716ae115bc7Smrj * AGP device GART pointer.
717ae115bc7Smrj */
718ae115bc7Smrj case AGP_TARGET_SET_GATTADDR:
719ae115bc7Smrj {
720ae115bc7Smrj uint32_t gartaddr;
721ae115bc7Smrj
722ae115bc7Smrj if (ddi_copyin((void *)data, &gartaddr,
723ae115bc7Smrj sizeof (uint32_t), mode)) {
724ae115bc7Smrj mutex_exit(&st->tsoft_lock);
725ae115bc7Smrj return (EFAULT);
726ae115bc7Smrj }
727ae115bc7Smrj
728ae115bc7Smrj agp_target_set_gartaddr(st, gartaddr);
729ae115bc7Smrj break;
730ae115bc7Smrj }
731ae115bc7Smrj case AGP_TARGET_SETCMD:
732ae115bc7Smrj {
733ae115bc7Smrj uint32_t command;
734ae115bc7Smrj
735ae115bc7Smrj if (ddi_copyin((void *)data, &command,
736ae115bc7Smrj sizeof (uint32_t), mode)) {
737ae115bc7Smrj mutex_exit(&st->tsoft_lock);
738ae115bc7Smrj return (EFAULT);
739ae115bc7Smrj }
740ae115bc7Smrj
741ae115bc7Smrj ASSERT(st->tsoft_acaptr);
742ae115bc7Smrj
743ae115bc7Smrj pci_config_put32(st->tsoft_pcihdl,
744ae115bc7Smrj st->tsoft_acaptr + AGP_CONF_COMMAND,
745ae115bc7Smrj command);
746ae115bc7Smrj break;
747ae115bc7Smrj
748ae115bc7Smrj }
749ae115bc7Smrj case AGP_TARGET_FLUSH_GTLB:
750ae115bc7Smrj {
751ae115bc7Smrj uint16_t value;
752ae115bc7Smrj
753ae115bc7Smrj ASSERT(st->tsoft_acaptr);
754ae115bc7Smrj
755ae115bc7Smrj value = pci_config_get16(st->tsoft_pcihdl,
756ae115bc7Smrj st->tsoft_acaptr + AGP_CONF_CONTROL);
757ae115bc7Smrj value &= ~AGPCTRL_GTLBEN;
758ae115bc7Smrj pci_config_put16(st->tsoft_pcihdl,
759ae115bc7Smrj st->tsoft_acaptr + AGP_CONF_CONTROL, value);
760ae115bc7Smrj value |= AGPCTRL_GTLBEN;
761ae115bc7Smrj pci_config_put16(st->tsoft_pcihdl,
762ae115bc7Smrj st->tsoft_acaptr + AGP_CONF_CONTROL, value);
763ae115bc7Smrj
764ae115bc7Smrj break;
765ae115bc7Smrj }
766ae115bc7Smrj case AGP_TARGET_CONFIGURE:
767ae115bc7Smrj {
768ae115bc7Smrj uint8_t value;
769ae115bc7Smrj
770ae115bc7Smrj ASSERT(st->tsoft_acaptr);
771ae115bc7Smrj
7723deb7cedSms148562 /*
7733deb7cedSms148562 * In Intel agp bridges, agp misc register offset
7743deb7cedSms148562 * is indexed from 0 instead of capability register.
7753deb7cedSms148562 * AMD agp bridges have no such misc register
7763deb7cedSms148562 * to control the aperture access, and they have
7773deb7cedSms148562 * similar regsiters in CPU gart devices instead.
7783deb7cedSms148562 */
7793deb7cedSms148562
7803deb7cedSms148562 if (is_intel_br(st)) {
781ae115bc7Smrj value = pci_config_get8(st->tsoft_pcihdl,
782ae115bc7Smrj st->tsoft_acaptr + AGP_CONF_MISC);
783ae115bc7Smrj value |= AGP_MISC_APEN;
784ae115bc7Smrj pci_config_put8(st->tsoft_pcihdl,
785ae115bc7Smrj st->tsoft_acaptr + AGP_CONF_MISC, value);
7863deb7cedSms148562 }
787ae115bc7Smrj break;
788ae115bc7Smrj
789ae115bc7Smrj }
790ae115bc7Smrj case AGP_TARGET_UNCONFIG:
791ae115bc7Smrj {
792ae115bc7Smrj uint32_t value1;
793ae115bc7Smrj uint8_t value2;
794ae115bc7Smrj
795ae115bc7Smrj ASSERT(st->tsoft_acaptr);
796ae115bc7Smrj
797ae115bc7Smrj pci_config_put16(st->tsoft_pcihdl,
798ae115bc7Smrj st->tsoft_acaptr + AGP_CONF_CONTROL, 0x0);
799ae115bc7Smrj
8003deb7cedSms148562 if (is_intel_br(st)) {
801ae115bc7Smrj value2 = pci_config_get8(st->tsoft_pcihdl,
802ae115bc7Smrj st->tsoft_acaptr + AGP_CONF_MISC);
803ae115bc7Smrj value2 &= ~AGP_MISC_APEN;
804ae115bc7Smrj pci_config_put8(st->tsoft_pcihdl,
805ae115bc7Smrj st->tsoft_acaptr + AGP_CONF_MISC, value2);
8063deb7cedSms148562 }
807ae115bc7Smrj
808ae115bc7Smrj value1 = pci_config_get32(st->tsoft_pcihdl,
809ae115bc7Smrj st->tsoft_acaptr + AGP_CONF_COMMAND);
810ae115bc7Smrj value1 &= ~AGPCMD_AGPEN;
811ae115bc7Smrj pci_config_put32(st->tsoft_pcihdl,
812ae115bc7Smrj st->tsoft_acaptr + AGP_CONF_COMMAND,
813ae115bc7Smrj value1);
814ae115bc7Smrj
815ae115bc7Smrj pci_config_put32(st->tsoft_pcihdl,
816ae115bc7Smrj st->tsoft_acaptr + AGP_CONF_ATTBASE, 0x0);
817ae115bc7Smrj
818ae115bc7Smrj break;
819ae115bc7Smrj }
820ae115bc7Smrj
8210035d21cSmiao chen - Sun Microsystems - Beijing China case INTEL_CHIPSET_FLUSH_SETUP:
8220035d21cSmiao chen - Sun Microsystems - Beijing China case INTEL_CHIPSET_FLUSH:
8230035d21cSmiao chen - Sun Microsystems - Beijing China case INTEL_CHIPSET_FLUSH_FREE:
8240035d21cSmiao chen - Sun Microsystems - Beijing China break;
825ae115bc7Smrj default:
826ae115bc7Smrj mutex_exit(&st->tsoft_lock);
827ae115bc7Smrj return (ENXIO);
828ae115bc7Smrj } /* end switch */
829ae115bc7Smrj
830ae115bc7Smrj mutex_exit(&st->tsoft_lock);
831ae115bc7Smrj
832ae115bc7Smrj return (0);
833ae115bc7Smrj }
834ae115bc7Smrj
835ae115bc7Smrj /*ARGSUSED*/
836ae115bc7Smrj static int
agp_target_open(dev_t * devp,int flag,int otyp,cred_t * cred)837ae115bc7Smrj agp_target_open(dev_t *devp, int flag, int otyp, cred_t *cred)
838ae115bc7Smrj {
839ae115bc7Smrj int instance = DEV2INST(*devp);
840ae115bc7Smrj agp_target_softstate_t *st;
841ae115bc7Smrj
842ae115bc7Smrj if (!(flag & FKLYR))
843ae115bc7Smrj return (ENXIO);
844ae115bc7Smrj
845ae115bc7Smrj st = GETSOFTC(instance);
846ae115bc7Smrj
847ae115bc7Smrj if (st == NULL)
848ae115bc7Smrj return (ENXIO);
849ae115bc7Smrj
850ae115bc7Smrj return (0);
851ae115bc7Smrj }
852ae115bc7Smrj
853ae115bc7Smrj /*ARGSUSED*/
854ae115bc7Smrj static int
agp_target_close(dev_t dev,int flag,int otyp,cred_t * cred)855ae115bc7Smrj agp_target_close(dev_t dev, int flag, int otyp, cred_t *cred)
856ae115bc7Smrj {
857ae115bc7Smrj int instance = DEV2INST(dev);
858ae115bc7Smrj agp_target_softstate_t *st;
859ae115bc7Smrj
860ae115bc7Smrj st = GETSOFTC(instance);
861ae115bc7Smrj
862ae115bc7Smrj if (st == NULL)
863ae115bc7Smrj return (ENXIO);
864ae115bc7Smrj
865ae115bc7Smrj return (0);
866ae115bc7Smrj }
867ae115bc7Smrj
868ae115bc7Smrj static struct cb_ops agp_target_cb_ops = {
869ae115bc7Smrj agp_target_open, /* cb_open */
870ae115bc7Smrj agp_target_close, /* cb_close */
871ae115bc7Smrj nodev, /* cb_strategy */
872ae115bc7Smrj nodev, /* cb_print */
873ae115bc7Smrj nodev, /* cb_dump */
874ae115bc7Smrj nodev, /* cb_read() */
875ae115bc7Smrj nodev, /* cb_write() */
876ae115bc7Smrj agp_target_ioctl, /* cb_ioctl */
877ae115bc7Smrj nodev, /* cb_devmap */
878ae115bc7Smrj nodev, /* cb_mmap */
879ae115bc7Smrj nodev, /* cb_segmap */
880ae115bc7Smrj nochpoll, /* cb_chpoll */
881ae115bc7Smrj ddi_prop_op, /* cb_prop_op */
882ae115bc7Smrj 0, /* cb_stream */
883ae115bc7Smrj D_NEW | D_MP, /* cb_flag */
884ae115bc7Smrj CB_REV, /* cb_ops version? */
885ae115bc7Smrj nodev, /* cb_aread() */
886ae115bc7Smrj nodev, /* cb_awrite() */
887ae115bc7Smrj };
888ae115bc7Smrj
889ae115bc7Smrj /* device operations */
890ae115bc7Smrj static struct dev_ops agp_target_ops = {
891ae115bc7Smrj DEVO_REV, /* devo_rev */
892ae115bc7Smrj 0, /* devo_refcnt */
893ae115bc7Smrj agptarget_getinfo, /* devo_getinfo */
894ae115bc7Smrj nulldev, /* devo_identify */
895ae115bc7Smrj nulldev, /* devo_probe */
896ae115bc7Smrj agp_target_attach, /* devo_attach */
897ae115bc7Smrj agp_target_detach, /* devo_detach */
898ae115bc7Smrj nodev, /* devo_reset */
899ae115bc7Smrj &agp_target_cb_ops, /* devo_cb_ops */
900ae115bc7Smrj 0, /* devo_bus_ops */
901ae115bc7Smrj 0, /* devo_power */
902dc5ffc8eSmiao chen - Sun Microsystems - Beijing China ddi_quiesce_not_needed, /* devo_quiesce */
903ae115bc7Smrj };
904ae115bc7Smrj
905ae115bc7Smrj static struct modldrv modldrv = {
906ae115bc7Smrj &mod_driverops,
90731c83a1bSms148562 "AGP target driver",
908ae115bc7Smrj &agp_target_ops,
909ae115bc7Smrj };
910ae115bc7Smrj
911ae115bc7Smrj static struct modlinkage modlinkage = {
912ae115bc7Smrj MODREV_1, /* MODREV_1 is indicated by manual */
913ae115bc7Smrj {&modldrv, NULL, NULL, NULL}
914ae115bc7Smrj };
915ae115bc7Smrj
916ae115bc7Smrj int
_init(void)917ae115bc7Smrj _init(void)
918ae115bc7Smrj {
919ae115bc7Smrj int ret;
920ae115bc7Smrj
921ae115bc7Smrj ret = ddi_soft_state_init(&agptarget_glob_soft_handle,
922ae115bc7Smrj sizeof (agp_target_softstate_t), 1);
923ae115bc7Smrj
924ae115bc7Smrj if (ret)
925ae115bc7Smrj goto err1;
926ae115bc7Smrj
927ae115bc7Smrj if ((ret = mod_install(&modlinkage)) != 0) {
928ae115bc7Smrj goto err2;
929ae115bc7Smrj }
930ae115bc7Smrj
931ae115bc7Smrj return (DDI_SUCCESS);
932ae115bc7Smrj err2:
933ae115bc7Smrj ddi_soft_state_fini(&agptarget_glob_soft_handle);
934ae115bc7Smrj err1:
935ae115bc7Smrj return (ret);
936ae115bc7Smrj }
937ae115bc7Smrj
938ae115bc7Smrj int
_info(struct modinfo * modinfop)939ae115bc7Smrj _info(struct modinfo *modinfop)
940ae115bc7Smrj {
941ae115bc7Smrj return (mod_info(&modlinkage, modinfop));
942ae115bc7Smrj }
943ae115bc7Smrj
944ae115bc7Smrj int
_fini(void)945ae115bc7Smrj _fini(void)
946ae115bc7Smrj {
947ae115bc7Smrj int ret;
948ae115bc7Smrj
949ae115bc7Smrj if ((ret = mod_remove(&modlinkage)) == 0) {
950ae115bc7Smrj ddi_soft_state_fini(&agptarget_glob_soft_handle);
951ae115bc7Smrj }
952ae115bc7Smrj return (ret);
953ae115bc7Smrj }
954