agp_i810.c revision 274378
1/*-
2 * Copyright (c) 2000 Doug Rabson
3 * Copyright (c) 2000 Ruslan Ermilov
4 * Copyright (c) 2011 The FreeBSD Foundation
5 * All rights reserved.
6 *
7 * Portions of this software were developed by Konstantin Belousov
8 * under sponsorship from the FreeBSD Foundation.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * Fixes for 830/845G support: David Dawes <dawes@xfree86.org>
34 * 852GM/855GM/865G support added by David Dawes <dawes@xfree86.org>
35 *
36 * This is generic Intel GTT handling code, morphed from the AGP
37 * bridge code.
38 */
39
40#include <sys/cdefs.h>
41__FBSDID("$FreeBSD: head/sys/dev/agp/agp_i810.c 274378 2014-11-11 12:52:45Z kib $");
42
43#if 0
44#define	KTR_AGP_I810	KTR_DEV
45#else
46#define	KTR_AGP_I810	0
47#endif
48
49#include <sys/param.h>
50#include <sys/systm.h>
51#include <sys/malloc.h>
52#include <sys/kernel.h>
53#include <sys/ktr.h>
54#include <sys/module.h>
55#include <sys/bus.h>
56#include <sys/lock.h>
57#include <sys/mutex.h>
58#include <sys/proc.h>
59#include <sys/rwlock.h>
60
61#include <dev/agp/agppriv.h>
62#include <dev/agp/agpreg.h>
63#include <dev/agp/agp_i810.h>
64#include <dev/pci/pcivar.h>
65#include <dev/pci/pcireg.h>
66#include <dev/pci/pci_private.h>
67
68#include <vm/vm.h>
69#include <vm/vm_extern.h>
70#include <vm/vm_kern.h>
71#include <vm/vm_param.h>
72#include <vm/vm_object.h>
73#include <vm/vm_page.h>
74#include <vm/vm_pageout.h>
75#include <vm/pmap.h>
76
77#include <machine/bus.h>
78#include <machine/resource.h>
79#include <machine/md_var.h>
80#include <sys/rman.h>
81
82MALLOC_DECLARE(M_AGP);
83
84struct agp_i810_match;
85
86static int agp_i810_check_active(device_t bridge_dev);
87static int agp_i830_check_active(device_t bridge_dev);
88static int agp_i915_check_active(device_t bridge_dev);
89static int agp_sb_check_active(device_t bridge_dev);
90
91static void agp_82852_set_desc(device_t dev,
92    const struct agp_i810_match *match);
93static void agp_i810_set_desc(device_t dev, const struct agp_i810_match *match);
94
95static void agp_i810_dump_regs(device_t dev);
96static void agp_i830_dump_regs(device_t dev);
97static void agp_i855_dump_regs(device_t dev);
98static void agp_i915_dump_regs(device_t dev);
99static void agp_i965_dump_regs(device_t dev);
100static void agp_sb_dump_regs(device_t dev);
101
102static int agp_i810_get_stolen_size(device_t dev);
103static int agp_i830_get_stolen_size(device_t dev);
104static int agp_i915_get_stolen_size(device_t dev);
105static int agp_sb_get_stolen_size(device_t dev);
106
107static int agp_i810_get_gtt_mappable_entries(device_t dev);
108static int agp_i830_get_gtt_mappable_entries(device_t dev);
109static int agp_i915_get_gtt_mappable_entries(device_t dev);
110
111static int agp_i810_get_gtt_total_entries(device_t dev);
112static int agp_i965_get_gtt_total_entries(device_t dev);
113static int agp_gen5_get_gtt_total_entries(device_t dev);
114static int agp_sb_get_gtt_total_entries(device_t dev);
115
116static int agp_i810_install_gatt(device_t dev);
117static int agp_i830_install_gatt(device_t dev);
118static int agp_i965_install_gatt(device_t dev);
119static int agp_g4x_install_gatt(device_t dev);
120
121static void agp_i810_deinstall_gatt(device_t dev);
122static void agp_i830_deinstall_gatt(device_t dev);
123
124static void agp_i810_install_gtt_pte(device_t dev, u_int index,
125    vm_offset_t physical, int flags);
126static void agp_i830_install_gtt_pte(device_t dev, u_int index,
127    vm_offset_t physical, int flags);
128static void agp_i915_install_gtt_pte(device_t dev, u_int index,
129    vm_offset_t physical, int flags);
130static void agp_i965_install_gtt_pte(device_t dev, u_int index,
131    vm_offset_t physical, int flags);
132static void agp_g4x_install_gtt_pte(device_t dev, u_int index,
133    vm_offset_t physical, int flags);
134static void agp_sb_install_gtt_pte(device_t dev, u_int index,
135    vm_offset_t physical, int flags);
136
137static void agp_i810_write_gtt(device_t dev, u_int index, uint32_t pte);
138static void agp_i915_write_gtt(device_t dev, u_int index, uint32_t pte);
139static void agp_i965_write_gtt(device_t dev, u_int index, uint32_t pte);
140static void agp_g4x_write_gtt(device_t dev, u_int index, uint32_t pte);
141static void agp_sb_write_gtt(device_t dev, u_int index, uint32_t pte);
142
143static u_int32_t agp_i810_read_gtt_pte(device_t dev, u_int index);
144static u_int32_t agp_i915_read_gtt_pte(device_t dev, u_int index);
145static u_int32_t agp_i965_read_gtt_pte(device_t dev, u_int index);
146static u_int32_t agp_g4x_read_gtt_pte(device_t dev, u_int index);
147
148static vm_paddr_t agp_i810_read_gtt_pte_paddr(device_t dev, u_int index);
149static vm_paddr_t agp_i915_read_gtt_pte_paddr(device_t dev, u_int index);
150static vm_paddr_t agp_sb_read_gtt_pte_paddr(device_t dev, u_int index);
151
152static int agp_i810_set_aperture(device_t dev, u_int32_t aperture);
153static int agp_i830_set_aperture(device_t dev, u_int32_t aperture);
154static int agp_i915_set_aperture(device_t dev, u_int32_t aperture);
155
156static int agp_i810_chipset_flush_setup(device_t dev);
157static int agp_i915_chipset_flush_setup(device_t dev);
158static int agp_i965_chipset_flush_setup(device_t dev);
159
160static void agp_i810_chipset_flush_teardown(device_t dev);
161static void agp_i915_chipset_flush_teardown(device_t dev);
162static void agp_i965_chipset_flush_teardown(device_t dev);
163
164static void agp_i810_chipset_flush(device_t dev);
165static void agp_i830_chipset_flush(device_t dev);
166static void agp_i915_chipset_flush(device_t dev);
167
168enum {
169	CHIP_I810,	/* i810/i815 */
170	CHIP_I830,	/* 830M/845G */
171	CHIP_I855,	/* 852GM/855GM/865G */
172	CHIP_I915,	/* 915G/915GM */
173	CHIP_I965,	/* G965 */
174	CHIP_G33,	/* G33/Q33/Q35 */
175	CHIP_IGD,	/* Pineview */
176	CHIP_G4X,	/* G45/Q45 */
177	CHIP_SB,	/* SandyBridge */
178};
179
180/* The i810 through i855 have the registers at BAR 1, and the GATT gets
181 * allocated by us.  The i915 has registers in BAR 0 and the GATT is at the
182 * start of the stolen memory, and should only be accessed by the OS through
183 * BAR 3.  The G965 has registers and GATT in the same BAR (0) -- first 512KB
184 * is registers, second 512KB is GATT.
185 */
186static struct resource_spec agp_i810_res_spec[] = {
187	{ SYS_RES_MEMORY, AGP_I810_MMADR, RF_ACTIVE | RF_SHAREABLE },
188	{ -1, 0 }
189};
190
191static struct resource_spec agp_i915_res_spec[] = {
192	{ SYS_RES_MEMORY, AGP_I915_MMADR, RF_ACTIVE | RF_SHAREABLE },
193	{ SYS_RES_MEMORY, AGP_I915_GTTADR, RF_ACTIVE | RF_SHAREABLE },
194	{ -1, 0 }
195};
196
197static struct resource_spec agp_i965_res_spec[] = {
198	{ SYS_RES_MEMORY, AGP_I965_GTTMMADR, RF_ACTIVE | RF_SHAREABLE },
199	{ -1, 0 }
200};
201
202static struct resource_spec agp_g4x_res_spec[] = {
203	{ SYS_RES_MEMORY, AGP_G4X_MMADR, RF_ACTIVE | RF_SHAREABLE },
204	{ SYS_RES_MEMORY, AGP_G4X_GTTADR, RF_ACTIVE | RF_SHAREABLE },
205	{ -1, 0 }
206};
207
208struct agp_i810_softc {
209	struct agp_softc agp;
210	u_int32_t initial_aperture;	/* aperture size at startup */
211	struct agp_gatt *gatt;
212	u_int32_t dcache_size;		/* i810 only */
213	u_int32_t stolen;		/* number of i830/845 gtt
214					   entries for stolen memory */
215	u_int stolen_size;		/* BIOS-reserved graphics memory */
216	u_int gtt_total_entries;	/* Total number of gtt ptes */
217	u_int gtt_mappable_entries;	/* Number of gtt ptes mappable by CPU */
218	device_t bdev;			/* bridge device */
219	void *argb_cursor;		/* contigmalloc area for ARGB cursor */
220	struct resource *sc_res[2];
221	const struct agp_i810_match *match;
222	int sc_flush_page_rid;
223	struct resource *sc_flush_page_res;
224	void *sc_flush_page_vaddr;
225	int sc_bios_allocated_flush_page;
226};
227
228static device_t intel_agp;
229
230struct agp_i810_driver {
231	int chiptype;
232	int gen;
233	int busdma_addr_mask_sz;
234	struct resource_spec *res_spec;
235	int (*check_active)(device_t);
236	void (*set_desc)(device_t, const struct agp_i810_match *);
237	void (*dump_regs)(device_t);
238	int (*get_stolen_size)(device_t);
239	int (*get_gtt_total_entries)(device_t);
240	int (*get_gtt_mappable_entries)(device_t);
241	int (*install_gatt)(device_t);
242	void (*deinstall_gatt)(device_t);
243	void (*write_gtt)(device_t, u_int, uint32_t);
244	void (*install_gtt_pte)(device_t, u_int, vm_offset_t, int);
245	u_int32_t (*read_gtt_pte)(device_t, u_int);
246	vm_paddr_t (*read_gtt_pte_paddr)(device_t , u_int);
247	int (*set_aperture)(device_t, u_int32_t);
248	int (*chipset_flush_setup)(device_t);
249	void (*chipset_flush_teardown)(device_t);
250	void (*chipset_flush)(device_t);
251};
252
253static const struct agp_i810_driver agp_i810_i810_driver = {
254	.chiptype = CHIP_I810,
255	.gen = 1,
256	.busdma_addr_mask_sz = 32,
257	.res_spec = agp_i810_res_spec,
258	.check_active = agp_i810_check_active,
259	.set_desc = agp_i810_set_desc,
260	.dump_regs = agp_i810_dump_regs,
261	.get_stolen_size = agp_i810_get_stolen_size,
262	.get_gtt_mappable_entries = agp_i810_get_gtt_mappable_entries,
263	.get_gtt_total_entries = agp_i810_get_gtt_total_entries,
264	.install_gatt = agp_i810_install_gatt,
265	.deinstall_gatt = agp_i810_deinstall_gatt,
266	.write_gtt = agp_i810_write_gtt,
267	.install_gtt_pte = agp_i810_install_gtt_pte,
268	.read_gtt_pte = agp_i810_read_gtt_pte,
269	.read_gtt_pte_paddr = agp_i810_read_gtt_pte_paddr,
270	.set_aperture = agp_i810_set_aperture,
271	.chipset_flush_setup = agp_i810_chipset_flush_setup,
272	.chipset_flush_teardown = agp_i810_chipset_flush_teardown,
273	.chipset_flush = agp_i810_chipset_flush,
274};
275
276static const struct agp_i810_driver agp_i810_i815_driver = {
277	.chiptype = CHIP_I810,
278	.gen = 2,
279	.busdma_addr_mask_sz = 32,
280	.res_spec = agp_i810_res_spec,
281	.check_active = agp_i810_check_active,
282	.set_desc = agp_i810_set_desc,
283	.dump_regs = agp_i810_dump_regs,
284	.get_stolen_size = agp_i810_get_stolen_size,
285	.get_gtt_mappable_entries = agp_i830_get_gtt_mappable_entries,
286	.get_gtt_total_entries = agp_i810_get_gtt_total_entries,
287	.install_gatt = agp_i810_install_gatt,
288	.deinstall_gatt = agp_i810_deinstall_gatt,
289	.write_gtt = agp_i810_write_gtt,
290	.install_gtt_pte = agp_i810_install_gtt_pte,
291	.read_gtt_pte = agp_i810_read_gtt_pte,
292	.read_gtt_pte_paddr = agp_i810_read_gtt_pte_paddr,
293	.set_aperture = agp_i810_set_aperture,
294	.chipset_flush_setup = agp_i810_chipset_flush_setup,
295	.chipset_flush_teardown = agp_i810_chipset_flush_teardown,
296	.chipset_flush = agp_i830_chipset_flush,
297};
298
299static const struct agp_i810_driver agp_i810_i830_driver = {
300	.chiptype = CHIP_I830,
301	.gen = 2,
302	.busdma_addr_mask_sz = 32,
303	.res_spec = agp_i810_res_spec,
304	.check_active = agp_i830_check_active,
305	.set_desc = agp_i810_set_desc,
306	.dump_regs = agp_i830_dump_regs,
307	.get_stolen_size = agp_i830_get_stolen_size,
308	.get_gtt_mappable_entries = agp_i830_get_gtt_mappable_entries,
309	.get_gtt_total_entries = agp_i810_get_gtt_total_entries,
310	.install_gatt = agp_i830_install_gatt,
311	.deinstall_gatt = agp_i830_deinstall_gatt,
312	.write_gtt = agp_i810_write_gtt,
313	.install_gtt_pte = agp_i830_install_gtt_pte,
314	.read_gtt_pte = agp_i810_read_gtt_pte,
315	.read_gtt_pte_paddr = agp_i810_read_gtt_pte_paddr,
316	.set_aperture = agp_i830_set_aperture,
317	.chipset_flush_setup = agp_i810_chipset_flush_setup,
318	.chipset_flush_teardown = agp_i810_chipset_flush_teardown,
319	.chipset_flush = agp_i830_chipset_flush,
320};
321
322static const struct agp_i810_driver agp_i810_i855_driver = {
323	.chiptype = CHIP_I855,
324	.gen = 2,
325	.busdma_addr_mask_sz = 32,
326	.res_spec = agp_i810_res_spec,
327	.check_active = agp_i830_check_active,
328	.set_desc = agp_82852_set_desc,
329	.dump_regs = agp_i855_dump_regs,
330	.get_stolen_size = agp_i915_get_stolen_size,
331	.get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
332	.get_gtt_total_entries = agp_i810_get_gtt_total_entries,
333	.install_gatt = agp_i830_install_gatt,
334	.deinstall_gatt = agp_i830_deinstall_gatt,
335	.write_gtt = agp_i810_write_gtt,
336	.install_gtt_pte = agp_i830_install_gtt_pte,
337	.read_gtt_pte = agp_i810_read_gtt_pte,
338	.read_gtt_pte_paddr = agp_i810_read_gtt_pte_paddr,
339	.set_aperture = agp_i830_set_aperture,
340	.chipset_flush_setup = agp_i810_chipset_flush_setup,
341	.chipset_flush_teardown = agp_i810_chipset_flush_teardown,
342	.chipset_flush = agp_i830_chipset_flush,
343};
344
345static const struct agp_i810_driver agp_i810_i865_driver = {
346	.chiptype = CHIP_I855,
347	.gen = 2,
348	.busdma_addr_mask_sz = 32,
349	.res_spec = agp_i810_res_spec,
350	.check_active = agp_i830_check_active,
351	.set_desc = agp_i810_set_desc,
352	.dump_regs = agp_i855_dump_regs,
353	.get_stolen_size = agp_i915_get_stolen_size,
354	.get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
355	.get_gtt_total_entries = agp_i810_get_gtt_total_entries,
356	.install_gatt = agp_i830_install_gatt,
357	.deinstall_gatt = agp_i830_deinstall_gatt,
358	.write_gtt = agp_i810_write_gtt,
359	.install_gtt_pte = agp_i830_install_gtt_pte,
360	.read_gtt_pte = agp_i810_read_gtt_pte,
361	.read_gtt_pte_paddr = agp_i810_read_gtt_pte_paddr,
362	.set_aperture = agp_i915_set_aperture,
363	.chipset_flush_setup = agp_i810_chipset_flush_setup,
364	.chipset_flush_teardown = agp_i810_chipset_flush_teardown,
365	.chipset_flush = agp_i830_chipset_flush,
366};
367
368static const struct agp_i810_driver agp_i810_i915_driver = {
369	.chiptype = CHIP_I915,
370	.gen = 3,
371	.busdma_addr_mask_sz = 32,
372	.res_spec = agp_i915_res_spec,
373	.check_active = agp_i915_check_active,
374	.set_desc = agp_i810_set_desc,
375	.dump_regs = agp_i915_dump_regs,
376	.get_stolen_size = agp_i915_get_stolen_size,
377	.get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
378	.get_gtt_total_entries = agp_i810_get_gtt_total_entries,
379	.install_gatt = agp_i830_install_gatt,
380	.deinstall_gatt = agp_i830_deinstall_gatt,
381	.write_gtt = agp_i915_write_gtt,
382	.install_gtt_pte = agp_i915_install_gtt_pte,
383	.read_gtt_pte = agp_i915_read_gtt_pte,
384	.read_gtt_pte_paddr = agp_i915_read_gtt_pte_paddr,
385	.set_aperture = agp_i915_set_aperture,
386	.chipset_flush_setup = agp_i915_chipset_flush_setup,
387	.chipset_flush_teardown = agp_i915_chipset_flush_teardown,
388	.chipset_flush = agp_i915_chipset_flush,
389};
390
391static const struct agp_i810_driver agp_i810_g965_driver = {
392	.chiptype = CHIP_I965,
393	.gen = 4,
394	.busdma_addr_mask_sz = 36,
395	.res_spec = agp_i965_res_spec,
396	.check_active = agp_i915_check_active,
397	.set_desc = agp_i810_set_desc,
398	.dump_regs = agp_i965_dump_regs,
399	.get_stolen_size = agp_i915_get_stolen_size,
400	.get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
401	.get_gtt_total_entries = agp_i965_get_gtt_total_entries,
402	.install_gatt = agp_i965_install_gatt,
403	.deinstall_gatt = agp_i830_deinstall_gatt,
404	.write_gtt = agp_i965_write_gtt,
405	.install_gtt_pte = agp_i965_install_gtt_pte,
406	.read_gtt_pte = agp_i965_read_gtt_pte,
407	.read_gtt_pte_paddr = agp_i915_read_gtt_pte_paddr,
408	.set_aperture = agp_i915_set_aperture,
409	.chipset_flush_setup = agp_i965_chipset_flush_setup,
410	.chipset_flush_teardown = agp_i965_chipset_flush_teardown,
411	.chipset_flush = agp_i915_chipset_flush,
412};
413
414static const struct agp_i810_driver agp_i810_g33_driver = {
415	.chiptype = CHIP_G33,
416	.gen = 3,
417	.busdma_addr_mask_sz = 36,
418	.res_spec = agp_i915_res_spec,
419	.check_active = agp_i915_check_active,
420	.set_desc = agp_i810_set_desc,
421	.dump_regs = agp_i965_dump_regs,
422	.get_stolen_size = agp_i915_get_stolen_size,
423	.get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
424	.get_gtt_total_entries = agp_i965_get_gtt_total_entries,
425	.install_gatt = agp_i830_install_gatt,
426	.deinstall_gatt = agp_i830_deinstall_gatt,
427	.write_gtt = agp_i915_write_gtt,
428	.install_gtt_pte = agp_i915_install_gtt_pte,
429	.read_gtt_pte = agp_i915_read_gtt_pte,
430	.read_gtt_pte_paddr = agp_i915_read_gtt_pte_paddr,
431	.set_aperture = agp_i915_set_aperture,
432	.chipset_flush_setup = agp_i965_chipset_flush_setup,
433	.chipset_flush_teardown = agp_i965_chipset_flush_teardown,
434	.chipset_flush = agp_i915_chipset_flush,
435};
436
437static const struct agp_i810_driver agp_i810_igd_driver = {
438	.chiptype = CHIP_IGD,
439	.gen = 3,
440	.busdma_addr_mask_sz = 36,
441	.res_spec = agp_i915_res_spec,
442	.check_active = agp_i915_check_active,
443	.set_desc = agp_i810_set_desc,
444	.dump_regs = agp_i915_dump_regs,
445	.get_stolen_size = agp_i915_get_stolen_size,
446	.get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
447	.get_gtt_total_entries = agp_i965_get_gtt_total_entries,
448	.install_gatt = agp_i830_install_gatt,
449	.deinstall_gatt = agp_i830_deinstall_gatt,
450	.write_gtt = agp_i915_write_gtt,
451	.install_gtt_pte = agp_i915_install_gtt_pte,
452	.read_gtt_pte = agp_i915_read_gtt_pte,
453	.read_gtt_pte_paddr = agp_i915_read_gtt_pte_paddr,
454	.set_aperture = agp_i915_set_aperture,
455	.chipset_flush_setup = agp_i965_chipset_flush_setup,
456	.chipset_flush_teardown = agp_i965_chipset_flush_teardown,
457	.chipset_flush = agp_i915_chipset_flush,
458};
459
460static const struct agp_i810_driver agp_i810_g4x_driver = {
461	.chiptype = CHIP_G4X,
462	.gen = 5,
463	.busdma_addr_mask_sz = 36,
464	.res_spec = agp_i965_res_spec,
465	.check_active = agp_i915_check_active,
466	.set_desc = agp_i810_set_desc,
467	.dump_regs = agp_i965_dump_regs,
468	.get_stolen_size = agp_i915_get_stolen_size,
469	.get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
470	.get_gtt_total_entries = agp_gen5_get_gtt_total_entries,
471	.install_gatt = agp_g4x_install_gatt,
472	.deinstall_gatt = agp_i830_deinstall_gatt,
473	.write_gtt = agp_g4x_write_gtt,
474	.install_gtt_pte = agp_g4x_install_gtt_pte,
475	.read_gtt_pte = agp_g4x_read_gtt_pte,
476	.read_gtt_pte_paddr = agp_i915_read_gtt_pte_paddr,
477	.set_aperture = agp_i915_set_aperture,
478	.chipset_flush_setup = agp_i965_chipset_flush_setup,
479	.chipset_flush_teardown = agp_i965_chipset_flush_teardown,
480	.chipset_flush = agp_i915_chipset_flush,
481};
482
483static const struct agp_i810_driver agp_i810_sb_driver = {
484	.chiptype = CHIP_SB,
485	.gen = 6,
486	.busdma_addr_mask_sz = 40,
487	.res_spec = agp_g4x_res_spec,
488	.check_active = agp_sb_check_active,
489	.set_desc = agp_i810_set_desc,
490	.dump_regs = agp_sb_dump_regs,
491	.get_stolen_size = agp_sb_get_stolen_size,
492	.get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
493	.get_gtt_total_entries = agp_sb_get_gtt_total_entries,
494	.install_gatt = agp_g4x_install_gatt,
495	.deinstall_gatt = agp_i830_deinstall_gatt,
496	.write_gtt = agp_sb_write_gtt,
497	.install_gtt_pte = agp_sb_install_gtt_pte,
498	.read_gtt_pte = agp_g4x_read_gtt_pte,
499	.read_gtt_pte_paddr = agp_sb_read_gtt_pte_paddr,
500	.set_aperture = agp_i915_set_aperture,
501	.chipset_flush_setup = agp_i810_chipset_flush_setup,
502	.chipset_flush_teardown = agp_i810_chipset_flush_teardown,
503	.chipset_flush = agp_i810_chipset_flush,
504};
505
506/* For adding new devices, devid is the id of the graphics controller
507 * (pci:0:2:0, for example).  The placeholder (usually at pci:0:2:1) for the
508 * second head should never be added.  The bridge_offset is the offset to
509 * subtract from devid to get the id of the hostb that the device is on.
510 */
511static const struct agp_i810_match {
512	int devid;
513	char *name;
514	const struct agp_i810_driver *driver;
515} agp_i810_matches[] = {
516	{
517		.devid = 0x71218086,
518		.name = "Intel 82810 (i810 GMCH) SVGA controller",
519		.driver = &agp_i810_i810_driver
520	},
521	{
522		.devid = 0x71238086,
523		.name = "Intel 82810-DC100 (i810-DC100 GMCH) SVGA controller",
524		.driver = &agp_i810_i810_driver
525	},
526	{
527		.devid = 0x71258086,
528		.name = "Intel 82810E (i810E GMCH) SVGA controller",
529		.driver = &agp_i810_i810_driver
530	},
531	{
532		.devid = 0x11328086,
533		.name = "Intel 82815 (i815 GMCH) SVGA controller",
534		.driver = &agp_i810_i815_driver
535	},
536	{
537		.devid = 0x35778086,
538		.name = "Intel 82830M (830M GMCH) SVGA controller",
539		.driver = &agp_i810_i830_driver
540	},
541	{
542		.devid = 0x25628086,
543		.name = "Intel 82845M (845M GMCH) SVGA controller",
544		.driver = &agp_i810_i830_driver
545	},
546	{
547		.devid = 0x35828086,
548		.name = "Intel 82852/855GM SVGA controller",
549		.driver = &agp_i810_i855_driver
550	},
551	{
552		.devid = 0x25728086,
553		.name = "Intel 82865G (865G GMCH) SVGA controller",
554		.driver = &agp_i810_i865_driver
555	},
556	{
557		.devid = 0x25828086,
558		.name = "Intel 82915G (915G GMCH) SVGA controller",
559		.driver = &agp_i810_i915_driver
560	},
561	{
562		.devid = 0x258A8086,
563		.name = "Intel E7221 SVGA controller",
564		.driver = &agp_i810_i915_driver
565	},
566	{
567		.devid = 0x25928086,
568		.name = "Intel 82915GM (915GM GMCH) SVGA controller",
569		.driver = &agp_i810_i915_driver
570	},
571	{
572		.devid = 0x27728086,
573		.name = "Intel 82945G (945G GMCH) SVGA controller",
574		.driver = &agp_i810_i915_driver
575	},
576	{
577		.devid = 0x27A28086,
578		.name = "Intel 82945GM (945GM GMCH) SVGA controller",
579		.driver = &agp_i810_i915_driver
580	},
581	{
582		.devid = 0x27AE8086,
583		.name = "Intel 945GME SVGA controller",
584		.driver = &agp_i810_i915_driver
585	},
586	{
587		.devid = 0x29728086,
588		.name = "Intel 946GZ SVGA controller",
589		.driver = &agp_i810_g965_driver
590	},
591	{
592		.devid = 0x29828086,
593		.name = "Intel G965 SVGA controller",
594		.driver = &agp_i810_g965_driver
595	},
596	{
597		.devid = 0x29928086,
598		.name = "Intel Q965 SVGA controller",
599		.driver = &agp_i810_g965_driver
600	},
601	{
602		.devid = 0x29A28086,
603		.name = "Intel G965 SVGA controller",
604		.driver = &agp_i810_g965_driver
605	},
606	{
607		.devid = 0x29B28086,
608		.name = "Intel Q35 SVGA controller",
609		.driver = &agp_i810_g33_driver
610	},
611	{
612		.devid = 0x29C28086,
613		.name = "Intel G33 SVGA controller",
614		.driver = &agp_i810_g33_driver
615	},
616	{
617		.devid = 0x29D28086,
618		.name = "Intel Q33 SVGA controller",
619		.driver = &agp_i810_g33_driver
620	},
621	{
622		.devid = 0xA0018086,
623		.name = "Intel Pineview SVGA controller",
624		.driver = &agp_i810_igd_driver
625	},
626	{
627		.devid = 0xA0118086,
628		.name = "Intel Pineview (M) SVGA controller",
629		.driver = &agp_i810_igd_driver
630	},
631	{
632		.devid = 0x2A028086,
633		.name = "Intel GM965 SVGA controller",
634		.driver = &agp_i810_g965_driver
635	},
636	{
637		.devid = 0x2A128086,
638		.name = "Intel GME965 SVGA controller",
639		.driver = &agp_i810_g965_driver
640	},
641	{
642		.devid = 0x2A428086,
643		.name = "Intel GM45 SVGA controller",
644		.driver = &agp_i810_g4x_driver
645	},
646	{
647		.devid = 0x2E028086,
648		.name = "Intel Eaglelake SVGA controller",
649		.driver = &agp_i810_g4x_driver
650	},
651	{
652		.devid = 0x2E128086,
653		.name = "Intel Q45 SVGA controller",
654		.driver = &agp_i810_g4x_driver
655	},
656	{
657		.devid = 0x2E228086,
658		.name = "Intel G45 SVGA controller",
659		.driver = &agp_i810_g4x_driver
660	},
661	{
662		.devid = 0x2E328086,
663		.name = "Intel G41 SVGA controller",
664		.driver = &agp_i810_g4x_driver
665	},
666	{
667		.devid = 0x00428086,
668		.name = "Intel Ironlake (D) SVGA controller",
669		.driver = &agp_i810_g4x_driver
670	},
671	{
672		.devid = 0x00468086,
673		.name = "Intel Ironlake (M) SVGA controller",
674		.driver = &agp_i810_g4x_driver
675	},
676	{
677		.devid = 0x01028086,
678		.name = "SandyBridge desktop GT1 IG",
679		.driver = &agp_i810_sb_driver
680	},
681	{
682		.devid = 0x01128086,
683		.name = "SandyBridge desktop GT2 IG",
684		.driver = &agp_i810_sb_driver
685	},
686	{
687		.devid = 0x01228086,
688		.name = "SandyBridge desktop GT2+ IG",
689		.driver = &agp_i810_sb_driver
690	},
691	{
692		.devid = 0x01068086,
693		.name = "SandyBridge mobile GT1 IG",
694		.driver = &agp_i810_sb_driver
695	},
696	{
697		.devid = 0x01168086,
698		.name = "SandyBridge mobile GT2 IG",
699		.driver = &agp_i810_sb_driver
700	},
701	{
702		.devid = 0x01268086,
703		.name = "SandyBridge mobile GT2+ IG",
704		.driver = &agp_i810_sb_driver
705	},
706	{
707		.devid = 0x010a8086,
708		.name = "SandyBridge server IG",
709		.driver = &agp_i810_sb_driver
710	},
711	{
712		.devid = 0x01528086,
713		.name = "IvyBridge desktop GT1 IG",
714		.driver = &agp_i810_sb_driver
715	},
716	{
717		.devid = 0x01628086,
718		.name = "IvyBridge desktop GT2 IG",
719		.driver = &agp_i810_sb_driver
720	},
721	{
722		.devid = 0x01568086,
723		.name = "IvyBridge mobile GT1 IG",
724		.driver = &agp_i810_sb_driver
725	},
726	{
727		.devid = 0x01668086,
728		.name = "IvyBridge mobile GT2 IG",
729		.driver = &agp_i810_sb_driver
730	},
731	{
732		.devid = 0x015a8086,
733		.name = "IvyBridge server GT1 IG",
734		.driver = &agp_i810_sb_driver
735	},
736	{
737		.devid = 0x016a8086,
738		.name = "IvyBridge server GT2 IG",
739		.driver = &agp_i810_sb_driver
740	},
741	{
742		.devid = 0,
743	}
744};
745
746static const struct agp_i810_match*
747agp_i810_match(device_t dev)
748{
749	int i, devid;
750
751	if (pci_get_class(dev) != PCIC_DISPLAY
752	    || (pci_get_subclass(dev) != PCIS_DISPLAY_VGA &&
753	    pci_get_subclass(dev) != PCIS_DISPLAY_OTHER))
754		return (NULL);
755
756	devid = pci_get_devid(dev);
757	for (i = 0; agp_i810_matches[i].devid != 0; i++) {
758		if (agp_i810_matches[i].devid == devid)
759			break;
760	}
761	if (agp_i810_matches[i].devid == 0)
762		return (NULL);
763	else
764		return (&agp_i810_matches[i]);
765}
766
767/*
768 * Find bridge device.
769 */
770static device_t
771agp_i810_find_bridge(device_t dev)
772{
773
774	return (pci_find_dbsf(0, 0, 0, 0));
775}
776
777static void
778agp_i810_identify(driver_t *driver, device_t parent)
779{
780
781	if (device_find_child(parent, "agp", -1) == NULL &&
782	    agp_i810_match(parent))
783		device_add_child(parent, "agp", -1);
784}
785
786static int
787agp_i810_check_active(device_t bridge_dev)
788{
789	u_int8_t smram;
790
791	smram = pci_read_config(bridge_dev, AGP_I810_SMRAM, 1);
792	if ((smram & AGP_I810_SMRAM_GMS) == AGP_I810_SMRAM_GMS_DISABLED)
793		return (ENXIO);
794	return (0);
795}
796
797static int
798agp_i830_check_active(device_t bridge_dev)
799{
800	int gcc1;
801
802	gcc1 = pci_read_config(bridge_dev, AGP_I830_GCC1, 1);
803	if ((gcc1 & AGP_I830_GCC1_DEV2) == AGP_I830_GCC1_DEV2_DISABLED)
804		return (ENXIO);
805	return (0);
806}
807
808static int
809agp_i915_check_active(device_t bridge_dev)
810{
811	int deven;
812
813	deven = pci_read_config(bridge_dev, AGP_I915_DEVEN, 4);
814	if ((deven & AGP_I915_DEVEN_D2F0) == AGP_I915_DEVEN_D2F0_DISABLED)
815		return (ENXIO);
816	return (0);
817}
818
819static int
820agp_sb_check_active(device_t bridge_dev)
821{
822	int deven;
823
824	deven = pci_read_config(bridge_dev, AGP_I915_DEVEN, 4);
825	if ((deven & AGP_SB_DEVEN_D2EN) == AGP_SB_DEVEN_D2EN_DISABLED)
826		return (ENXIO);
827	return (0);
828}
829
830static void
831agp_82852_set_desc(device_t dev, const struct agp_i810_match *match)
832{
833
834	switch (pci_read_config(dev, AGP_I85X_CAPID, 1)) {
835	case AGP_I855_GME:
836		device_set_desc(dev,
837		    "Intel 82855GME (855GME GMCH) SVGA controller");
838		break;
839	case AGP_I855_GM:
840		device_set_desc(dev,
841		    "Intel 82855GM (855GM GMCH) SVGA controller");
842		break;
843	case AGP_I852_GME:
844		device_set_desc(dev,
845		    "Intel 82852GME (852GME GMCH) SVGA controller");
846		break;
847	case AGP_I852_GM:
848		device_set_desc(dev,
849		    "Intel 82852GM (852GM GMCH) SVGA controller");
850		break;
851	default:
852		device_set_desc(dev,
853		    "Intel 8285xM (85xGM GMCH) SVGA controller");
854		break;
855	}
856}
857
858static void
859agp_i810_set_desc(device_t dev, const struct agp_i810_match *match)
860{
861
862	device_set_desc(dev, match->name);
863}
864
865static int
866agp_i810_probe(device_t dev)
867{
868	device_t bdev;
869	const struct agp_i810_match *match;
870	int err;
871
872	if (resource_disabled("agp", device_get_unit(dev)))
873		return (ENXIO);
874	match = agp_i810_match(dev);
875	if (match == NULL)
876		return (ENXIO);
877
878	bdev = agp_i810_find_bridge(dev);
879	if (bdev == NULL) {
880		if (bootverbose)
881			printf("I810: can't find bridge device\n");
882		return (ENXIO);
883	}
884
885	/*
886	 * checking whether internal graphics device has been activated.
887	 */
888	err = match->driver->check_active(bdev);
889	if (err != 0) {
890		if (bootverbose)
891			printf("i810: disabled, not probing\n");
892		return (err);
893	}
894
895	match->driver->set_desc(dev, match);
896	return (BUS_PROBE_DEFAULT);
897}
898
899static void
900agp_i810_dump_regs(device_t dev)
901{
902	struct agp_i810_softc *sc = device_get_softc(dev);
903
904	device_printf(dev, "AGP_I810_PGTBL_CTL: %08x\n",
905	    bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL));
906	device_printf(dev, "AGP_I810_MISCC: 0x%04x\n",
907	    pci_read_config(sc->bdev, AGP_I810_MISCC, 2));
908}
909
910static void
911agp_i830_dump_regs(device_t dev)
912{
913	struct agp_i810_softc *sc = device_get_softc(dev);
914
915	device_printf(dev, "AGP_I810_PGTBL_CTL: %08x\n",
916	    bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL));
917	device_printf(dev, "AGP_I830_GCC1: 0x%02x\n",
918	    pci_read_config(sc->bdev, AGP_I830_GCC1, 1));
919}
920
921static void
922agp_i855_dump_regs(device_t dev)
923{
924	struct agp_i810_softc *sc = device_get_softc(dev);
925
926	device_printf(dev, "AGP_I810_PGTBL_CTL: %08x\n",
927	    bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL));
928	device_printf(dev, "AGP_I855_GCC1: 0x%02x\n",
929	    pci_read_config(sc->bdev, AGP_I855_GCC1, 1));
930}
931
932static void
933agp_i915_dump_regs(device_t dev)
934{
935	struct agp_i810_softc *sc = device_get_softc(dev);
936
937	device_printf(dev, "AGP_I810_PGTBL_CTL: %08x\n",
938	    bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL));
939	device_printf(dev, "AGP_I855_GCC1: 0x%02x\n",
940	    pci_read_config(sc->bdev, AGP_I855_GCC1, 1));
941	device_printf(dev, "AGP_I915_MSAC: 0x%02x\n",
942	    pci_read_config(sc->bdev, AGP_I915_MSAC, 1));
943}
944
945static void
946agp_i965_dump_regs(device_t dev)
947{
948	struct agp_i810_softc *sc = device_get_softc(dev);
949
950	device_printf(dev, "AGP_I965_PGTBL_CTL2: %08x\n",
951	    bus_read_4(sc->sc_res[0], AGP_I965_PGTBL_CTL2));
952	device_printf(dev, "AGP_I855_GCC1: 0x%02x\n",
953	    pci_read_config(sc->bdev, AGP_I855_GCC1, 1));
954	device_printf(dev, "AGP_I965_MSAC: 0x%02x\n",
955	    pci_read_config(sc->bdev, AGP_I965_MSAC, 1));
956}
957
958static void
959agp_sb_dump_regs(device_t dev)
960{
961	struct agp_i810_softc *sc = device_get_softc(dev);
962
963	device_printf(dev, "AGP_SNB_GFX_MODE: %08x\n",
964	    bus_read_4(sc->sc_res[0], AGP_SNB_GFX_MODE));
965	device_printf(dev, "AGP_SNB_GCC1: 0x%04x\n",
966	    pci_read_config(sc->bdev, AGP_SNB_GCC1, 2));
967}
968
969static int
970agp_i810_get_stolen_size(device_t dev)
971{
972	struct agp_i810_softc *sc;
973
974	sc = device_get_softc(dev);
975	sc->stolen = 0;
976	sc->stolen_size = 0;
977	return (0);
978}
979
980static int
981agp_i830_get_stolen_size(device_t dev)
982{
983	struct agp_i810_softc *sc;
984	unsigned int gcc1;
985
986	sc = device_get_softc(dev);
987
988	gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 1);
989	switch (gcc1 & AGP_I830_GCC1_GMS) {
990	case AGP_I830_GCC1_GMS_STOLEN_512:
991		sc->stolen = (512 - 132) * 1024 / 4096;
992		sc->stolen_size = 512 * 1024;
993		break;
994	case AGP_I830_GCC1_GMS_STOLEN_1024:
995		sc->stolen = (1024 - 132) * 1024 / 4096;
996		sc->stolen_size = 1024 * 1024;
997		break;
998	case AGP_I830_GCC1_GMS_STOLEN_8192:
999		sc->stolen = (8192 - 132) * 1024 / 4096;
1000		sc->stolen_size = 8192 * 1024;
1001		break;
1002	default:
1003		sc->stolen = 0;
1004		device_printf(dev,
1005		    "unknown memory configuration, disabling (GCC1 %x)\n",
1006		    gcc1);
1007		return (EINVAL);
1008	}
1009	return (0);
1010}
1011
1012static int
1013agp_i915_get_stolen_size(device_t dev)
1014{
1015	struct agp_i810_softc *sc;
1016	unsigned int gcc1, stolen, gtt_size;
1017
1018	sc = device_get_softc(dev);
1019
1020	/*
1021	 * Stolen memory is set up at the beginning of the aperture by
1022	 * the BIOS, consisting of the GATT followed by 4kb for the
1023	 * BIOS display.
1024	 */
1025	switch (sc->match->driver->chiptype) {
1026	case CHIP_I855:
1027		gtt_size = 128;
1028		break;
1029	case CHIP_I915:
1030		gtt_size = 256;
1031		break;
1032	case CHIP_I965:
1033		switch (bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL) &
1034			AGP_I810_PGTBL_SIZE_MASK) {
1035		case AGP_I810_PGTBL_SIZE_128KB:
1036			gtt_size = 128;
1037			break;
1038		case AGP_I810_PGTBL_SIZE_256KB:
1039			gtt_size = 256;
1040			break;
1041		case AGP_I810_PGTBL_SIZE_512KB:
1042			gtt_size = 512;
1043			break;
1044		case AGP_I965_PGTBL_SIZE_1MB:
1045			gtt_size = 1024;
1046			break;
1047		case AGP_I965_PGTBL_SIZE_2MB:
1048			gtt_size = 2048;
1049			break;
1050		case AGP_I965_PGTBL_SIZE_1_5MB:
1051			gtt_size = 1024 + 512;
1052			break;
1053		default:
1054			device_printf(dev, "Bad PGTBL size\n");
1055			return (EINVAL);
1056		}
1057		break;
1058	case CHIP_G33:
1059		gcc1 = pci_read_config(sc->bdev, AGP_I855_GCC1, 2);
1060		switch (gcc1 & AGP_G33_MGGC_GGMS_MASK) {
1061		case AGP_G33_MGGC_GGMS_SIZE_1M:
1062			gtt_size = 1024;
1063			break;
1064		case AGP_G33_MGGC_GGMS_SIZE_2M:
1065			gtt_size = 2048;
1066			break;
1067		default:
1068			device_printf(dev, "Bad PGTBL size\n");
1069			return (EINVAL);
1070		}
1071		break;
1072	case CHIP_IGD:
1073	case CHIP_G4X:
1074		gtt_size = 0;
1075		break;
1076	default:
1077		device_printf(dev, "Bad chiptype\n");
1078		return (EINVAL);
1079	}
1080
1081	/* GCC1 is called MGGC on i915+ */
1082	gcc1 = pci_read_config(sc->bdev, AGP_I855_GCC1, 1);
1083	switch (gcc1 & AGP_I855_GCC1_GMS) {
1084	case AGP_I855_GCC1_GMS_STOLEN_1M:
1085		stolen = 1024;
1086		break;
1087	case AGP_I855_GCC1_GMS_STOLEN_4M:
1088		stolen = 4 * 1024;
1089		break;
1090	case AGP_I855_GCC1_GMS_STOLEN_8M:
1091		stolen = 8 * 1024;
1092		break;
1093	case AGP_I855_GCC1_GMS_STOLEN_16M:
1094		stolen = 16 * 1024;
1095		break;
1096	case AGP_I855_GCC1_GMS_STOLEN_32M:
1097		stolen = 32 * 1024;
1098		break;
1099	case AGP_I915_GCC1_GMS_STOLEN_48M:
1100		stolen = sc->match->driver->gen > 2 ? 48 * 1024 : 0;
1101		break;
1102	case AGP_I915_GCC1_GMS_STOLEN_64M:
1103		stolen = sc->match->driver->gen > 2 ? 64 * 1024 : 0;
1104		break;
1105	case AGP_G33_GCC1_GMS_STOLEN_128M:
1106		stolen = sc->match->driver->gen > 2 ? 128 * 1024 : 0;
1107		break;
1108	case AGP_G33_GCC1_GMS_STOLEN_256M:
1109		stolen = sc->match->driver->gen > 2 ? 256 * 1024 : 0;
1110		break;
1111	case AGP_G4X_GCC1_GMS_STOLEN_96M:
1112		if (sc->match->driver->chiptype == CHIP_I965 ||
1113		    sc->match->driver->chiptype == CHIP_G4X)
1114			stolen = 96 * 1024;
1115		else
1116			stolen = 0;
1117		break;
1118	case AGP_G4X_GCC1_GMS_STOLEN_160M:
1119		if (sc->match->driver->chiptype == CHIP_I965 ||
1120		    sc->match->driver->chiptype == CHIP_G4X)
1121			stolen = 160 * 1024;
1122		else
1123			stolen = 0;
1124		break;
1125	case AGP_G4X_GCC1_GMS_STOLEN_224M:
1126		if (sc->match->driver->chiptype == CHIP_I965 ||
1127		    sc->match->driver->chiptype == CHIP_G4X)
1128			stolen = 224 * 1024;
1129		else
1130			stolen = 0;
1131		break;
1132	case AGP_G4X_GCC1_GMS_STOLEN_352M:
1133		if (sc->match->driver->chiptype == CHIP_I965 ||
1134		    sc->match->driver->chiptype == CHIP_G4X)
1135			stolen = 352 * 1024;
1136		else
1137			stolen = 0;
1138		break;
1139	default:
1140		device_printf(dev,
1141		    "unknown memory configuration, disabling (GCC1 %x)\n",
1142		    gcc1);
1143		return (EINVAL);
1144	}
1145
1146	gtt_size += 4;
1147	sc->stolen_size = stolen * 1024;
1148	sc->stolen = (stolen - gtt_size) * 1024 / 4096;
1149
1150	return (0);
1151}
1152
1153static int
1154agp_sb_get_stolen_size(device_t dev)
1155{
1156	struct agp_i810_softc *sc;
1157	uint16_t gmch_ctl;
1158
1159	sc = device_get_softc(dev);
1160	gmch_ctl = pci_read_config(sc->bdev, AGP_SNB_GCC1, 2);
1161	switch (gmch_ctl & AGP_SNB_GMCH_GMS_STOLEN_MASK) {
1162	case AGP_SNB_GMCH_GMS_STOLEN_32M:
1163		sc->stolen_size = 32 * 1024 * 1024;
1164		break;
1165	case AGP_SNB_GMCH_GMS_STOLEN_64M:
1166		sc->stolen_size = 64 * 1024 * 1024;
1167		break;
1168	case AGP_SNB_GMCH_GMS_STOLEN_96M:
1169		sc->stolen_size = 96 * 1024 * 1024;
1170		break;
1171	case AGP_SNB_GMCH_GMS_STOLEN_128M:
1172		sc->stolen_size = 128 * 1024 * 1024;
1173		break;
1174	case AGP_SNB_GMCH_GMS_STOLEN_160M:
1175		sc->stolen_size = 160 * 1024 * 1024;
1176		break;
1177	case AGP_SNB_GMCH_GMS_STOLEN_192M:
1178		sc->stolen_size = 192 * 1024 * 1024;
1179		break;
1180	case AGP_SNB_GMCH_GMS_STOLEN_224M:
1181		sc->stolen_size = 224 * 1024 * 1024;
1182		break;
1183	case AGP_SNB_GMCH_GMS_STOLEN_256M:
1184		sc->stolen_size = 256 * 1024 * 1024;
1185		break;
1186	case AGP_SNB_GMCH_GMS_STOLEN_288M:
1187		sc->stolen_size = 288 * 1024 * 1024;
1188		break;
1189	case AGP_SNB_GMCH_GMS_STOLEN_320M:
1190		sc->stolen_size = 320 * 1024 * 1024;
1191		break;
1192	case AGP_SNB_GMCH_GMS_STOLEN_352M:
1193		sc->stolen_size = 352 * 1024 * 1024;
1194		break;
1195	case AGP_SNB_GMCH_GMS_STOLEN_384M:
1196		sc->stolen_size = 384 * 1024 * 1024;
1197		break;
1198	case AGP_SNB_GMCH_GMS_STOLEN_416M:
1199		sc->stolen_size = 416 * 1024 * 1024;
1200		break;
1201	case AGP_SNB_GMCH_GMS_STOLEN_448M:
1202		sc->stolen_size = 448 * 1024 * 1024;
1203		break;
1204	case AGP_SNB_GMCH_GMS_STOLEN_480M:
1205		sc->stolen_size = 480 * 1024 * 1024;
1206		break;
1207	case AGP_SNB_GMCH_GMS_STOLEN_512M:
1208		sc->stolen_size = 512 * 1024 * 1024;
1209		break;
1210	}
1211	sc->stolen = (sc->stolen_size - 4) / 4096;
1212	return (0);
1213}
1214
1215static int
1216agp_i810_get_gtt_mappable_entries(device_t dev)
1217{
1218	struct agp_i810_softc *sc;
1219	uint32_t ap;
1220	uint16_t miscc;
1221
1222	sc = device_get_softc(dev);
1223	miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
1224	if ((miscc & AGP_I810_MISCC_WINSIZE) == AGP_I810_MISCC_WINSIZE_32)
1225		ap = 32;
1226	else
1227		ap = 64;
1228	sc->gtt_mappable_entries = (ap * 1024 * 1024) >> AGP_PAGE_SHIFT;
1229	return (0);
1230}
1231
1232static int
1233agp_i830_get_gtt_mappable_entries(device_t dev)
1234{
1235	struct agp_i810_softc *sc;
1236	uint32_t ap;
1237	uint16_t gmch_ctl;
1238
1239	sc = device_get_softc(dev);
1240	gmch_ctl = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
1241	if ((gmch_ctl & AGP_I830_GCC1_GMASIZE) == AGP_I830_GCC1_GMASIZE_64)
1242		ap = 64;
1243	else
1244		ap = 128;
1245	sc->gtt_mappable_entries = (ap * 1024 * 1024) >> AGP_PAGE_SHIFT;
1246	return (0);
1247}
1248
1249static int
1250agp_i915_get_gtt_mappable_entries(device_t dev)
1251{
1252	struct agp_i810_softc *sc;
1253	uint32_t ap;
1254
1255	sc = device_get_softc(dev);
1256	ap = AGP_GET_APERTURE(dev);
1257	sc->gtt_mappable_entries = ap >> AGP_PAGE_SHIFT;
1258	return (0);
1259}
1260
1261static int
1262agp_i810_get_gtt_total_entries(device_t dev)
1263{
1264	struct agp_i810_softc *sc;
1265
1266	sc = device_get_softc(dev);
1267	sc->gtt_total_entries = sc->gtt_mappable_entries;
1268	return (0);
1269}
1270
1271static int
1272agp_i965_get_gtt_total_entries(device_t dev)
1273{
1274	struct agp_i810_softc *sc;
1275	uint32_t pgetbl_ctl;
1276	int error;
1277
1278	sc = device_get_softc(dev);
1279	error = 0;
1280	pgetbl_ctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
1281	switch (pgetbl_ctl & AGP_I810_PGTBL_SIZE_MASK) {
1282	case AGP_I810_PGTBL_SIZE_128KB:
1283		sc->gtt_total_entries = 128 * 1024 / 4;
1284		break;
1285	case AGP_I810_PGTBL_SIZE_256KB:
1286		sc->gtt_total_entries = 256 * 1024 / 4;
1287		break;
1288	case AGP_I810_PGTBL_SIZE_512KB:
1289		sc->gtt_total_entries = 512 * 1024 / 4;
1290		break;
1291	/* GTT pagetable sizes bigger than 512KB are not possible on G33! */
1292	case AGP_I810_PGTBL_SIZE_1MB:
1293		sc->gtt_total_entries = 1024 * 1024 / 4;
1294		break;
1295	case AGP_I810_PGTBL_SIZE_2MB:
1296		sc->gtt_total_entries = 2 * 1024 * 1024 / 4;
1297		break;
1298	case AGP_I810_PGTBL_SIZE_1_5MB:
1299		sc->gtt_total_entries = (1024 + 512) * 1024 / 4;
1300		break;
1301	default:
1302		device_printf(dev, "Unknown page table size\n");
1303		error = ENXIO;
1304	}
1305	return (error);
1306}
1307
1308static void
1309agp_gen5_adjust_pgtbl_size(device_t dev, uint32_t sz)
1310{
1311	struct agp_i810_softc *sc;
1312	uint32_t pgetbl_ctl, pgetbl_ctl2;
1313
1314	sc = device_get_softc(dev);
1315
1316	/* Disable per-process page table. */
1317	pgetbl_ctl2 = bus_read_4(sc->sc_res[0], AGP_I965_PGTBL_CTL2);
1318	pgetbl_ctl2 &= ~AGP_I810_PGTBL_ENABLED;
1319	bus_write_4(sc->sc_res[0], AGP_I965_PGTBL_CTL2, pgetbl_ctl2);
1320
1321	/* Write the new ggtt size. */
1322	pgetbl_ctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
1323	pgetbl_ctl &= ~AGP_I810_PGTBL_SIZE_MASK;
1324	pgetbl_ctl |= sz;
1325	bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgetbl_ctl);
1326}
1327
1328static int
1329agp_gen5_get_gtt_total_entries(device_t dev)
1330{
1331	struct agp_i810_softc *sc;
1332	uint16_t gcc1;
1333
1334	sc = device_get_softc(dev);
1335
1336	gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
1337	switch (gcc1 & AGP_G4x_GCC1_SIZE_MASK) {
1338	case AGP_G4x_GCC1_SIZE_1M:
1339	case AGP_G4x_GCC1_SIZE_VT_1M:
1340		agp_gen5_adjust_pgtbl_size(dev, AGP_I810_PGTBL_SIZE_1MB);
1341		break;
1342	case AGP_G4x_GCC1_SIZE_VT_1_5M:
1343		agp_gen5_adjust_pgtbl_size(dev, AGP_I810_PGTBL_SIZE_1_5MB);
1344		break;
1345	case AGP_G4x_GCC1_SIZE_2M:
1346	case AGP_G4x_GCC1_SIZE_VT_2M:
1347		agp_gen5_adjust_pgtbl_size(dev, AGP_I810_PGTBL_SIZE_2MB);
1348		break;
1349	default:
1350		device_printf(dev, "Unknown page table size\n");
1351		return (ENXIO);
1352	}
1353
1354	return (agp_i965_get_gtt_total_entries(dev));
1355}
1356
1357static int
1358agp_sb_get_gtt_total_entries(device_t dev)
1359{
1360	struct agp_i810_softc *sc;
1361	uint16_t gcc1;
1362
1363	sc = device_get_softc(dev);
1364
1365	gcc1 = pci_read_config(sc->bdev, AGP_SNB_GCC1, 2);
1366	switch (gcc1 & AGP_SNB_GTT_SIZE_MASK) {
1367	default:
1368	case AGP_SNB_GTT_SIZE_0M:
1369		printf("Bad GTT size mask: 0x%04x\n", gcc1);
1370		return (ENXIO);
1371	case AGP_SNB_GTT_SIZE_1M:
1372		sc->gtt_total_entries = 1024 * 1024 / 4;
1373		break;
1374	case AGP_SNB_GTT_SIZE_2M:
1375		sc->gtt_total_entries = 2 * 1024 * 1024 / 4;
1376		break;
1377	}
1378	return (0);
1379}
1380
1381static int
1382agp_i810_install_gatt(device_t dev)
1383{
1384	struct agp_i810_softc *sc;
1385
1386	sc = device_get_softc(dev);
1387
1388	/* Some i810s have on-chip memory called dcache. */
1389	if ((bus_read_1(sc->sc_res[0], AGP_I810_DRT) & AGP_I810_DRT_POPULATED)
1390	    != 0)
1391		sc->dcache_size = 4 * 1024 * 1024;
1392	else
1393		sc->dcache_size = 0;
1394
1395	/* According to the specs the gatt on the i810 must be 64k. */
1396	sc->gatt->ag_virtual = (void *)kmem_alloc_contig(kernel_arena,
1397	    64 * 1024, M_NOWAIT | M_ZERO, 0, ~0, PAGE_SIZE,
1398	    0, VM_MEMATTR_WRITE_COMBINING);
1399	if (sc->gatt->ag_virtual == NULL) {
1400		if (bootverbose)
1401			device_printf(dev, "contiguous allocation failed\n");
1402		return (ENOMEM);
1403	}
1404
1405	sc->gatt->ag_physical = vtophys((vm_offset_t)sc->gatt->ag_virtual);
1406	/* Install the GATT. */
1407	bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL,
1408	    sc->gatt->ag_physical | 1);
1409	return (0);
1410}
1411
1412static void
1413agp_i830_install_gatt_init(struct agp_i810_softc *sc)
1414{
1415	uint32_t pgtblctl;
1416
1417	/*
1418	 * The i830 automatically initializes the 128k gatt on boot.
1419	 * GATT address is already in there, make sure it's enabled.
1420	 */
1421	pgtblctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
1422	pgtblctl |= 1;
1423	bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgtblctl);
1424
1425	sc->gatt->ag_physical = pgtblctl & ~1;
1426}
1427
1428static int
1429agp_i830_install_gatt(device_t dev)
1430{
1431	struct agp_i810_softc *sc;
1432
1433	sc = device_get_softc(dev);
1434	agp_i830_install_gatt_init(sc);
1435	return (0);
1436}
1437
1438static int
1439agp_gen4_install_gatt(device_t dev, const vm_size_t gtt_offset)
1440{
1441	struct agp_i810_softc *sc;
1442
1443	sc = device_get_softc(dev);
1444	pmap_change_attr((vm_offset_t)rman_get_virtual(sc->sc_res[0]) +
1445	    gtt_offset, rman_get_size(sc->sc_res[0]) - gtt_offset,
1446	    VM_MEMATTR_WRITE_COMBINING);
1447	agp_i830_install_gatt_init(sc);
1448	return (0);
1449}
1450
1451static int
1452agp_i965_install_gatt(device_t dev)
1453{
1454
1455	return (agp_gen4_install_gatt(dev, 512 * 1024));
1456}
1457
1458static int
1459agp_g4x_install_gatt(device_t dev)
1460{
1461
1462	return (agp_gen4_install_gatt(dev, 2 * 1024 * 1024));
1463}
1464
1465static int
1466agp_i810_attach(device_t dev)
1467{
1468	struct agp_i810_softc *sc;
1469	int error;
1470
1471	sc = device_get_softc(dev);
1472	sc->bdev = agp_i810_find_bridge(dev);
1473	if (sc->bdev == NULL)
1474		return (ENOENT);
1475
1476	sc->match = agp_i810_match(dev);
1477
1478	agp_set_aperture_resource(dev, sc->match->driver->gen <= 2 ?
1479	    AGP_APBASE : AGP_I915_GMADR);
1480	error = agp_generic_attach(dev);
1481	if (error)
1482		return (error);
1483
1484	if (ptoa((vm_paddr_t)Maxmem) >
1485	    (1ULL << sc->match->driver->busdma_addr_mask_sz) - 1) {
1486		device_printf(dev, "agp_i810 does not support physical "
1487		    "memory above %ju.\n", (uintmax_t)(1ULL <<
1488		    sc->match->driver->busdma_addr_mask_sz) - 1);
1489		return (ENOENT);
1490	}
1491
1492	if (bus_alloc_resources(dev, sc->match->driver->res_spec, sc->sc_res)) {
1493		agp_generic_detach(dev);
1494		return (ENODEV);
1495	}
1496
1497	sc->initial_aperture = AGP_GET_APERTURE(dev);
1498	sc->gatt = malloc(sizeof(struct agp_gatt), M_AGP, M_WAITOK);
1499	sc->gatt->ag_entries = AGP_GET_APERTURE(dev) >> AGP_PAGE_SHIFT;
1500
1501	if ((error = sc->match->driver->get_stolen_size(dev)) != 0 ||
1502	    (error = sc->match->driver->install_gatt(dev)) != 0 ||
1503	    (error = sc->match->driver->get_gtt_mappable_entries(dev)) != 0 ||
1504	    (error = sc->match->driver->get_gtt_total_entries(dev)) != 0 ||
1505	    (error = sc->match->driver->chipset_flush_setup(dev)) != 0) {
1506		bus_release_resources(dev, sc->match->driver->res_spec,
1507		    sc->sc_res);
1508		free(sc->gatt, M_AGP);
1509		agp_generic_detach(dev);
1510		return (error);
1511	}
1512
1513	intel_agp = dev;
1514	device_printf(dev, "aperture size is %dM",
1515	    sc->initial_aperture / 1024 / 1024);
1516	if (sc->stolen > 0)
1517		printf(", detected %dk stolen memory\n", sc->stolen * 4);
1518	else
1519		printf("\n");
1520	if (bootverbose) {
1521		sc->match->driver->dump_regs(dev);
1522		device_printf(dev, "Mappable GTT entries: %d\n",
1523		    sc->gtt_mappable_entries);
1524		device_printf(dev, "Total GTT entries: %d\n",
1525		    sc->gtt_total_entries);
1526	}
1527	return (0);
1528}
1529
1530static void
1531agp_i810_deinstall_gatt(device_t dev)
1532{
1533	struct agp_i810_softc *sc;
1534
1535	sc = device_get_softc(dev);
1536	bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, 0);
1537	kmem_free(kernel_arena, (vm_offset_t)sc->gatt->ag_virtual, 64 * 1024);
1538}
1539
1540static void
1541agp_i830_deinstall_gatt(device_t dev)
1542{
1543	struct agp_i810_softc *sc;
1544	unsigned int pgtblctl;
1545
1546	sc = device_get_softc(dev);
1547	pgtblctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
1548	pgtblctl &= ~1;
1549	bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgtblctl);
1550}
1551
1552static int
1553agp_i810_detach(device_t dev)
1554{
1555	struct agp_i810_softc *sc;
1556
1557	sc = device_get_softc(dev);
1558	agp_free_cdev(dev);
1559
1560	/* Clear the GATT base. */
1561	sc->match->driver->deinstall_gatt(dev);
1562
1563	sc->match->driver->chipset_flush_teardown(dev);
1564
1565	/* Put the aperture back the way it started. */
1566	AGP_SET_APERTURE(dev, sc->initial_aperture);
1567
1568	free(sc->gatt, M_AGP);
1569	bus_release_resources(dev, sc->match->driver->res_spec, sc->sc_res);
1570	agp_free_res(dev);
1571
1572	return (0);
1573}
1574
1575static int
1576agp_i810_resume(device_t dev)
1577{
1578	struct agp_i810_softc *sc;
1579	sc = device_get_softc(dev);
1580
1581	AGP_SET_APERTURE(dev, sc->initial_aperture);
1582
1583	/* Install the GATT. */
1584	bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL,
1585	sc->gatt->ag_physical | 1);
1586
1587	return (bus_generic_resume(dev));
1588}
1589
1590/**
1591 * Sets the PCI resource size of the aperture on i830-class and below chipsets,
1592 * while returning failure on later chipsets when an actual change is
1593 * requested.
1594 *
1595 * This whole function is likely bogus, as the kernel would probably need to
1596 * reconfigure the placement of the AGP aperture if a larger size is requested,
1597 * which doesn't happen currently.
1598 */
1599static int
1600agp_i810_set_aperture(device_t dev, u_int32_t aperture)
1601{
1602	struct agp_i810_softc *sc;
1603	u_int16_t miscc;
1604
1605	sc = device_get_softc(dev);
1606	/*
1607	 * Double check for sanity.
1608	 */
1609	if (aperture != 32 * 1024 * 1024 && aperture != 64 * 1024 * 1024) {
1610		device_printf(dev, "bad aperture size %d\n", aperture);
1611		return (EINVAL);
1612	}
1613
1614	miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
1615	miscc &= ~AGP_I810_MISCC_WINSIZE;
1616	if (aperture == 32 * 1024 * 1024)
1617		miscc |= AGP_I810_MISCC_WINSIZE_32;
1618	else
1619		miscc |= AGP_I810_MISCC_WINSIZE_64;
1620
1621	pci_write_config(sc->bdev, AGP_I810_MISCC, miscc, 2);
1622	return (0);
1623}
1624
1625static int
1626agp_i830_set_aperture(device_t dev, u_int32_t aperture)
1627{
1628	struct agp_i810_softc *sc;
1629	u_int16_t gcc1;
1630
1631	sc = device_get_softc(dev);
1632
1633	if (aperture != 64 * 1024 * 1024 &&
1634	    aperture != 128 * 1024 * 1024) {
1635		device_printf(dev, "bad aperture size %d\n", aperture);
1636		return (EINVAL);
1637	}
1638	gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
1639	gcc1 &= ~AGP_I830_GCC1_GMASIZE;
1640	if (aperture == 64 * 1024 * 1024)
1641		gcc1 |= AGP_I830_GCC1_GMASIZE_64;
1642	else
1643		gcc1 |= AGP_I830_GCC1_GMASIZE_128;
1644
1645	pci_write_config(sc->bdev, AGP_I830_GCC1, gcc1, 2);
1646	return (0);
1647}
1648
1649static int
1650agp_i915_set_aperture(device_t dev, u_int32_t aperture)
1651{
1652
1653	return (agp_generic_set_aperture(dev, aperture));
1654}
1655
1656static int
1657agp_i810_method_set_aperture(device_t dev, u_int32_t aperture)
1658{
1659	struct agp_i810_softc *sc;
1660
1661	sc = device_get_softc(dev);
1662	return (sc->match->driver->set_aperture(dev, aperture));
1663}
1664
1665/**
1666 * Writes a GTT entry mapping the page at the given offset from the
1667 * beginning of the aperture to the given physical address.  Setup the
1668 * caching mode according to flags.
1669 *
1670 * For gen 1, 2 and 3, GTT start is located at AGP_I810_GTT offset
1671 * from corresponding BAR start. For gen 4, offset is 512KB +
1672 * AGP_I810_GTT, for gen 5 and 6 it is 2MB + AGP_I810_GTT.
1673 *
1674 * Also, the bits of the physical page address above 4GB needs to be
1675 * placed into bits 40-32 of PTE.
1676 */
1677static void
1678agp_i810_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
1679    int flags)
1680{
1681	uint32_t pte;
1682
1683	pte = (u_int32_t)physical | I810_PTE_VALID;
1684	if (flags == AGP_DCACHE_MEMORY)
1685		pte |= I810_PTE_LOCAL;
1686	else if (flags == AGP_USER_CACHED_MEMORY)
1687		pte |= I830_PTE_SYSTEM_CACHED;
1688	agp_i810_write_gtt(dev, index, pte);
1689}
1690
1691static void
1692agp_i810_write_gtt(device_t dev, u_int index, uint32_t pte)
1693{
1694	struct agp_i810_softc *sc;
1695
1696	sc = device_get_softc(dev);
1697	bus_write_4(sc->sc_res[0], AGP_I810_GTT + index * 4, pte);
1698	CTR2(KTR_AGP_I810, "810_pte %x %x", index, pte);
1699}
1700
1701static void
1702agp_i830_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
1703    int flags)
1704{
1705	uint32_t pte;
1706
1707	pte = (u_int32_t)physical | I810_PTE_VALID;
1708	if (flags == AGP_USER_CACHED_MEMORY)
1709		pte |= I830_PTE_SYSTEM_CACHED;
1710	agp_i810_write_gtt(dev, index, pte);
1711}
1712
1713static void
1714agp_i915_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
1715    int flags)
1716{
1717	uint32_t pte;
1718
1719	pte = (u_int32_t)physical | I810_PTE_VALID;
1720	if (flags == AGP_USER_CACHED_MEMORY)
1721		pte |= I830_PTE_SYSTEM_CACHED;
1722	pte |= (physical & 0x0000000f00000000ull) >> 28;
1723	agp_i915_write_gtt(dev, index, pte);
1724}
1725
1726static void
1727agp_i915_write_gtt(device_t dev, u_int index, uint32_t pte)
1728{
1729	struct agp_i810_softc *sc;
1730
1731	sc = device_get_softc(dev);
1732	bus_write_4(sc->sc_res[1], index * 4, pte);
1733	CTR2(KTR_AGP_I810, "915_pte %x %x", index, pte);
1734}
1735
1736static void
1737agp_i965_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
1738    int flags)
1739{
1740	uint32_t pte;
1741
1742	pte = (u_int32_t)physical | I810_PTE_VALID;
1743	if (flags == AGP_USER_CACHED_MEMORY)
1744		pte |= I830_PTE_SYSTEM_CACHED;
1745	pte |= (physical & 0x0000000f00000000ull) >> 28;
1746	agp_i965_write_gtt(dev, index, pte);
1747}
1748
1749static void
1750agp_i965_write_gtt(device_t dev, u_int index, uint32_t pte)
1751{
1752	struct agp_i810_softc *sc;
1753
1754	sc = device_get_softc(dev);
1755	bus_write_4(sc->sc_res[0], index * 4 + (512 * 1024), pte);
1756	CTR2(KTR_AGP_I810, "965_pte %x %x", index, pte);
1757}
1758
1759static void
1760agp_g4x_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
1761    int flags)
1762{
1763	uint32_t pte;
1764
1765	pte = (u_int32_t)physical | I810_PTE_VALID;
1766	if (flags == AGP_USER_CACHED_MEMORY)
1767		pte |= I830_PTE_SYSTEM_CACHED;
1768	pte |= (physical & 0x0000000f00000000ull) >> 28;
1769	agp_g4x_write_gtt(dev, index, pte);
1770}
1771
1772static void
1773agp_g4x_write_gtt(device_t dev, u_int index, uint32_t pte)
1774{
1775	struct agp_i810_softc *sc;
1776
1777	sc = device_get_softc(dev);
1778	bus_write_4(sc->sc_res[0], index * 4 + (2 * 1024 * 1024), pte);
1779	CTR2(KTR_AGP_I810, "g4x_pte %x %x", index, pte);
1780}
1781
1782static void
1783agp_sb_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
1784    int flags)
1785{
1786	int type_mask, gfdt;
1787	uint32_t pte;
1788
1789	pte = (u_int32_t)physical | I810_PTE_VALID;
1790	type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT;
1791	gfdt = (flags & AGP_USER_CACHED_MEMORY_GFDT) != 0 ? GEN6_PTE_GFDT : 0;
1792
1793	if (type_mask == AGP_USER_MEMORY)
1794		pte |= GEN6_PTE_UNCACHED;
1795	else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC)
1796		pte |= GEN6_PTE_LLC_MLC | gfdt;
1797	else
1798		pte |= GEN6_PTE_LLC | gfdt;
1799
1800	pte |= (physical & 0x000000ff00000000ull) >> 28;
1801	agp_sb_write_gtt(dev, index, pte);
1802}
1803
1804static void
1805agp_sb_write_gtt(device_t dev, u_int index, uint32_t pte)
1806{
1807	struct agp_i810_softc *sc;
1808
1809	sc = device_get_softc(dev);
1810	bus_write_4(sc->sc_res[0], index * 4 + (2 * 1024 * 1024), pte);
1811	CTR2(KTR_AGP_I810, "sb_pte %x %x", index, pte);
1812}
1813
1814static int
1815agp_i810_bind_page(device_t dev, vm_offset_t offset, vm_offset_t physical)
1816{
1817	struct agp_i810_softc *sc = device_get_softc(dev);
1818	u_int index;
1819
1820	if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) {
1821		device_printf(dev, "failed: offset is 0x%08jx, "
1822		    "shift is %d, entries is %d\n", (intmax_t)offset,
1823		    AGP_PAGE_SHIFT, sc->gatt->ag_entries);
1824		return (EINVAL);
1825	}
1826	index = offset >> AGP_PAGE_SHIFT;
1827	if (sc->stolen != 0 && index < sc->stolen) {
1828		device_printf(dev, "trying to bind into stolen memory\n");
1829		return (EINVAL);
1830	}
1831	sc->match->driver->install_gtt_pte(dev, index, physical, 0);
1832	return (0);
1833}
1834
1835static int
1836agp_i810_unbind_page(device_t dev, vm_offset_t offset)
1837{
1838	struct agp_i810_softc *sc;
1839	u_int index;
1840
1841	sc = device_get_softc(dev);
1842	if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
1843		return (EINVAL);
1844	index = offset >> AGP_PAGE_SHIFT;
1845	if (sc->stolen != 0 && index < sc->stolen) {
1846		device_printf(dev, "trying to unbind from stolen memory\n");
1847		return (EINVAL);
1848	}
1849	sc->match->driver->install_gtt_pte(dev, index, 0, 0);
1850	return (0);
1851}
1852
1853static u_int32_t
1854agp_i810_read_gtt_pte(device_t dev, u_int index)
1855{
1856	struct agp_i810_softc *sc;
1857	u_int32_t pte;
1858
1859	sc = device_get_softc(dev);
1860	pte = bus_read_4(sc->sc_res[0], AGP_I810_GTT + index * 4);
1861	return (pte);
1862}
1863
1864static u_int32_t
1865agp_i915_read_gtt_pte(device_t dev, u_int index)
1866{
1867	struct agp_i810_softc *sc;
1868	u_int32_t pte;
1869
1870	sc = device_get_softc(dev);
1871	pte = bus_read_4(sc->sc_res[1], index * 4);
1872	return (pte);
1873}
1874
1875static u_int32_t
1876agp_i965_read_gtt_pte(device_t dev, u_int index)
1877{
1878	struct agp_i810_softc *sc;
1879	u_int32_t pte;
1880
1881	sc = device_get_softc(dev);
1882	pte = bus_read_4(sc->sc_res[0], index * 4 + (512 * 1024));
1883	return (pte);
1884}
1885
1886static u_int32_t
1887agp_g4x_read_gtt_pte(device_t dev, u_int index)
1888{
1889	struct agp_i810_softc *sc;
1890	u_int32_t pte;
1891
1892	sc = device_get_softc(dev);
1893	pte = bus_read_4(sc->sc_res[0], index * 4 + (2 * 1024 * 1024));
1894	return (pte);
1895}
1896
1897static vm_paddr_t
1898agp_i810_read_gtt_pte_paddr(device_t dev, u_int index)
1899{
1900	struct agp_i810_softc *sc;
1901	u_int32_t pte;
1902	vm_paddr_t res;
1903
1904	sc = device_get_softc(dev);
1905	pte = sc->match->driver->read_gtt_pte(dev, index);
1906	res = pte & ~PAGE_MASK;
1907	return (res);
1908}
1909
1910static vm_paddr_t
1911agp_i915_read_gtt_pte_paddr(device_t dev, u_int index)
1912{
1913	struct agp_i810_softc *sc;
1914	u_int32_t pte;
1915	vm_paddr_t res;
1916
1917	sc = device_get_softc(dev);
1918	pte = sc->match->driver->read_gtt_pte(dev, index);
1919	res = (pte & ~PAGE_MASK) | ((pte & 0xf0) << 28);
1920	return (res);
1921}
1922
1923static vm_paddr_t
1924agp_sb_read_gtt_pte_paddr(device_t dev, u_int index)
1925{
1926	struct agp_i810_softc *sc;
1927	u_int32_t pte;
1928	vm_paddr_t res;
1929
1930	sc = device_get_softc(dev);
1931	pte = sc->match->driver->read_gtt_pte(dev, index);
1932	res = (pte & ~PAGE_MASK) | ((pte & 0xff0) << 28);
1933	return (res);
1934}
1935
1936/*
1937 * Writing via memory mapped registers already flushes all TLBs.
1938 */
1939static void
1940agp_i810_flush_tlb(device_t dev)
1941{
1942}
1943
1944static int
1945agp_i810_enable(device_t dev, u_int32_t mode)
1946{
1947
1948	return (0);
1949}
1950
1951static struct agp_memory *
1952agp_i810_alloc_memory(device_t dev, int type, vm_size_t size)
1953{
1954	struct agp_i810_softc *sc;
1955	struct agp_memory *mem;
1956	vm_page_t m;
1957
1958	sc = device_get_softc(dev);
1959
1960	if ((size & (AGP_PAGE_SIZE - 1)) != 0 ||
1961	    sc->agp.as_allocated + size > sc->agp.as_maxmem)
1962		return (0);
1963
1964	if (type == 1) {
1965		/*
1966		 * Mapping local DRAM into GATT.
1967		 */
1968		if (sc->match->driver->chiptype != CHIP_I810)
1969			return (0);
1970		if (size != sc->dcache_size)
1971			return (0);
1972	} else if (type == 2) {
1973		/*
1974		 * Type 2 is the contiguous physical memory type, that hands
1975		 * back a physical address.  This is used for cursors on i810.
1976		 * Hand back as many single pages with physical as the user
1977		 * wants, but only allow one larger allocation (ARGB cursor)
1978		 * for simplicity.
1979		 */
1980		if (size != AGP_PAGE_SIZE) {
1981			if (sc->argb_cursor != NULL)
1982				return (0);
1983
1984			/* Allocate memory for ARGB cursor, if we can. */
1985			sc->argb_cursor = contigmalloc(size, M_AGP,
1986			   0, 0, ~0, PAGE_SIZE, 0);
1987			if (sc->argb_cursor == NULL)
1988				return (0);
1989		}
1990	}
1991
1992	mem = malloc(sizeof *mem, M_AGP, M_WAITOK);
1993	mem->am_id = sc->agp.as_nextid++;
1994	mem->am_size = size;
1995	mem->am_type = type;
1996	if (type != 1 && (type != 2 || size == AGP_PAGE_SIZE))
1997		mem->am_obj = vm_object_allocate(OBJT_DEFAULT,
1998		    atop(round_page(size)));
1999	else
2000		mem->am_obj = 0;
2001
2002	if (type == 2) {
2003		if (size == AGP_PAGE_SIZE) {
2004			/*
2005			 * Allocate and wire down the page now so that we can
2006			 * get its physical address.
2007			 */
2008			VM_OBJECT_WLOCK(mem->am_obj);
2009			m = vm_page_grab(mem->am_obj, 0, VM_ALLOC_NOBUSY |
2010			    VM_ALLOC_WIRED | VM_ALLOC_ZERO);
2011			VM_OBJECT_WUNLOCK(mem->am_obj);
2012			mem->am_physical = VM_PAGE_TO_PHYS(m);
2013		} else {
2014			/* Our allocation is already nicely wired down for us.
2015			 * Just grab the physical address.
2016			 */
2017			mem->am_physical = vtophys(sc->argb_cursor);
2018		}
2019	} else
2020		mem->am_physical = 0;
2021
2022	mem->am_offset = 0;
2023	mem->am_is_bound = 0;
2024	TAILQ_INSERT_TAIL(&sc->agp.as_memory, mem, am_link);
2025	sc->agp.as_allocated += size;
2026
2027	return (mem);
2028}
2029
2030static int
2031agp_i810_free_memory(device_t dev, struct agp_memory *mem)
2032{
2033	struct agp_i810_softc *sc;
2034	vm_page_t m;
2035
2036	if (mem->am_is_bound)
2037		return (EBUSY);
2038
2039	sc = device_get_softc(dev);
2040
2041	if (mem->am_type == 2) {
2042		if (mem->am_size == AGP_PAGE_SIZE) {
2043			/*
2044			 * Unwire the page which we wired in alloc_memory.
2045			 */
2046			VM_OBJECT_WLOCK(mem->am_obj);
2047			m = vm_page_lookup(mem->am_obj, 0);
2048			vm_page_lock(m);
2049			vm_page_unwire(m, PQ_INACTIVE);
2050			vm_page_unlock(m);
2051			VM_OBJECT_WUNLOCK(mem->am_obj);
2052		} else {
2053			contigfree(sc->argb_cursor, mem->am_size, M_AGP);
2054			sc->argb_cursor = NULL;
2055		}
2056	}
2057
2058	sc->agp.as_allocated -= mem->am_size;
2059	TAILQ_REMOVE(&sc->agp.as_memory, mem, am_link);
2060	if (mem->am_obj)
2061		vm_object_deallocate(mem->am_obj);
2062	free(mem, M_AGP);
2063	return (0);
2064}
2065
2066static int
2067agp_i810_bind_memory(device_t dev, struct agp_memory *mem, vm_offset_t offset)
2068{
2069	struct agp_i810_softc *sc;
2070	vm_offset_t i;
2071
2072	/* Do some sanity checks first. */
2073	if ((offset & (AGP_PAGE_SIZE - 1)) != 0 ||
2074	    offset + mem->am_size > AGP_GET_APERTURE(dev)) {
2075		device_printf(dev, "binding memory at bad offset %#x\n",
2076		    (int)offset);
2077		return (EINVAL);
2078	}
2079
2080	sc = device_get_softc(dev);
2081	if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) {
2082		mtx_lock(&sc->agp.as_lock);
2083		if (mem->am_is_bound) {
2084			mtx_unlock(&sc->agp.as_lock);
2085			return (EINVAL);
2086		}
2087		/* The memory's already wired down, just stick it in the GTT. */
2088		for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
2089			sc->match->driver->install_gtt_pte(dev, (offset + i) >>
2090			    AGP_PAGE_SHIFT, mem->am_physical + i, 0);
2091		}
2092		mem->am_offset = offset;
2093		mem->am_is_bound = 1;
2094		mtx_unlock(&sc->agp.as_lock);
2095		return (0);
2096	}
2097
2098	if (mem->am_type != 1)
2099		return (agp_generic_bind_memory(dev, mem, offset));
2100
2101	/*
2102	 * Mapping local DRAM into GATT.
2103	 */
2104	if (sc->match->driver->chiptype != CHIP_I810)
2105		return (EINVAL);
2106	for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
2107		bus_write_4(sc->sc_res[0],
2108		    AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, i | 3);
2109
2110	return (0);
2111}
2112
2113static int
2114agp_i810_unbind_memory(device_t dev, struct agp_memory *mem)
2115{
2116	struct agp_i810_softc *sc;
2117	vm_offset_t i;
2118
2119	sc = device_get_softc(dev);
2120
2121	if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) {
2122		mtx_lock(&sc->agp.as_lock);
2123		if (!mem->am_is_bound) {
2124			mtx_unlock(&sc->agp.as_lock);
2125			return (EINVAL);
2126		}
2127
2128		for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
2129			sc->match->driver->install_gtt_pte(dev,
2130			    (mem->am_offset + i) >> AGP_PAGE_SHIFT, 0, 0);
2131		}
2132		mem->am_is_bound = 0;
2133		mtx_unlock(&sc->agp.as_lock);
2134		return (0);
2135	}
2136
2137	if (mem->am_type != 1)
2138		return (agp_generic_unbind_memory(dev, mem));
2139
2140	if (sc->match->driver->chiptype != CHIP_I810)
2141		return (EINVAL);
2142	for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
2143		sc->match->driver->install_gtt_pte(dev, i >> AGP_PAGE_SHIFT,
2144		    0, 0);
2145	}
2146	return (0);
2147}
2148
2149static device_method_t agp_i810_methods[] = {
2150	/* Device interface */
2151	DEVMETHOD(device_identify,	agp_i810_identify),
2152	DEVMETHOD(device_probe,		agp_i810_probe),
2153	DEVMETHOD(device_attach,	agp_i810_attach),
2154	DEVMETHOD(device_detach,	agp_i810_detach),
2155	DEVMETHOD(device_suspend,	bus_generic_suspend),
2156	DEVMETHOD(device_resume,	agp_i810_resume),
2157
2158	/* AGP interface */
2159	DEVMETHOD(agp_get_aperture,	agp_generic_get_aperture),
2160	DEVMETHOD(agp_set_aperture,	agp_i810_method_set_aperture),
2161	DEVMETHOD(agp_bind_page,	agp_i810_bind_page),
2162	DEVMETHOD(agp_unbind_page,	agp_i810_unbind_page),
2163	DEVMETHOD(agp_flush_tlb,	agp_i810_flush_tlb),
2164	DEVMETHOD(agp_enable,		agp_i810_enable),
2165	DEVMETHOD(agp_alloc_memory,	agp_i810_alloc_memory),
2166	DEVMETHOD(agp_free_memory,	agp_i810_free_memory),
2167	DEVMETHOD(agp_bind_memory,	agp_i810_bind_memory),
2168	DEVMETHOD(agp_unbind_memory,	agp_i810_unbind_memory),
2169	DEVMETHOD(agp_chipset_flush,	agp_intel_gtt_chipset_flush),
2170
2171	{ 0, 0 }
2172};
2173
2174static driver_t agp_i810_driver = {
2175	"agp",
2176	agp_i810_methods,
2177	sizeof(struct agp_i810_softc),
2178};
2179
2180static devclass_t agp_devclass;
2181
2182DRIVER_MODULE(agp_i810, vgapci, agp_i810_driver, agp_devclass, 0, 0);
2183MODULE_DEPEND(agp_i810, agp, 1, 1, 1);
2184MODULE_DEPEND(agp_i810, pci, 1, 1, 1);
2185
2186extern vm_page_t bogus_page;
2187
2188void
2189agp_intel_gtt_clear_range(device_t dev, u_int first_entry, u_int num_entries)
2190{
2191	struct agp_i810_softc *sc;
2192	u_int i;
2193
2194	sc = device_get_softc(dev);
2195	for (i = 0; i < num_entries; i++)
2196		sc->match->driver->install_gtt_pte(dev, first_entry + i,
2197		    VM_PAGE_TO_PHYS(bogus_page), 0);
2198	sc->match->driver->read_gtt_pte(dev, first_entry + num_entries - 1);
2199}
2200
2201void
2202agp_intel_gtt_insert_pages(device_t dev, u_int first_entry, u_int num_entries,
2203    vm_page_t *pages, u_int flags)
2204{
2205	struct agp_i810_softc *sc;
2206	u_int i;
2207
2208	sc = device_get_softc(dev);
2209	for (i = 0; i < num_entries; i++) {
2210		MPASS(pages[i]->valid == VM_PAGE_BITS_ALL);
2211		MPASS(pages[i]->wire_count > 0);
2212		sc->match->driver->install_gtt_pte(dev, first_entry + i,
2213		    VM_PAGE_TO_PHYS(pages[i]), flags);
2214	}
2215	sc->match->driver->read_gtt_pte(dev, first_entry + num_entries - 1);
2216}
2217
2218struct intel_gtt
2219agp_intel_gtt_get(device_t dev)
2220{
2221	struct agp_i810_softc *sc;
2222	struct intel_gtt res;
2223
2224	sc = device_get_softc(dev);
2225	res.stolen_size = sc->stolen_size;
2226	res.gtt_total_entries = sc->gtt_total_entries;
2227	res.gtt_mappable_entries = sc->gtt_mappable_entries;
2228	res.do_idle_maps = 0;
2229	res.scratch_page_dma = VM_PAGE_TO_PHYS(bogus_page);
2230	return (res);
2231}
2232
2233static int
2234agp_i810_chipset_flush_setup(device_t dev)
2235{
2236
2237	return (0);
2238}
2239
2240static void
2241agp_i810_chipset_flush_teardown(device_t dev)
2242{
2243
2244	/* Nothing to do. */
2245}
2246
2247static void
2248agp_i810_chipset_flush(device_t dev)
2249{
2250
2251	/* Nothing to do. */
2252}
2253
2254static void
2255agp_i830_chipset_flush(device_t dev)
2256{
2257	struct agp_i810_softc *sc;
2258	uint32_t hic;
2259	int i;
2260
2261	sc = device_get_softc(dev);
2262	pmap_invalidate_cache();
2263	hic = bus_read_4(sc->sc_res[0], AGP_I830_HIC);
2264	bus_write_4(sc->sc_res[0], AGP_I830_HIC, hic | (1U << 31));
2265	for (i = 0; i < 20000 /* 1 sec */; i++) {
2266		hic = bus_read_4(sc->sc_res[0], AGP_I830_HIC);
2267		if ((hic & (1U << 31)) == 0)
2268			break;
2269		DELAY(50);
2270	}
2271}
2272
2273static int
2274agp_i915_chipset_flush_alloc_page(device_t dev, uint64_t start, uint64_t end)
2275{
2276	struct agp_i810_softc *sc;
2277	device_t vga;
2278
2279	sc = device_get_softc(dev);
2280	vga = device_get_parent(dev);
2281	sc->sc_flush_page_rid = 100;
2282	sc->sc_flush_page_res = BUS_ALLOC_RESOURCE(device_get_parent(vga), dev,
2283	    SYS_RES_MEMORY, &sc->sc_flush_page_rid, start, end, PAGE_SIZE,
2284	    RF_ACTIVE);
2285	if (sc->sc_flush_page_res == NULL) {
2286		device_printf(dev, "Failed to allocate flush page at 0x%jx\n",
2287		    (uintmax_t)start);
2288		return (EINVAL);
2289	}
2290	sc->sc_flush_page_vaddr = rman_get_virtual(sc->sc_flush_page_res);
2291	if (bootverbose) {
2292		device_printf(dev, "Allocated flush page phys 0x%jx virt %p\n",
2293		    (uintmax_t)rman_get_start(sc->sc_flush_page_res),
2294		    sc->sc_flush_page_vaddr);
2295	}
2296	return (0);
2297}
2298
2299static void
2300agp_i915_chipset_flush_free_page(device_t dev)
2301{
2302	struct agp_i810_softc *sc;
2303	device_t vga;
2304
2305	sc = device_get_softc(dev);
2306	vga = device_get_parent(dev);
2307	if (sc->sc_flush_page_res == NULL)
2308		return;
2309	BUS_DEACTIVATE_RESOURCE(device_get_parent(vga), dev, SYS_RES_MEMORY,
2310	    sc->sc_flush_page_rid, sc->sc_flush_page_res);
2311	BUS_RELEASE_RESOURCE(device_get_parent(vga), dev, SYS_RES_MEMORY,
2312	    sc->sc_flush_page_rid, sc->sc_flush_page_res);
2313}
2314
2315static int
2316agp_i915_chipset_flush_setup(device_t dev)
2317{
2318	struct agp_i810_softc *sc;
2319	uint32_t temp;
2320	int error;
2321
2322	sc = device_get_softc(dev);
2323	temp = pci_read_config(sc->bdev, AGP_I915_IFPADDR, 4);
2324	if ((temp & 1) != 0) {
2325		temp &= ~1;
2326		if (bootverbose)
2327			device_printf(dev,
2328			    "Found already configured flush page at 0x%jx\n",
2329			    (uintmax_t)temp);
2330		sc->sc_bios_allocated_flush_page = 1;
2331		/*
2332		 * In the case BIOS initialized the flush pointer (?)
2333		 * register, expect that BIOS also set up the resource
2334		 * for the page.
2335		 */
2336		error = agp_i915_chipset_flush_alloc_page(dev, temp,
2337		    temp + PAGE_SIZE - 1);
2338		if (error != 0)
2339			return (error);
2340	} else {
2341		sc->sc_bios_allocated_flush_page = 0;
2342		error = agp_i915_chipset_flush_alloc_page(dev, 0, 0xffffffff);
2343		if (error != 0)
2344			return (error);
2345		temp = rman_get_start(sc->sc_flush_page_res);
2346		pci_write_config(sc->bdev, AGP_I915_IFPADDR, temp | 1, 4);
2347	}
2348	return (0);
2349}
2350
2351static void
2352agp_i915_chipset_flush_teardown(device_t dev)
2353{
2354	struct agp_i810_softc *sc;
2355	uint32_t temp;
2356
2357	sc = device_get_softc(dev);
2358	if (sc->sc_flush_page_res == NULL)
2359		return;
2360	if (!sc->sc_bios_allocated_flush_page) {
2361		temp = pci_read_config(sc->bdev, AGP_I915_IFPADDR, 4);
2362		temp &= ~1;
2363		pci_write_config(sc->bdev, AGP_I915_IFPADDR, temp, 4);
2364	}
2365	agp_i915_chipset_flush_free_page(dev);
2366}
2367
2368static int
2369agp_i965_chipset_flush_setup(device_t dev)
2370{
2371	struct agp_i810_softc *sc;
2372	uint64_t temp;
2373	uint32_t temp_hi, temp_lo;
2374	int error;
2375
2376	sc = device_get_softc(dev);
2377
2378	temp_hi = pci_read_config(sc->bdev, AGP_I965_IFPADDR + 4, 4);
2379	temp_lo = pci_read_config(sc->bdev, AGP_I965_IFPADDR, 4);
2380
2381	if ((temp_lo & 1) != 0) {
2382		temp = ((uint64_t)temp_hi << 32) | (temp_lo & ~1);
2383		if (bootverbose)
2384			device_printf(dev,
2385			    "Found already configured flush page at 0x%jx\n",
2386			    (uintmax_t)temp);
2387		sc->sc_bios_allocated_flush_page = 1;
2388		/*
2389		 * In the case BIOS initialized the flush pointer (?)
2390		 * register, expect that BIOS also set up the resource
2391		 * for the page.
2392		 */
2393		error = agp_i915_chipset_flush_alloc_page(dev, temp,
2394		    temp + PAGE_SIZE - 1);
2395		if (error != 0)
2396			return (error);
2397	} else {
2398		sc->sc_bios_allocated_flush_page = 0;
2399		error = agp_i915_chipset_flush_alloc_page(dev, 0, ~0);
2400		if (error != 0)
2401			return (error);
2402		temp = rman_get_start(sc->sc_flush_page_res);
2403		pci_write_config(sc->bdev, AGP_I965_IFPADDR + 4,
2404		    (temp >> 32) & UINT32_MAX, 4);
2405		pci_write_config(sc->bdev, AGP_I965_IFPADDR,
2406		    (temp & UINT32_MAX) | 1, 4);
2407	}
2408	return (0);
2409}
2410
2411static void
2412agp_i965_chipset_flush_teardown(device_t dev)
2413{
2414	struct agp_i810_softc *sc;
2415	uint32_t temp_lo;
2416
2417	sc = device_get_softc(dev);
2418	if (sc->sc_flush_page_res == NULL)
2419		return;
2420	if (!sc->sc_bios_allocated_flush_page) {
2421		temp_lo = pci_read_config(sc->bdev, AGP_I965_IFPADDR, 4);
2422		temp_lo &= ~1;
2423		pci_write_config(sc->bdev, AGP_I965_IFPADDR, temp_lo, 4);
2424	}
2425	agp_i915_chipset_flush_free_page(dev);
2426}
2427
2428static void
2429agp_i915_chipset_flush(device_t dev)
2430{
2431	struct agp_i810_softc *sc;
2432
2433	sc = device_get_softc(dev);
2434	*(uint32_t *)sc->sc_flush_page_vaddr = 1;
2435}
2436
2437int
2438agp_intel_gtt_chipset_flush(device_t dev)
2439{
2440	struct agp_i810_softc *sc;
2441
2442	sc = device_get_softc(dev);
2443	sc->match->driver->chipset_flush(dev);
2444	return (0);
2445}
2446
2447void
2448agp_intel_gtt_unmap_memory(device_t dev, struct sglist *sg_list)
2449{
2450}
2451
2452int
2453agp_intel_gtt_map_memory(device_t dev, vm_page_t *pages, u_int num_entries,
2454    struct sglist **sg_list)
2455{
2456	struct agp_i810_softc *sc;
2457	struct sglist *sg;
2458	int i;
2459#if 0
2460	int error;
2461	bus_dma_tag_t dmat;
2462#endif
2463
2464	if (*sg_list != NULL)
2465		return (0);
2466	sc = device_get_softc(dev);
2467	sg = sglist_alloc(num_entries, M_WAITOK /* XXXKIB */);
2468	for (i = 0; i < num_entries; i++) {
2469		sg->sg_segs[i].ss_paddr = VM_PAGE_TO_PHYS(pages[i]);
2470		sg->sg_segs[i].ss_len = PAGE_SIZE;
2471	}
2472
2473#if 0
2474	error = bus_dma_tag_create(bus_get_dma_tag(dev),
2475	    1 /* alignment */, 0 /* boundary */,
2476	    1ULL << sc->match->busdma_addr_mask_sz /* lowaddr */,
2477	    BUS_SPACE_MAXADDR /* highaddr */,
2478            NULL /* filtfunc */, NULL /* filtfuncarg */,
2479	    BUS_SPACE_MAXADDR /* maxsize */,
2480	    BUS_SPACE_UNRESTRICTED /* nsegments */,
2481	    BUS_SPACE_MAXADDR /* maxsegsz */,
2482	    0 /* flags */, NULL /* lockfunc */, NULL /* lockfuncarg */,
2483	    &dmat);
2484	if (error != 0) {
2485		sglist_free(sg);
2486		return (error);
2487	}
2488	/* XXXKIB */
2489#endif
2490	*sg_list = sg;
2491	return (0);
2492}
2493
2494void
2495agp_intel_gtt_insert_sg_entries(device_t dev, struct sglist *sg_list,
2496    u_int first_entry, u_int flags)
2497{
2498	struct agp_i810_softc *sc;
2499	vm_paddr_t spaddr;
2500	size_t slen;
2501	u_int i, j;
2502
2503	sc = device_get_softc(dev);
2504	for (i = j = 0; j < sg_list->sg_nseg; j++) {
2505		spaddr = sg_list->sg_segs[i].ss_paddr;
2506		slen = sg_list->sg_segs[i].ss_len;
2507		for (; slen > 0; i++) {
2508			sc->match->driver->install_gtt_pte(dev, first_entry + i,
2509			    spaddr, flags);
2510			spaddr += AGP_PAGE_SIZE;
2511			slen -= AGP_PAGE_SIZE;
2512		}
2513	}
2514	sc->match->driver->read_gtt_pte(dev, first_entry + i - 1);
2515}
2516
2517void
2518intel_gtt_clear_range(u_int first_entry, u_int num_entries)
2519{
2520
2521	agp_intel_gtt_clear_range(intel_agp, first_entry, num_entries);
2522}
2523
2524void
2525intel_gtt_insert_pages(u_int first_entry, u_int num_entries, vm_page_t *pages,
2526    u_int flags)
2527{
2528
2529	agp_intel_gtt_insert_pages(intel_agp, first_entry, num_entries,
2530	    pages, flags);
2531}
2532
2533struct intel_gtt
2534intel_gtt_get(void)
2535{
2536
2537	return (agp_intel_gtt_get(intel_agp));
2538}
2539
2540int
2541intel_gtt_chipset_flush(void)
2542{
2543
2544	return (agp_intel_gtt_chipset_flush(intel_agp));
2545}
2546
2547void
2548intel_gtt_unmap_memory(struct sglist *sg_list)
2549{
2550
2551	agp_intel_gtt_unmap_memory(intel_agp, sg_list);
2552}
2553
2554int
2555intel_gtt_map_memory(vm_page_t *pages, u_int num_entries,
2556    struct sglist **sg_list)
2557{
2558
2559	return (agp_intel_gtt_map_memory(intel_agp, pages, num_entries,
2560	    sg_list));
2561}
2562
2563void
2564intel_gtt_insert_sg_entries(struct sglist *sg_list, u_int first_entry,
2565    u_int flags)
2566{
2567
2568	agp_intel_gtt_insert_sg_entries(intel_agp, sg_list, first_entry, flags);
2569}
2570
2571device_t
2572intel_gtt_get_bridge_device(void)
2573{
2574	struct agp_i810_softc *sc;
2575
2576	sc = device_get_softc(intel_agp);
2577	return (sc->bdev);
2578}
2579
2580vm_paddr_t
2581intel_gtt_read_pte_paddr(u_int entry)
2582{
2583	struct agp_i810_softc *sc;
2584
2585	sc = device_get_softc(intel_agp);
2586	return (sc->match->driver->read_gtt_pte_paddr(intel_agp, entry));
2587}
2588
2589u_int32_t
2590intel_gtt_read_pte(u_int entry)
2591{
2592	struct agp_i810_softc *sc;
2593
2594	sc = device_get_softc(intel_agp);
2595	return (sc->match->driver->read_gtt_pte(intel_agp, entry));
2596}
2597
2598void
2599intel_gtt_write(u_int entry, uint32_t val)
2600{
2601	struct agp_i810_softc *sc;
2602
2603	sc = device_get_softc(intel_agp);
2604	return (sc->match->driver->write_gtt(intel_agp, entry, val));
2605}
2606