163010Sdfr/*-
263010Sdfr * Copyright (c) 2000 Doug Rabson
363010Sdfr * Copyright (c) 2000 Ruslan Ermilov
4236926Skib * Copyright (c) 2011 The FreeBSD Foundation
563010Sdfr * All rights reserved.
663010Sdfr *
7236926Skib * Portions of this software were developed by Konstantin Belousov
8236926Skib * under sponsorship from the FreeBSD Foundation.
9236926Skib *
1063010Sdfr * Redistribution and use in source and binary forms, with or without
1163010Sdfr * modification, are permitted provided that the following conditions
1263010Sdfr * are met:
1363010Sdfr * 1. Redistributions of source code must retain the above copyright
1463010Sdfr *    notice, this list of conditions and the following disclaimer.
1563010Sdfr * 2. Redistributions in binary form must reproduce the above copyright
1663010Sdfr *    notice, this list of conditions and the following disclaimer in the
1763010Sdfr *    documentation and/or other materials provided with the distribution.
1863010Sdfr *
1963010Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2063010Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2163010Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2263010Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2363010Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2463010Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2563010Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2663010Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2763010Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2863010Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2963010Sdfr * SUCH DAMAGE.
3063010Sdfr */
3163010Sdfr
32103243Sanholt/*
33103243Sanholt * Fixes for 830/845G support: David Dawes <dawes@xfree86.org>
34110785Sanholt * 852GM/855GM/865G support added by David Dawes <dawes@xfree86.org>
35236926Skib *
36236926Skib * This is generic Intel GTT handling code, morphed from the AGP
37236926Skib * bridge code.
38103243Sanholt */
39103243Sanholt
40116192Sobrien#include <sys/cdefs.h>
41116192Sobrien__FBSDID("$FreeBSD$");
42116192Sobrien
4363010Sdfr#include "opt_bus.h"
4463010Sdfr
45236926Skib#if 0
46236926Skib#define	KTR_AGP_I810	KTR_DEV
47236926Skib#else
48236926Skib#define	KTR_AGP_I810	0
49236926Skib#endif
50236926Skib
5163010Sdfr#include <sys/param.h>
5263010Sdfr#include <sys/systm.h>
5363010Sdfr#include <sys/malloc.h>
5463010Sdfr#include <sys/kernel.h>
55236926Skib#include <sys/ktr.h>
56129878Sphk#include <sys/module.h>
5763010Sdfr#include <sys/bus.h>
5863010Sdfr#include <sys/lock.h>
5976827Salfred#include <sys/mutex.h>
6079339Sjhb#include <sys/proc.h>
6163010Sdfr
62173573Sjhb#include <dev/agp/agppriv.h>
63173573Sjhb#include <dev/agp/agpreg.h>
64236926Skib#include <dev/agp/agp_i810.h>
65119288Simp#include <dev/pci/pcivar.h>
66119288Simp#include <dev/pci/pcireg.h>
67236926Skib#include <dev/pci/pci_private.h>
6863010Sdfr
6963010Sdfr#include <vm/vm.h>
70240238Skib#include <vm/vm_param.h>
7163010Sdfr#include <vm/vm_object.h>
7263010Sdfr#include <vm/vm_page.h>
7363010Sdfr#include <vm/vm_pageout.h>
7463010Sdfr#include <vm/pmap.h>
7563010Sdfr
7663010Sdfr#include <machine/bus.h>
7763010Sdfr#include <machine/resource.h>
78171433Sanholt#include <machine/md_var.h>
7963010Sdfr#include <sys/rman.h>
8063010Sdfr
8163010SdfrMALLOC_DECLARE(M_AGP);
8263010Sdfr
83236926Skibstruct agp_i810_match;
84236926Skib
85236926Skibstatic int agp_i810_check_active(device_t bridge_dev);
86236926Skibstatic int agp_i830_check_active(device_t bridge_dev);
87236926Skibstatic int agp_i915_check_active(device_t bridge_dev);
88236926Skibstatic int agp_sb_check_active(device_t bridge_dev);
89236926Skib
90236926Skibstatic void agp_82852_set_desc(device_t dev,
91236926Skib    const struct agp_i810_match *match);
92236926Skibstatic void agp_i810_set_desc(device_t dev, const struct agp_i810_match *match);
93236926Skib
94236926Skibstatic void agp_i810_dump_regs(device_t dev);
95236926Skibstatic void agp_i830_dump_regs(device_t dev);
96236926Skibstatic void agp_i855_dump_regs(device_t dev);
97236926Skibstatic void agp_i915_dump_regs(device_t dev);
98236926Skibstatic void agp_i965_dump_regs(device_t dev);
99236926Skibstatic void agp_sb_dump_regs(device_t dev);
100236926Skib
101236926Skibstatic int agp_i810_get_stolen_size(device_t dev);
102236926Skibstatic int agp_i830_get_stolen_size(device_t dev);
103236926Skibstatic int agp_i915_get_stolen_size(device_t dev);
104236926Skibstatic int agp_sb_get_stolen_size(device_t dev);
105236926Skib
106236926Skibstatic int agp_i810_get_gtt_mappable_entries(device_t dev);
107236926Skibstatic int agp_i830_get_gtt_mappable_entries(device_t dev);
108236926Skibstatic int agp_i915_get_gtt_mappable_entries(device_t dev);
109236926Skib
110236926Skibstatic int agp_i810_get_gtt_total_entries(device_t dev);
111236926Skibstatic int agp_i965_get_gtt_total_entries(device_t dev);
112236926Skibstatic int agp_gen5_get_gtt_total_entries(device_t dev);
113236926Skibstatic int agp_sb_get_gtt_total_entries(device_t dev);
114236926Skib
115236926Skibstatic int agp_i810_install_gatt(device_t dev);
116236926Skibstatic int agp_i830_install_gatt(device_t dev);
117236926Skib
118236926Skibstatic void agp_i810_deinstall_gatt(device_t dev);
119236926Skibstatic void agp_i830_deinstall_gatt(device_t dev);
120236926Skib
121236926Skibstatic void agp_i810_install_gtt_pte(device_t dev, u_int index,
122236926Skib    vm_offset_t physical, int flags);
123236926Skibstatic void agp_i830_install_gtt_pte(device_t dev, u_int index,
124236926Skib    vm_offset_t physical, int flags);
125236926Skibstatic void agp_i915_install_gtt_pte(device_t dev, u_int index,
126236926Skib    vm_offset_t physical, int flags);
127236926Skibstatic void agp_i965_install_gtt_pte(device_t dev, u_int index,
128236926Skib    vm_offset_t physical, int flags);
129236926Skibstatic void agp_g4x_install_gtt_pte(device_t dev, u_int index,
130236926Skib    vm_offset_t physical, int flags);
131236926Skibstatic void agp_sb_install_gtt_pte(device_t dev, u_int index,
132236926Skib    vm_offset_t physical, int flags);
133236926Skib
134236926Skibstatic void agp_i810_write_gtt(device_t dev, u_int index, uint32_t pte);
135236926Skibstatic void agp_i915_write_gtt(device_t dev, u_int index, uint32_t pte);
136236926Skibstatic void agp_i965_write_gtt(device_t dev, u_int index, uint32_t pte);
137236926Skibstatic void agp_g4x_write_gtt(device_t dev, u_int index, uint32_t pte);
138236926Skibstatic void agp_sb_write_gtt(device_t dev, u_int index, uint32_t pte);
139236926Skib
140236926Skibstatic u_int32_t agp_i810_read_gtt_pte(device_t dev, u_int index);
141236926Skibstatic u_int32_t agp_i915_read_gtt_pte(device_t dev, u_int index);
142236926Skibstatic u_int32_t agp_i965_read_gtt_pte(device_t dev, u_int index);
143236926Skibstatic u_int32_t agp_g4x_read_gtt_pte(device_t dev, u_int index);
144236926Skib
145236926Skibstatic vm_paddr_t agp_i810_read_gtt_pte_paddr(device_t dev, u_int index);
146236926Skibstatic vm_paddr_t agp_i915_read_gtt_pte_paddr(device_t dev, u_int index);
147236926Skibstatic vm_paddr_t agp_sb_read_gtt_pte_paddr(device_t dev, u_int index);
148236926Skib
149236926Skibstatic int agp_i810_set_aperture(device_t dev, u_int32_t aperture);
150236926Skibstatic int agp_i830_set_aperture(device_t dev, u_int32_t aperture);
151236926Skibstatic int agp_i915_set_aperture(device_t dev, u_int32_t aperture);
152236926Skib
153236926Skibstatic int agp_i810_chipset_flush_setup(device_t dev);
154236926Skibstatic int agp_i915_chipset_flush_setup(device_t dev);
155236926Skibstatic int agp_i965_chipset_flush_setup(device_t dev);
156236926Skib
157236926Skibstatic void agp_i810_chipset_flush_teardown(device_t dev);
158236926Skibstatic void agp_i915_chipset_flush_teardown(device_t dev);
159236926Skibstatic void agp_i965_chipset_flush_teardown(device_t dev);
160236926Skib
161236926Skibstatic void agp_i810_chipset_flush(device_t dev);
162236926Skibstatic void agp_i830_chipset_flush(device_t dev);
163236926Skibstatic void agp_i915_chipset_flush(device_t dev);
164236926Skib
165171433Sanholtenum {
166171433Sanholt	CHIP_I810,	/* i810/i815 */
167171433Sanholt	CHIP_I830,	/* 830M/845G */
168171433Sanholt	CHIP_I855,	/* 852GM/855GM/865G */
169171433Sanholt	CHIP_I915,	/* 915G/915GM */
170171433Sanholt	CHIP_I965,	/* G965 */
171171433Sanholt	CHIP_G33,	/* G33/Q33/Q35 */
172205102Srnoland	CHIP_IGD,	/* Pineview */
173183555Srnoland	CHIP_G4X,	/* G45/Q45 */
174236926Skib	CHIP_SB,	/* SandyBridge */
175171433Sanholt};
17663010Sdfr
177171433Sanholt/* The i810 through i855 have the registers at BAR 1, and the GATT gets
178171433Sanholt * allocated by us.  The i915 has registers in BAR 0 and the GATT is at the
179171433Sanholt * start of the stolen memory, and should only be accessed by the OS through
180171433Sanholt * BAR 3.  The G965 has registers and GATT in the same BAR (0) -- first 512KB
181171433Sanholt * is registers, second 512KB is GATT.
182171433Sanholt */
183171433Sanholtstatic struct resource_spec agp_i810_res_spec[] = {
184171433Sanholt	{ SYS_RES_MEMORY, AGP_I810_MMADR, RF_ACTIVE | RF_SHAREABLE },
185171433Sanholt	{ -1, 0 }
186171433Sanholt};
187103243Sanholt
188171433Sanholtstatic struct resource_spec agp_i915_res_spec[] = {
189171433Sanholt	{ SYS_RES_MEMORY, AGP_I915_MMADR, RF_ACTIVE | RF_SHAREABLE },
190171433Sanholt	{ SYS_RES_MEMORY, AGP_I915_GTTADR, RF_ACTIVE | RF_SHAREABLE },
191171433Sanholt	{ -1, 0 }
192171433Sanholt};
193171433Sanholt
194171433Sanholtstatic struct resource_spec agp_i965_res_spec[] = {
195171433Sanholt	{ SYS_RES_MEMORY, AGP_I965_GTTMMADR, RF_ACTIVE | RF_SHAREABLE },
196171433Sanholt	{ -1, 0 }
197171433Sanholt};
198171433Sanholt
199236926Skibstatic struct resource_spec agp_g4x_res_spec[] = {
200236926Skib	{ SYS_RES_MEMORY, AGP_G4X_MMADR, RF_ACTIVE | RF_SHAREABLE },
201236926Skib	{ SYS_RES_MEMORY, AGP_G4X_GTTADR, RF_ACTIVE | RF_SHAREABLE },
202236926Skib	{ -1, 0 }
203236926Skib};
204236926Skib
20563010Sdfrstruct agp_i810_softc {
20663010Sdfr	struct agp_softc agp;
20763010Sdfr	u_int32_t initial_aperture;	/* aperture size at startup */
20863010Sdfr	struct agp_gatt *gatt;
209103243Sanholt	u_int32_t dcache_size;		/* i810 only */
210236926Skib	u_int32_t stolen;		/* number of i830/845 gtt
211236926Skib					   entries for stolen memory */
212236926Skib	u_int stolen_size;		/* BIOS-reserved graphics memory */
213236926Skib	u_int gtt_total_entries;	/* Total number of gtt ptes */
214236926Skib	u_int gtt_mappable_entries;	/* Number of gtt ptes mappable by CPU */
21563010Sdfr	device_t bdev;			/* bridge device */
216171433Sanholt	void *argb_cursor;		/* contigmalloc area for ARGB cursor */
217171433Sanholt	struct resource *sc_res[2];
218236926Skib	const struct agp_i810_match *match;
219236926Skib	int sc_flush_page_rid;
220236926Skib	struct resource *sc_flush_page_res;
221236926Skib	void *sc_flush_page_vaddr;
222236926Skib	int sc_bios_allocated_flush_page;
22363010Sdfr};
22463010Sdfr
225236926Skibstatic device_t intel_agp;
226236926Skib
227236926Skibstruct agp_i810_driver {
228236926Skib	int chiptype;
229236926Skib	int gen;
230236926Skib	int busdma_addr_mask_sz;
231236926Skib	struct resource_spec *res_spec;
232236926Skib	int (*check_active)(device_t);
233236926Skib	void (*set_desc)(device_t, const struct agp_i810_match *);
234236926Skib	void (*dump_regs)(device_t);
235236926Skib	int (*get_stolen_size)(device_t);
236236926Skib	int (*get_gtt_total_entries)(device_t);
237236926Skib	int (*get_gtt_mappable_entries)(device_t);
238236926Skib	int (*install_gatt)(device_t);
239236926Skib	void (*deinstall_gatt)(device_t);
240236926Skib	void (*write_gtt)(device_t, u_int, uint32_t);
241236926Skib	void (*install_gtt_pte)(device_t, u_int, vm_offset_t, int);
242236926Skib	u_int32_t (*read_gtt_pte)(device_t, u_int);
243236926Skib	vm_paddr_t (*read_gtt_pte_paddr)(device_t , u_int);
244236926Skib	int (*set_aperture)(device_t, u_int32_t);
245236926Skib	int (*chipset_flush_setup)(device_t);
246236926Skib	void (*chipset_flush_teardown)(device_t);
247236926Skib	void (*chipset_flush)(device_t);
248236926Skib};
249236926Skib
250236926Skibstatic const struct agp_i810_driver agp_i810_i810_driver = {
251236926Skib	.chiptype = CHIP_I810,
252236926Skib	.gen = 1,
253236926Skib	.busdma_addr_mask_sz = 32,
254236926Skib	.res_spec = agp_i810_res_spec,
255236926Skib	.check_active = agp_i810_check_active,
256236926Skib	.set_desc = agp_i810_set_desc,
257236926Skib	.dump_regs = agp_i810_dump_regs,
258236926Skib	.get_stolen_size = agp_i810_get_stolen_size,
259236926Skib	.get_gtt_mappable_entries = agp_i810_get_gtt_mappable_entries,
260236926Skib	.get_gtt_total_entries = agp_i810_get_gtt_total_entries,
261236926Skib	.install_gatt = agp_i810_install_gatt,
262236926Skib	.deinstall_gatt = agp_i810_deinstall_gatt,
263236926Skib	.write_gtt = agp_i810_write_gtt,
264236926Skib	.install_gtt_pte = agp_i810_install_gtt_pte,
265236926Skib	.read_gtt_pte = agp_i810_read_gtt_pte,
266236926Skib	.read_gtt_pte_paddr = agp_i810_read_gtt_pte_paddr,
267236926Skib	.set_aperture = agp_i810_set_aperture,
268236926Skib	.chipset_flush_setup = agp_i810_chipset_flush_setup,
269236926Skib	.chipset_flush_teardown = agp_i810_chipset_flush_teardown,
270236926Skib	.chipset_flush = agp_i810_chipset_flush,
271236926Skib};
272236926Skib
273236926Skibstatic const struct agp_i810_driver agp_i810_i815_driver = {
274236926Skib	.chiptype = CHIP_I810,
275236926Skib	.gen = 2,
276236926Skib	.busdma_addr_mask_sz = 32,
277236926Skib	.res_spec = agp_i810_res_spec,
278236926Skib	.check_active = agp_i810_check_active,
279236926Skib	.set_desc = agp_i810_set_desc,
280236926Skib	.dump_regs = agp_i810_dump_regs,
281236926Skib	.get_stolen_size = agp_i810_get_stolen_size,
282236926Skib	.get_gtt_mappable_entries = agp_i830_get_gtt_mappable_entries,
283236926Skib	.get_gtt_total_entries = agp_i810_get_gtt_total_entries,
284236926Skib	.install_gatt = agp_i810_install_gatt,
285236926Skib	.deinstall_gatt = agp_i810_deinstall_gatt,
286236926Skib	.write_gtt = agp_i810_write_gtt,
287236926Skib	.install_gtt_pte = agp_i810_install_gtt_pte,
288236926Skib	.read_gtt_pte = agp_i810_read_gtt_pte,
289236926Skib	.read_gtt_pte_paddr = agp_i810_read_gtt_pte_paddr,
290236926Skib	.set_aperture = agp_i810_set_aperture,
291236926Skib	.chipset_flush_setup = agp_i810_chipset_flush_setup,
292236926Skib	.chipset_flush_teardown = agp_i810_chipset_flush_teardown,
293236926Skib	.chipset_flush = agp_i830_chipset_flush,
294236926Skib};
295236926Skib
296236926Skibstatic const struct agp_i810_driver agp_i810_i830_driver = {
297236926Skib	.chiptype = CHIP_I830,
298236926Skib	.gen = 2,
299236926Skib	.busdma_addr_mask_sz = 32,
300236926Skib	.res_spec = agp_i810_res_spec,
301236926Skib	.check_active = agp_i830_check_active,
302236926Skib	.set_desc = agp_i810_set_desc,
303236926Skib	.dump_regs = agp_i830_dump_regs,
304236926Skib	.get_stolen_size = agp_i830_get_stolen_size,
305236926Skib	.get_gtt_mappable_entries = agp_i830_get_gtt_mappable_entries,
306236926Skib	.get_gtt_total_entries = agp_i810_get_gtt_total_entries,
307236926Skib	.install_gatt = agp_i830_install_gatt,
308236926Skib	.deinstall_gatt = agp_i830_deinstall_gatt,
309236926Skib	.write_gtt = agp_i810_write_gtt,
310236926Skib	.install_gtt_pte = agp_i830_install_gtt_pte,
311236926Skib	.read_gtt_pte = agp_i810_read_gtt_pte,
312236926Skib	.read_gtt_pte_paddr = agp_i810_read_gtt_pte_paddr,
313236926Skib	.set_aperture = agp_i830_set_aperture,
314236926Skib	.chipset_flush_setup = agp_i810_chipset_flush_setup,
315236926Skib	.chipset_flush_teardown = agp_i810_chipset_flush_teardown,
316236926Skib	.chipset_flush = agp_i830_chipset_flush,
317236926Skib};
318236926Skib
319236926Skibstatic const struct agp_i810_driver agp_i810_i855_driver = {
320236926Skib	.chiptype = CHIP_I855,
321236926Skib	.gen = 2,
322236926Skib	.busdma_addr_mask_sz = 32,
323236926Skib	.res_spec = agp_i810_res_spec,
324236926Skib	.check_active = agp_i830_check_active,
325236926Skib	.set_desc = agp_82852_set_desc,
326236926Skib	.dump_regs = agp_i855_dump_regs,
327236926Skib	.get_stolen_size = agp_i915_get_stolen_size,
328236926Skib	.get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
329236926Skib	.get_gtt_total_entries = agp_i810_get_gtt_total_entries,
330236926Skib	.install_gatt = agp_i830_install_gatt,
331236926Skib	.deinstall_gatt = agp_i830_deinstall_gatt,
332236926Skib	.write_gtt = agp_i810_write_gtt,
333236926Skib	.install_gtt_pte = agp_i830_install_gtt_pte,
334236926Skib	.read_gtt_pte = agp_i810_read_gtt_pte,
335236926Skib	.read_gtt_pte_paddr = agp_i810_read_gtt_pte_paddr,
336236926Skib	.set_aperture = agp_i830_set_aperture,
337236926Skib	.chipset_flush_setup = agp_i810_chipset_flush_setup,
338236926Skib	.chipset_flush_teardown = agp_i810_chipset_flush_teardown,
339236926Skib	.chipset_flush = agp_i830_chipset_flush,
340236926Skib};
341236926Skib
342236926Skibstatic const struct agp_i810_driver agp_i810_i865_driver = {
343236926Skib	.chiptype = CHIP_I855,
344236926Skib	.gen = 2,
345236926Skib	.busdma_addr_mask_sz = 32,
346236926Skib	.res_spec = agp_i810_res_spec,
347236926Skib	.check_active = agp_i830_check_active,
348236926Skib	.set_desc = agp_i810_set_desc,
349236926Skib	.dump_regs = agp_i855_dump_regs,
350236926Skib	.get_stolen_size = agp_i915_get_stolen_size,
351236926Skib	.get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
352236926Skib	.get_gtt_total_entries = agp_i810_get_gtt_total_entries,
353236926Skib	.install_gatt = agp_i830_install_gatt,
354236926Skib	.deinstall_gatt = agp_i830_deinstall_gatt,
355236926Skib	.write_gtt = agp_i810_write_gtt,
356236926Skib	.install_gtt_pte = agp_i830_install_gtt_pte,
357236926Skib	.read_gtt_pte = agp_i810_read_gtt_pte,
358236926Skib	.read_gtt_pte_paddr = agp_i810_read_gtt_pte_paddr,
359236926Skib	.set_aperture = agp_i915_set_aperture,
360236926Skib	.chipset_flush_setup = agp_i810_chipset_flush_setup,
361236926Skib	.chipset_flush_teardown = agp_i810_chipset_flush_teardown,
362236926Skib	.chipset_flush = agp_i830_chipset_flush,
363236926Skib};
364236926Skib
365236926Skibstatic const struct agp_i810_driver agp_i810_i915_driver = {
366236926Skib	.chiptype = CHIP_I915,
367236926Skib	.gen = 3,
368236926Skib	.busdma_addr_mask_sz = 32,
369236926Skib	.res_spec = agp_i915_res_spec,
370236926Skib	.check_active = agp_i915_check_active,
371236926Skib	.set_desc = agp_i810_set_desc,
372236926Skib	.dump_regs = agp_i915_dump_regs,
373236926Skib	.get_stolen_size = agp_i915_get_stolen_size,
374236926Skib	.get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
375236926Skib	.get_gtt_total_entries = agp_i810_get_gtt_total_entries,
376236926Skib	.install_gatt = agp_i830_install_gatt,
377236926Skib	.deinstall_gatt = agp_i830_deinstall_gatt,
378236926Skib	.write_gtt = agp_i915_write_gtt,
379236926Skib	.install_gtt_pte = agp_i915_install_gtt_pte,
380236926Skib	.read_gtt_pte = agp_i915_read_gtt_pte,
381236926Skib	.read_gtt_pte_paddr = agp_i915_read_gtt_pte_paddr,
382236926Skib	.set_aperture = agp_i915_set_aperture,
383236926Skib	.chipset_flush_setup = agp_i915_chipset_flush_setup,
384236926Skib	.chipset_flush_teardown = agp_i915_chipset_flush_teardown,
385236926Skib	.chipset_flush = agp_i915_chipset_flush,
386236926Skib};
387236926Skib
388236926Skibstatic const struct agp_i810_driver agp_i810_g965_driver = {
389236926Skib	.chiptype = CHIP_I965,
390236926Skib	.gen = 4,
391236926Skib	.busdma_addr_mask_sz = 36,
392236926Skib	.res_spec = agp_i965_res_spec,
393236926Skib	.check_active = agp_i915_check_active,
394236926Skib	.set_desc = agp_i810_set_desc,
395236926Skib	.dump_regs = agp_i965_dump_regs,
396236926Skib	.get_stolen_size = agp_i915_get_stolen_size,
397236926Skib	.get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
398236926Skib	.get_gtt_total_entries = agp_i965_get_gtt_total_entries,
399236926Skib	.install_gatt = agp_i830_install_gatt,
400236926Skib	.deinstall_gatt = agp_i830_deinstall_gatt,
401236926Skib	.write_gtt = agp_i965_write_gtt,
402236926Skib	.install_gtt_pte = agp_i965_install_gtt_pte,
403236926Skib	.read_gtt_pte = agp_i965_read_gtt_pte,
404236926Skib	.read_gtt_pte_paddr = agp_i915_read_gtt_pte_paddr,
405236926Skib	.set_aperture = agp_i915_set_aperture,
406236926Skib	.chipset_flush_setup = agp_i965_chipset_flush_setup,
407236926Skib	.chipset_flush_teardown = agp_i965_chipset_flush_teardown,
408236926Skib	.chipset_flush = agp_i915_chipset_flush,
409236926Skib};
410236926Skib
411236926Skibstatic const struct agp_i810_driver agp_i810_g33_driver = {
412236926Skib	.chiptype = CHIP_G33,
413236926Skib	.gen = 3,
414236926Skib	.busdma_addr_mask_sz = 36,
415236926Skib	.res_spec = agp_i915_res_spec,
416236926Skib	.check_active = agp_i915_check_active,
417236926Skib	.set_desc = agp_i810_set_desc,
418236926Skib	.dump_regs = agp_i965_dump_regs,
419236926Skib	.get_stolen_size = agp_i915_get_stolen_size,
420236926Skib	.get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
421236926Skib	.get_gtt_total_entries = agp_i965_get_gtt_total_entries,
422236926Skib	.install_gatt = agp_i830_install_gatt,
423236926Skib	.deinstall_gatt = agp_i830_deinstall_gatt,
424236926Skib	.write_gtt = agp_i915_write_gtt,
425236926Skib	.install_gtt_pte = agp_i915_install_gtt_pte,
426236926Skib	.read_gtt_pte = agp_i915_read_gtt_pte,
427236926Skib	.read_gtt_pte_paddr = agp_i915_read_gtt_pte_paddr,
428236926Skib	.set_aperture = agp_i915_set_aperture,
429236926Skib	.chipset_flush_setup = agp_i965_chipset_flush_setup,
430236926Skib	.chipset_flush_teardown = agp_i965_chipset_flush_teardown,
431236926Skib	.chipset_flush = agp_i915_chipset_flush,
432236926Skib};
433236926Skib
434236926Skibstatic const struct agp_i810_driver agp_i810_igd_driver = {
435236926Skib	.chiptype = CHIP_IGD,
436236926Skib	.gen = 3,
437236926Skib	.busdma_addr_mask_sz = 36,
438236926Skib	.res_spec = agp_i915_res_spec,
439236926Skib	.check_active = agp_i915_check_active,
440236926Skib	.set_desc = agp_i810_set_desc,
441236926Skib	.dump_regs = agp_i915_dump_regs,
442236926Skib	.get_stolen_size = agp_i915_get_stolen_size,
443236926Skib	.get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
444236926Skib	.get_gtt_total_entries = agp_i965_get_gtt_total_entries,
445236926Skib	.install_gatt = agp_i830_install_gatt,
446236926Skib	.deinstall_gatt = agp_i830_deinstall_gatt,
447236926Skib	.write_gtt = agp_i915_write_gtt,
448236926Skib	.install_gtt_pte = agp_i915_install_gtt_pte,
449236926Skib	.read_gtt_pte = agp_i915_read_gtt_pte,
450236926Skib	.read_gtt_pte_paddr = agp_i915_read_gtt_pte_paddr,
451236926Skib	.set_aperture = agp_i915_set_aperture,
452236926Skib	.chipset_flush_setup = agp_i965_chipset_flush_setup,
453236926Skib	.chipset_flush_teardown = agp_i965_chipset_flush_teardown,
454236926Skib	.chipset_flush = agp_i915_chipset_flush,
455236926Skib};
456236926Skib
457236926Skibstatic const struct agp_i810_driver agp_i810_g4x_driver = {
458236926Skib	.chiptype = CHIP_G4X,
459236926Skib	.gen = 5,
460236926Skib	.busdma_addr_mask_sz = 36,
461236926Skib	.res_spec = agp_i965_res_spec,
462236926Skib	.check_active = agp_i915_check_active,
463236926Skib	.set_desc = agp_i810_set_desc,
464236926Skib	.dump_regs = agp_i965_dump_regs,
465236926Skib	.get_stolen_size = agp_i915_get_stolen_size,
466236926Skib	.get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
467236926Skib	.get_gtt_total_entries = agp_gen5_get_gtt_total_entries,
468236926Skib	.install_gatt = agp_i830_install_gatt,
469236926Skib	.deinstall_gatt = agp_i830_deinstall_gatt,
470236926Skib	.write_gtt = agp_g4x_write_gtt,
471236926Skib	.install_gtt_pte = agp_g4x_install_gtt_pte,
472236926Skib	.read_gtt_pte = agp_g4x_read_gtt_pte,
473236926Skib	.read_gtt_pte_paddr = agp_i915_read_gtt_pte_paddr,
474236926Skib	.set_aperture = agp_i915_set_aperture,
475236926Skib	.chipset_flush_setup = agp_i965_chipset_flush_setup,
476236926Skib	.chipset_flush_teardown = agp_i965_chipset_flush_teardown,
477236926Skib	.chipset_flush = agp_i915_chipset_flush,
478236926Skib};
479236926Skib
480236926Skibstatic const struct agp_i810_driver agp_i810_sb_driver = {
481236926Skib	.chiptype = CHIP_SB,
482236926Skib	.gen = 6,
483236926Skib	.busdma_addr_mask_sz = 40,
484236926Skib	.res_spec = agp_g4x_res_spec,
485236926Skib	.check_active = agp_sb_check_active,
486236926Skib	.set_desc = agp_i810_set_desc,
487236926Skib	.dump_regs = agp_sb_dump_regs,
488236926Skib	.get_stolen_size = agp_sb_get_stolen_size,
489236926Skib	.get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
490236926Skib	.get_gtt_total_entries = agp_sb_get_gtt_total_entries,
491236926Skib	.install_gatt = agp_i830_install_gatt,
492236926Skib	.deinstall_gatt = agp_i830_deinstall_gatt,
493236926Skib	.write_gtt = agp_sb_write_gtt,
494236926Skib	.install_gtt_pte = agp_sb_install_gtt_pte,
495236926Skib	.read_gtt_pte = agp_g4x_read_gtt_pte,
496236926Skib	.read_gtt_pte_paddr = agp_sb_read_gtt_pte_paddr,
497236926Skib	.set_aperture = agp_i915_set_aperture,
498236926Skib	.chipset_flush_setup = agp_i810_chipset_flush_setup,
499236926Skib	.chipset_flush_teardown = agp_i810_chipset_flush_teardown,
500236926Skib	.chipset_flush = agp_i810_chipset_flush,
501236926Skib};
502236926Skib
503159926Sanholt/* For adding new devices, devid is the id of the graphics controller
504159926Sanholt * (pci:0:2:0, for example).  The placeholder (usually at pci:0:2:1) for the
505159926Sanholt * second head should never be added.  The bridge_offset is the offset to
506159926Sanholt * subtract from devid to get the id of the hostb that the device is on.
507159926Sanholt */
508159926Sanholtstatic const struct agp_i810_match {
509159926Sanholt	int devid;
510159926Sanholt	char *name;
511236926Skib	const struct agp_i810_driver *driver;
512159926Sanholt} agp_i810_matches[] = {
513236926Skib	{
514236926Skib		.devid = 0x71218086,
515236926Skib		.name = "Intel 82810 (i810 GMCH) SVGA controller",
516236926Skib		.driver = &agp_i810_i810_driver
517236926Skib	},
518236926Skib	{
519236926Skib		.devid = 0x71238086,
520236926Skib		.name = "Intel 82810-DC100 (i810-DC100 GMCH) SVGA controller",
521236926Skib		.driver = &agp_i810_i810_driver
522236926Skib	},
523236926Skib	{
524236926Skib		.devid = 0x71258086,
525236926Skib		.name = "Intel 82810E (i810E GMCH) SVGA controller",
526236926Skib		.driver = &agp_i810_i810_driver
527236926Skib	},
528236926Skib	{
529236926Skib		.devid = 0x11328086,
530236926Skib		.name = "Intel 82815 (i815 GMCH) SVGA controller",
531236926Skib		.driver = &agp_i810_i815_driver
532236926Skib	},
533236926Skib	{
534236926Skib		.devid = 0x35778086,
535236926Skib		.name = "Intel 82830M (830M GMCH) SVGA controller",
536236926Skib		.driver = &agp_i810_i830_driver
537236926Skib	},
538236926Skib	{
539236926Skib		.devid = 0x25628086,
540236926Skib		.name = "Intel 82845M (845M GMCH) SVGA controller",
541236926Skib		.driver = &agp_i810_i830_driver
542236926Skib	},
543236926Skib	{
544236926Skib		.devid = 0x35828086,
545236926Skib		.name = "Intel 82852/855GM SVGA controller",
546236926Skib		.driver = &agp_i810_i855_driver
547236926Skib	},
548236926Skib	{
549236926Skib		.devid = 0x25728086,
550236926Skib		.name = "Intel 82865G (865G GMCH) SVGA controller",
551236926Skib		.driver = &agp_i810_i865_driver
552236926Skib	},
553236926Skib	{
554236926Skib		.devid = 0x25828086,
555236926Skib		.name = "Intel 82915G (915G GMCH) SVGA controller",
556236926Skib		.driver = &agp_i810_i915_driver
557236926Skib	},
558236926Skib	{
559236926Skib		.devid = 0x258A8086,
560236926Skib		.name = "Intel E7221 SVGA controller",
561236926Skib		.driver = &agp_i810_i915_driver
562236926Skib	},
563236926Skib	{
564236926Skib		.devid = 0x25928086,
565236926Skib		.name = "Intel 82915GM (915GM GMCH) SVGA controller",
566236926Skib		.driver = &agp_i810_i915_driver
567236926Skib	},
568236926Skib	{
569236926Skib		.devid = 0x27728086,
570236926Skib		.name = "Intel 82945G (945G GMCH) SVGA controller",
571236926Skib		.driver = &agp_i810_i915_driver
572236926Skib	},
573236926Skib	{
574236926Skib		.devid = 0x27A28086,
575236926Skib		.name = "Intel 82945GM (945GM GMCH) SVGA controller",
576236926Skib		.driver = &agp_i810_i915_driver
577236926Skib	},
578236926Skib	{
579236926Skib		.devid = 0x27AE8086,
580236926Skib		.name = "Intel 945GME SVGA controller",
581236926Skib		.driver = &agp_i810_i915_driver
582236926Skib	},
583236926Skib	{
584236926Skib		.devid = 0x29728086,
585236926Skib		.name = "Intel 946GZ SVGA controller",
586236926Skib		.driver = &agp_i810_g965_driver
587236926Skib	},
588236926Skib	{
589236926Skib		.devid = 0x29828086,
590236926Skib		.name = "Intel G965 SVGA controller",
591236926Skib		.driver = &agp_i810_g965_driver
592236926Skib	},
593236926Skib	{
594236926Skib		.devid = 0x29928086,
595236926Skib		.name = "Intel Q965 SVGA controller",
596236926Skib		.driver = &agp_i810_g965_driver
597236926Skib	},
598236926Skib	{
599236926Skib		.devid = 0x29A28086,
600236926Skib		.name = "Intel G965 SVGA controller",
601236926Skib		.driver = &agp_i810_g965_driver
602236926Skib	},
603236926Skib	{
604236926Skib		.devid = 0x29B28086,
605236926Skib		.name = "Intel Q35 SVGA controller",
606236926Skib		.driver = &agp_i810_g33_driver
607236926Skib	},
608236926Skib	{
609236926Skib		.devid = 0x29C28086,
610236926Skib		.name = "Intel G33 SVGA controller",
611236926Skib		.driver = &agp_i810_g33_driver
612236926Skib	},
613236926Skib	{
614236926Skib		.devid = 0x29D28086,
615236926Skib		.name = "Intel Q33 SVGA controller",
616236926Skib		.driver = &agp_i810_g33_driver
617236926Skib	},
618236926Skib	{
619236926Skib		.devid = 0xA0018086,
620236926Skib		.name = "Intel Pineview SVGA controller",
621236926Skib		.driver = &agp_i810_igd_driver
622236926Skib	},
623236926Skib	{
624236926Skib		.devid = 0xA0118086,
625236926Skib		.name = "Intel Pineview (M) SVGA controller",
626236926Skib		.driver = &agp_i810_igd_driver
627236926Skib	},
628236926Skib	{
629236926Skib		.devid = 0x2A028086,
630236926Skib		.name = "Intel GM965 SVGA controller",
631236926Skib		.driver = &agp_i810_g965_driver
632236926Skib	},
633236926Skib	{
634236926Skib		.devid = 0x2A128086,
635236926Skib		.name = "Intel GME965 SVGA controller",
636236926Skib		.driver = &agp_i810_g965_driver
637236926Skib	},
638236926Skib	{
639236926Skib		.devid = 0x2A428086,
640236926Skib		.name = "Intel GM45 SVGA controller",
641236926Skib		.driver = &agp_i810_g4x_driver
642236926Skib	},
643236926Skib	{
644236926Skib		.devid = 0x2E028086,
645236926Skib		.name = "Intel Eaglelake SVGA controller",
646236926Skib		.driver = &agp_i810_g4x_driver
647236926Skib	},
648236926Skib	{
649236926Skib		.devid = 0x2E128086,
650236926Skib		.name = "Intel Q45 SVGA controller",
651236926Skib		.driver = &agp_i810_g4x_driver
652236926Skib	},
653236926Skib	{
654236926Skib		.devid = 0x2E228086,
655236926Skib		.name = "Intel G45 SVGA controller",
656236926Skib		.driver = &agp_i810_g4x_driver
657236926Skib	},
658236926Skib	{
659236926Skib		.devid = 0x2E328086,
660236926Skib		.name = "Intel G41 SVGA controller",
661236926Skib		.driver = &agp_i810_g4x_driver
662236926Skib	},
663236926Skib	{
664236926Skib		.devid = 0x00428086,
665236926Skib		.name = "Intel Ironlake (D) SVGA controller",
666236926Skib		.driver = &agp_i810_g4x_driver
667236926Skib	},
668236926Skib	{
669236926Skib		.devid = 0x00468086,
670236926Skib		.name = "Intel Ironlake (M) SVGA controller",
671236926Skib		.driver = &agp_i810_g4x_driver
672236926Skib	},
673236926Skib	{
674236926Skib		.devid = 0x01028086,
675236926Skib		.name = "SandyBridge desktop GT1 IG",
676236926Skib		.driver = &agp_i810_sb_driver
677236926Skib	},
678236926Skib	{
679236926Skib		.devid = 0x01128086,
680236926Skib		.name = "SandyBridge desktop GT2 IG",
681236926Skib		.driver = &agp_i810_sb_driver
682236926Skib	},
683236926Skib	{
684236926Skib		.devid = 0x01228086,
685236926Skib		.name = "SandyBridge desktop GT2+ IG",
686236926Skib		.driver = &agp_i810_sb_driver
687236926Skib	},
688236926Skib	{
689236926Skib		.devid = 0x01068086,
690236926Skib		.name = "SandyBridge mobile GT1 IG",
691236926Skib		.driver = &agp_i810_sb_driver
692236926Skib	},
693236926Skib	{
694236926Skib		.devid = 0x01168086,
695236926Skib		.name = "SandyBridge mobile GT2 IG",
696236926Skib		.driver = &agp_i810_sb_driver
697236926Skib	},
698236926Skib	{
699236926Skib		.devid = 0x01268086,
700236926Skib		.name = "SandyBridge mobile GT2+ IG",
701236926Skib		.driver = &agp_i810_sb_driver
702236926Skib	},
703236926Skib	{
704237594Skib		.devid = 0x010a8086,
705236926Skib		.name = "SandyBridge server IG",
706236926Skib		.driver = &agp_i810_sb_driver
707236926Skib	},
708236926Skib	{
709236926Skib		.devid = 0x01528086,
710236926Skib		.name = "IvyBridge desktop GT1 IG",
711236926Skib		.driver = &agp_i810_sb_driver
712236926Skib	},
713236926Skib	{
714236926Skib		.devid = 0x01628086,
715236926Skib		.name = "IvyBridge desktop GT2 IG",
716236926Skib		.driver = &agp_i810_sb_driver
717236926Skib	},
718236926Skib	{
719236926Skib		.devid = 0x01568086,
720236926Skib		.name = "IvyBridge mobile GT1 IG",
721236926Skib		.driver = &agp_i810_sb_driver
722236926Skib	},
723236926Skib	{
724236926Skib		.devid = 0x01668086,
725236926Skib		.name = "IvyBridge mobile GT2 IG",
726236926Skib		.driver = &agp_i810_sb_driver
727236926Skib	},
728236926Skib	{
729236926Skib		.devid = 0x015a8086,
730236926Skib		.name = "IvyBridge server GT1 IG",
731236926Skib		.driver = &agp_i810_sb_driver
732236926Skib	},
733236926Skib	{
734244207Sbapt		.devid = 0x016a8086,
735244207Sbapt		.name = "IvyBridge server GT2 IG",
736244207Sbapt		.driver = &agp_i810_sb_driver
737244207Sbapt	},
738244207Sbapt	{
739236926Skib		.devid = 0,
740236926Skib	}
741159926Sanholt};
742159926Sanholt
743159926Sanholtstatic const struct agp_i810_match*
74463010Sdfragp_i810_match(device_t dev)
74563010Sdfr{
746159926Sanholt	int i, devid;
747159926Sanholt
74863010Sdfr	if (pci_get_class(dev) != PCIC_DISPLAY
74963010Sdfr	    || pci_get_subclass(dev) != PCIS_DISPLAY_VGA)
750236926Skib		return (NULL);
75163010Sdfr
752159926Sanholt	devid = pci_get_devid(dev);
753159926Sanholt	for (i = 0; agp_i810_matches[i].devid != 0; i++) {
754159926Sanholt		if (agp_i810_matches[i].devid == devid)
755236926Skib			break;
756159926Sanholt	}
757159926Sanholt	if (agp_i810_matches[i].devid == 0)
758236926Skib		return (NULL);
759159926Sanholt	else
760236926Skib		return (&agp_i810_matches[i]);
76163010Sdfr}
76263010Sdfr
76363010Sdfr/*
76463010Sdfr * Find bridge device.
76563010Sdfr */
76663010Sdfrstatic device_t
76763010Sdfragp_i810_find_bridge(device_t dev)
76863010Sdfr{
76963010Sdfr
770236926Skib	return (pci_find_dbsf(0, 0, 0, 0));
77163010Sdfr}
77263010Sdfr
773155186Sjhbstatic void
774155186Sjhbagp_i810_identify(driver_t *driver, device_t parent)
775155186Sjhb{
776155186Sjhb
777155186Sjhb	if (device_find_child(parent, "agp", -1) == NULL &&
778155186Sjhb	    agp_i810_match(parent))
779155186Sjhb		device_add_child(parent, "agp", -1);
780155186Sjhb}
781155186Sjhb
78263010Sdfrstatic int
783236926Skibagp_i810_check_active(device_t bridge_dev)
784236926Skib{
785236926Skib	u_int8_t smram;
786236926Skib
787236926Skib	smram = pci_read_config(bridge_dev, AGP_I810_SMRAM, 1);
788236926Skib	if ((smram & AGP_I810_SMRAM_GMS) == AGP_I810_SMRAM_GMS_DISABLED)
789236926Skib		return (ENXIO);
790236926Skib	return (0);
791236926Skib}
792236926Skib
793236926Skibstatic int
794236926Skibagp_i830_check_active(device_t bridge_dev)
795236926Skib{
796236926Skib	int gcc1;
797236926Skib
798236926Skib	gcc1 = pci_read_config(bridge_dev, AGP_I830_GCC1, 1);
799236926Skib	if ((gcc1 & AGP_I830_GCC1_DEV2) == AGP_I830_GCC1_DEV2_DISABLED)
800236926Skib		return (ENXIO);
801236926Skib	return (0);
802236926Skib}
803236926Skib
804236926Skibstatic int
805236926Skibagp_i915_check_active(device_t bridge_dev)
806236926Skib{
807236926Skib	int deven;
808236926Skib
809236926Skib	deven = pci_read_config(bridge_dev, AGP_I915_DEVEN, 4);
810236926Skib	if ((deven & AGP_I915_DEVEN_D2F0) == AGP_I915_DEVEN_D2F0_DISABLED)
811236926Skib		return (ENXIO);
812236926Skib	return (0);
813236926Skib}
814236926Skib
815236926Skibstatic int
816236926Skibagp_sb_check_active(device_t bridge_dev)
817236926Skib{
818236926Skib	int deven;
819236926Skib
820236926Skib	deven = pci_read_config(bridge_dev, AGP_I915_DEVEN, 4);
821236926Skib	if ((deven & AGP_SB_DEVEN_D2EN) == AGP_SB_DEVEN_D2EN_DISABLED)
822236926Skib		return (ENXIO);
823236926Skib	return (0);
824236926Skib}
825236926Skib
826236926Skibstatic void
827236926Skibagp_82852_set_desc(device_t dev, const struct agp_i810_match *match)
828236926Skib{
829236926Skib
830236926Skib	switch (pci_read_config(dev, AGP_I85X_CAPID, 1)) {
831236926Skib	case AGP_I855_GME:
832236926Skib		device_set_desc(dev,
833236926Skib		    "Intel 82855GME (855GME GMCH) SVGA controller");
834236926Skib		break;
835236926Skib	case AGP_I855_GM:
836236926Skib		device_set_desc(dev,
837236926Skib		    "Intel 82855GM (855GM GMCH) SVGA controller");
838236926Skib		break;
839236926Skib	case AGP_I852_GME:
840236926Skib		device_set_desc(dev,
841236926Skib		    "Intel 82852GME (852GME GMCH) SVGA controller");
842236926Skib		break;
843236926Skib	case AGP_I852_GM:
844236926Skib		device_set_desc(dev,
845236926Skib		    "Intel 82852GM (852GM GMCH) SVGA controller");
846236926Skib		break;
847236926Skib	default:
848236926Skib		device_set_desc(dev,
849236926Skib		    "Intel 8285xM (85xGM GMCH) SVGA controller");
850236926Skib		break;
851236926Skib	}
852236926Skib}
853236926Skib
854236926Skibstatic void
855236926Skibagp_i810_set_desc(device_t dev, const struct agp_i810_match *match)
856236926Skib{
857236926Skib
858236926Skib	device_set_desc(dev, match->name);
859236926Skib}
860236926Skib
861236926Skibstatic int
86263010Sdfragp_i810_probe(device_t dev)
86363010Sdfr{
864159926Sanholt	device_t bdev;
865159926Sanholt	const struct agp_i810_match *match;
866236926Skib	int err;
86763010Sdfr
868127815Snjl	if (resource_disabled("agp", device_get_unit(dev)))
869127815Snjl		return (ENXIO);
870159926Sanholt	match = agp_i810_match(dev);
871159926Sanholt	if (match == NULL)
872236926Skib		return (ENXIO);
873159926Sanholt
874159926Sanholt	bdev = agp_i810_find_bridge(dev);
875236926Skib	if (bdev == NULL) {
876159926Sanholt		if (bootverbose)
877159926Sanholt			printf("I810: can't find bridge device\n");
878236926Skib		return (ENXIO);
879159926Sanholt	}
880159926Sanholt
881159926Sanholt	/*
882159926Sanholt	 * checking whether internal graphics device has been activated.
883159926Sanholt	 */
884236926Skib	err = match->driver->check_active(bdev);
885236926Skib	if (err != 0) {
886236926Skib		if (bootverbose)
887236926Skib			printf("i810: disabled, not probing\n");
888236926Skib		return (err);
889159926Sanholt	}
890121437Sjhb
891236926Skib	match->driver->set_desc(dev, match);
892236926Skib	return (BUS_PROBE_DEFAULT);
89363010Sdfr}
89463010Sdfr
895171433Sanholtstatic void
896171433Sanholtagp_i810_dump_regs(device_t dev)
897171433Sanholt{
898171433Sanholt	struct agp_i810_softc *sc = device_get_softc(dev);
899171433Sanholt
900171433Sanholt	device_printf(dev, "AGP_I810_PGTBL_CTL: %08x\n",
901171433Sanholt	    bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL));
902236926Skib	device_printf(dev, "AGP_I810_MISCC: 0x%04x\n",
903236926Skib	    pci_read_config(sc->bdev, AGP_I810_MISCC, 2));
904236926Skib}
905171433Sanholt
906236926Skibstatic void
907236926Skibagp_i830_dump_regs(device_t dev)
908236926Skib{
909236926Skib	struct agp_i810_softc *sc = device_get_softc(dev);
910236926Skib
911236926Skib	device_printf(dev, "AGP_I810_PGTBL_CTL: %08x\n",
912236926Skib	    bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL));
913236926Skib	device_printf(dev, "AGP_I830_GCC1: 0x%02x\n",
914236926Skib	    pci_read_config(sc->bdev, AGP_I830_GCC1, 1));
915236926Skib}
916236926Skib
917236926Skibstatic void
918236926Skibagp_i855_dump_regs(device_t dev)
919236926Skib{
920236926Skib	struct agp_i810_softc *sc = device_get_softc(dev);
921236926Skib
922236926Skib	device_printf(dev, "AGP_I810_PGTBL_CTL: %08x\n",
923236926Skib	    bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL));
924236926Skib	device_printf(dev, "AGP_I855_GCC1: 0x%02x\n",
925236926Skib	    pci_read_config(sc->bdev, AGP_I855_GCC1, 1));
926236926Skib}
927236926Skib
928236926Skibstatic void
929236926Skibagp_i915_dump_regs(device_t dev)
930236926Skib{
931236926Skib	struct agp_i810_softc *sc = device_get_softc(dev);
932236926Skib
933236926Skib	device_printf(dev, "AGP_I810_PGTBL_CTL: %08x\n",
934236926Skib	    bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL));
935236926Skib	device_printf(dev, "AGP_I855_GCC1: 0x%02x\n",
936236926Skib	    pci_read_config(sc->bdev, AGP_I855_GCC1, 1));
937236926Skib	device_printf(dev, "AGP_I915_MSAC: 0x%02x\n",
938236926Skib	    pci_read_config(sc->bdev, AGP_I915_MSAC, 1));
939236926Skib}
940236926Skib
941236926Skibstatic void
942236926Skibagp_i965_dump_regs(device_t dev)
943236926Skib{
944236926Skib	struct agp_i810_softc *sc = device_get_softc(dev);
945236926Skib
946236926Skib	device_printf(dev, "AGP_I965_PGTBL_CTL2: %08x\n",
947236926Skib	    bus_read_4(sc->sc_res[0], AGP_I965_PGTBL_CTL2));
948236926Skib	device_printf(dev, "AGP_I855_GCC1: 0x%02x\n",
949236926Skib	    pci_read_config(sc->bdev, AGP_I855_GCC1, 1));
950236926Skib	device_printf(dev, "AGP_I965_MSAC: 0x%02x\n",
951236926Skib	    pci_read_config(sc->bdev, AGP_I965_MSAC, 1));
952236926Skib}
953236926Skib
954236926Skibstatic void
955236926Skibagp_sb_dump_regs(device_t dev)
956236926Skib{
957236926Skib	struct agp_i810_softc *sc = device_get_softc(dev);
958236926Skib
959236926Skib	device_printf(dev, "AGP_SNB_GFX_MODE: %08x\n",
960236926Skib	    bus_read_4(sc->sc_res[0], AGP_SNB_GFX_MODE));
961236926Skib	device_printf(dev, "AGP_SNB_GCC1: 0x%04x\n",
962236926Skib	    pci_read_config(sc->bdev, AGP_SNB_GCC1, 2));
963236926Skib}
964236926Skib
965236926Skibstatic int
966236926Skibagp_i810_get_stolen_size(device_t dev)
967236926Skib{
968236926Skib	struct agp_i810_softc *sc;
969236926Skib
970236926Skib	sc = device_get_softc(dev);
971236926Skib	sc->stolen = 0;
972236926Skib	sc->stolen_size = 0;
973236926Skib	return (0);
974236926Skib}
975236926Skib
976236926Skibstatic int
977236926Skibagp_i830_get_stolen_size(device_t dev)
978236926Skib{
979236926Skib	struct agp_i810_softc *sc;
980236926Skib	unsigned int gcc1;
981236926Skib
982236926Skib	sc = device_get_softc(dev);
983236926Skib
984236926Skib	gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 1);
985236926Skib	switch (gcc1 & AGP_I830_GCC1_GMS) {
986236926Skib	case AGP_I830_GCC1_GMS_STOLEN_512:
987236926Skib		sc->stolen = (512 - 132) * 1024 / 4096;
988236926Skib		sc->stolen_size = 512 * 1024;
989171433Sanholt		break;
990236926Skib	case AGP_I830_GCC1_GMS_STOLEN_1024:
991236926Skib		sc->stolen = (1024 - 132) * 1024 / 4096;
992236926Skib		sc->stolen_size = 1024 * 1024;
993171433Sanholt		break;
994236926Skib	case AGP_I830_GCC1_GMS_STOLEN_8192:
995236926Skib		sc->stolen = (8192 - 132) * 1024 / 4096;
996236926Skib		sc->stolen_size = 8192 * 1024;
997236926Skib		break;
998236926Skib	default:
999236926Skib		sc->stolen = 0;
1000236926Skib		device_printf(dev,
1001236926Skib		    "unknown memory configuration, disabling (GCC1 %x)\n",
1002236926Skib		    gcc1);
1003236926Skib		return (EINVAL);
1004236926Skib	}
1005236926Skib	return (0);
1006236926Skib}
1007236926Skib
1008236926Skibstatic int
1009236926Skibagp_i915_get_stolen_size(device_t dev)
1010236926Skib{
1011236926Skib	struct agp_i810_softc *sc;
1012236926Skib	unsigned int gcc1, stolen, gtt_size;
1013236926Skib
1014236926Skib	sc = device_get_softc(dev);
1015236926Skib
1016236926Skib	/*
1017236926Skib	 * Stolen memory is set up at the beginning of the aperture by
1018236926Skib	 * the BIOS, consisting of the GATT followed by 4kb for the
1019236926Skib	 * BIOS display.
1020236926Skib	 */
1021236926Skib	switch (sc->match->driver->chiptype) {
1022171433Sanholt	case CHIP_I855:
1023236926Skib		gtt_size = 128;
1024171433Sanholt		break;
1025171433Sanholt	case CHIP_I915:
1026236926Skib		gtt_size = 256;
1027236926Skib		break;
1028171433Sanholt	case CHIP_I965:
1029236926Skib		switch (bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL) &
1030236926Skib			AGP_I810_PGTBL_SIZE_MASK) {
1031236926Skib		case AGP_I810_PGTBL_SIZE_128KB:
1032236926Skib			gtt_size = 128;
1033236926Skib			break;
1034236926Skib		case AGP_I810_PGTBL_SIZE_256KB:
1035236926Skib			gtt_size = 256;
1036236926Skib			break;
1037236926Skib		case AGP_I810_PGTBL_SIZE_512KB:
1038236926Skib			gtt_size = 512;
1039236926Skib			break;
1040236926Skib		case AGP_I965_PGTBL_SIZE_1MB:
1041236926Skib			gtt_size = 1024;
1042236926Skib			break;
1043236926Skib		case AGP_I965_PGTBL_SIZE_2MB:
1044236926Skib			gtt_size = 2048;
1045236926Skib			break;
1046236926Skib		case AGP_I965_PGTBL_SIZE_1_5MB:
1047236926Skib			gtt_size = 1024 + 512;
1048236926Skib			break;
1049236926Skib		default:
1050236926Skib			device_printf(dev, "Bad PGTBL size\n");
1051236926Skib			return (EINVAL);
1052236926Skib		}
1053236926Skib		break;
1054171433Sanholt	case CHIP_G33:
1055236926Skib		gcc1 = pci_read_config(sc->bdev, AGP_I855_GCC1, 2);
1056236926Skib		switch (gcc1 & AGP_G33_MGGC_GGMS_MASK) {
1057236926Skib		case AGP_G33_MGGC_GGMS_SIZE_1M:
1058236926Skib			gtt_size = 1024;
1059236926Skib			break;
1060236926Skib		case AGP_G33_MGGC_GGMS_SIZE_2M:
1061236926Skib			gtt_size = 2048;
1062236926Skib			break;
1063236926Skib		default:
1064236926Skib			device_printf(dev, "Bad PGTBL size\n");
1065236926Skib			return (EINVAL);
1066236926Skib		}
1067236926Skib		break;
1068205102Srnoland	case CHIP_IGD:
1069186434Srnoland	case CHIP_G4X:
1070236926Skib		gtt_size = 0;
1071171433Sanholt		break;
1072236926Skib	default:
1073236926Skib		device_printf(dev, "Bad chiptype\n");
1074236926Skib		return (EINVAL);
1075171433Sanholt	}
1076236926Skib
1077236926Skib	/* GCC1 is called MGGC on i915+ */
1078236926Skib	gcc1 = pci_read_config(sc->bdev, AGP_I855_GCC1, 1);
1079236926Skib	switch (gcc1 & AGP_I855_GCC1_GMS) {
1080236926Skib	case AGP_I855_GCC1_GMS_STOLEN_1M:
1081236926Skib		stolen = 1024;
1082236926Skib		break;
1083236926Skib	case AGP_I855_GCC1_GMS_STOLEN_4M:
1084236926Skib		stolen = 4 * 1024;
1085236926Skib		break;
1086236926Skib	case AGP_I855_GCC1_GMS_STOLEN_8M:
1087236926Skib		stolen = 8 * 1024;
1088236926Skib		break;
1089236926Skib	case AGP_I855_GCC1_GMS_STOLEN_16M:
1090236926Skib		stolen = 16 * 1024;
1091236926Skib		break;
1092236926Skib	case AGP_I855_GCC1_GMS_STOLEN_32M:
1093236926Skib		stolen = 32 * 1024;
1094236926Skib		break;
1095236926Skib	case AGP_I915_GCC1_GMS_STOLEN_48M:
1096236926Skib		stolen = sc->match->driver->gen > 2 ? 48 * 1024 : 0;
1097236926Skib		break;
1098236926Skib	case AGP_I915_GCC1_GMS_STOLEN_64M:
1099236926Skib		stolen = sc->match->driver->gen > 2 ? 64 * 1024 : 0;
1100236926Skib		break;
1101236926Skib	case AGP_G33_GCC1_GMS_STOLEN_128M:
1102236926Skib		stolen = sc->match->driver->gen > 2 ? 128 * 1024 : 0;
1103236926Skib		break;
1104236926Skib	case AGP_G33_GCC1_GMS_STOLEN_256M:
1105236926Skib		stolen = sc->match->driver->gen > 2 ? 256 * 1024 : 0;
1106236926Skib		break;
1107236926Skib	case AGP_G4X_GCC1_GMS_STOLEN_96M:
1108236926Skib		if (sc->match->driver->chiptype == CHIP_I965 ||
1109236926Skib		    sc->match->driver->chiptype == CHIP_G4X)
1110236926Skib			stolen = 96 * 1024;
1111236926Skib		else
1112236926Skib			stolen = 0;
1113236926Skib		break;
1114236926Skib	case AGP_G4X_GCC1_GMS_STOLEN_160M:
1115236926Skib		if (sc->match->driver->chiptype == CHIP_I965 ||
1116236926Skib		    sc->match->driver->chiptype == CHIP_G4X)
1117236926Skib			stolen = 160 * 1024;
1118236926Skib		else
1119236926Skib			stolen = 0;
1120236926Skib		break;
1121236926Skib	case AGP_G4X_GCC1_GMS_STOLEN_224M:
1122236926Skib		if (sc->match->driver->chiptype == CHIP_I965 ||
1123236926Skib		    sc->match->driver->chiptype == CHIP_G4X)
1124236926Skib			stolen = 224 * 1024;
1125236926Skib		else
1126236926Skib			stolen = 0;
1127236926Skib		break;
1128236926Skib	case AGP_G4X_GCC1_GMS_STOLEN_352M:
1129236926Skib		if (sc->match->driver->chiptype == CHIP_I965 ||
1130236926Skib		    sc->match->driver->chiptype == CHIP_G4X)
1131236926Skib			stolen = 352 * 1024;
1132236926Skib		else
1133236926Skib			stolen = 0;
1134236926Skib		break;
1135236926Skib	default:
1136236926Skib		device_printf(dev,
1137236926Skib		    "unknown memory configuration, disabling (GCC1 %x)\n",
1138236926Skib		    gcc1);
1139236926Skib		return (EINVAL);
1140236926Skib	}
1141236926Skib
1142236926Skib	gtt_size += 4;
1143236926Skib	sc->stolen_size = stolen * 1024;
1144236926Skib	sc->stolen = (stolen - gtt_size) * 1024 / 4096;
1145236926Skib
1146236926Skib	return (0);
1147171433Sanholt}
1148171433Sanholt
114963010Sdfrstatic int
1150236926Skibagp_sb_get_stolen_size(device_t dev)
115163010Sdfr{
1152236926Skib	struct agp_i810_softc *sc;
1153236926Skib	uint16_t gmch_ctl;
115463010Sdfr
1155236926Skib	sc = device_get_softc(dev);
1156236926Skib	gmch_ctl = pci_read_config(sc->bdev, AGP_SNB_GCC1, 2);
1157236926Skib	switch (gmch_ctl & AGP_SNB_GMCH_GMS_STOLEN_MASK) {
1158236926Skib	case AGP_SNB_GMCH_GMS_STOLEN_32M:
1159236926Skib		sc->stolen_size = 32 * 1024 * 1024;
1160236926Skib		break;
1161236926Skib	case AGP_SNB_GMCH_GMS_STOLEN_64M:
1162236926Skib		sc->stolen_size = 64 * 1024 * 1024;
1163236926Skib		break;
1164236926Skib	case AGP_SNB_GMCH_GMS_STOLEN_96M:
1165236926Skib		sc->stolen_size = 96 * 1024 * 1024;
1166236926Skib		break;
1167236926Skib	case AGP_SNB_GMCH_GMS_STOLEN_128M:
1168236926Skib		sc->stolen_size = 128 * 1024 * 1024;
1169236926Skib		break;
1170236926Skib	case AGP_SNB_GMCH_GMS_STOLEN_160M:
1171236926Skib		sc->stolen_size = 160 * 1024 * 1024;
1172236926Skib		break;
1173236926Skib	case AGP_SNB_GMCH_GMS_STOLEN_192M:
1174236926Skib		sc->stolen_size = 192 * 1024 * 1024;
1175236926Skib		break;
1176236926Skib	case AGP_SNB_GMCH_GMS_STOLEN_224M:
1177236926Skib		sc->stolen_size = 224 * 1024 * 1024;
1178236926Skib		break;
1179236926Skib	case AGP_SNB_GMCH_GMS_STOLEN_256M:
1180236926Skib		sc->stolen_size = 256 * 1024 * 1024;
1181236926Skib		break;
1182236926Skib	case AGP_SNB_GMCH_GMS_STOLEN_288M:
1183236926Skib		sc->stolen_size = 288 * 1024 * 1024;
1184236926Skib		break;
1185236926Skib	case AGP_SNB_GMCH_GMS_STOLEN_320M:
1186236926Skib		sc->stolen_size = 320 * 1024 * 1024;
1187236926Skib		break;
1188236926Skib	case AGP_SNB_GMCH_GMS_STOLEN_352M:
1189236926Skib		sc->stolen_size = 352 * 1024 * 1024;
1190236926Skib		break;
1191236926Skib	case AGP_SNB_GMCH_GMS_STOLEN_384M:
1192236926Skib		sc->stolen_size = 384 * 1024 * 1024;
1193236926Skib		break;
1194236926Skib	case AGP_SNB_GMCH_GMS_STOLEN_416M:
1195236926Skib		sc->stolen_size = 416 * 1024 * 1024;
1196236926Skib		break;
1197236926Skib	case AGP_SNB_GMCH_GMS_STOLEN_448M:
1198236926Skib		sc->stolen_size = 448 * 1024 * 1024;
1199236926Skib		break;
1200236926Skib	case AGP_SNB_GMCH_GMS_STOLEN_480M:
1201236926Skib		sc->stolen_size = 480 * 1024 * 1024;
1202236926Skib		break;
1203236926Skib	case AGP_SNB_GMCH_GMS_STOLEN_512M:
1204236926Skib		sc->stolen_size = 512 * 1024 * 1024;
1205236926Skib		break;
1206236926Skib	}
1207236926Skib	sc->stolen = (sc->stolen_size - 4) / 4096;
1208236926Skib	return (0);
1209236926Skib}
121063010Sdfr
1211236926Skibstatic int
1212236926Skibagp_i810_get_gtt_mappable_entries(device_t dev)
1213236926Skib{
1214236926Skib	struct agp_i810_softc *sc;
1215236926Skib	uint32_t ap;
1216236926Skib	uint16_t miscc;
1217171433Sanholt
1218236926Skib	sc = device_get_softc(dev);
1219236926Skib	miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
1220236926Skib	if ((miscc & AGP_I810_MISCC_WINSIZE) == AGP_I810_MISCC_WINSIZE_32)
1221236926Skib		ap = 32;
1222236926Skib	else
1223236926Skib		ap = 64;
1224236926Skib	sc->gtt_mappable_entries = (ap * 1024 * 1024) >> AGP_PAGE_SHIFT;
1225236926Skib	return (0);
1226236926Skib}
1227236926Skib
1228236926Skibstatic int
1229236926Skibagp_i830_get_gtt_mappable_entries(device_t dev)
1230236926Skib{
1231236926Skib	struct agp_i810_softc *sc;
1232236926Skib	uint32_t ap;
1233236926Skib	uint16_t gmch_ctl;
1234236926Skib
1235236926Skib	sc = device_get_softc(dev);
1236236926Skib	gmch_ctl = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
1237236926Skib	if ((gmch_ctl & AGP_I830_GCC1_GMASIZE) == AGP_I830_GCC1_GMASIZE_64)
1238236926Skib		ap = 64;
1239236926Skib	else
1240236926Skib		ap = 128;
1241236926Skib	sc->gtt_mappable_entries = (ap * 1024 * 1024) >> AGP_PAGE_SHIFT;
1242236926Skib	return (0);
1243236926Skib}
1244236926Skib
1245236926Skibstatic int
1246236926Skibagp_i915_get_gtt_mappable_entries(device_t dev)
1247236926Skib{
1248236926Skib	struct agp_i810_softc *sc;
1249236926Skib	uint32_t ap;
1250236926Skib
1251236926Skib	sc = device_get_softc(dev);
1252236926Skib	ap = AGP_GET_APERTURE(dev);
1253236926Skib	sc->gtt_mappable_entries = ap >> AGP_PAGE_SHIFT;
1254236926Skib	return (0);
1255236926Skib}
1256236926Skib
1257236926Skibstatic int
1258236926Skibagp_i810_get_gtt_total_entries(device_t dev)
1259236926Skib{
1260236926Skib	struct agp_i810_softc *sc;
1261236926Skib
1262236926Skib	sc = device_get_softc(dev);
1263236926Skib	sc->gtt_total_entries = sc->gtt_mappable_entries;
1264236926Skib	return (0);
1265236926Skib}
1266236926Skib
1267236926Skibstatic int
1268236926Skibagp_i965_get_gtt_total_entries(device_t dev)
1269236926Skib{
1270236926Skib	struct agp_i810_softc *sc;
1271236926Skib	uint32_t pgetbl_ctl;
1272236926Skib	int error;
1273236926Skib
1274236926Skib	sc = device_get_softc(dev);
1275236926Skib	error = 0;
1276236926Skib	pgetbl_ctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
1277236926Skib	switch (pgetbl_ctl & AGP_I810_PGTBL_SIZE_MASK) {
1278236926Skib	case AGP_I810_PGTBL_SIZE_128KB:
1279236926Skib		sc->gtt_total_entries = 128 * 1024 / 4;
1280171433Sanholt		break;
1281236926Skib	case AGP_I810_PGTBL_SIZE_256KB:
1282236926Skib		sc->gtt_total_entries = 256 * 1024 / 4;
1283171433Sanholt		break;
1284236926Skib	case AGP_I810_PGTBL_SIZE_512KB:
1285236926Skib		sc->gtt_total_entries = 512 * 1024 / 4;
1286171433Sanholt		break;
1287236926Skib	/* GTT pagetable sizes bigger than 512KB are not possible on G33! */
1288236926Skib	case AGP_I810_PGTBL_SIZE_1MB:
1289236926Skib		sc->gtt_total_entries = 1024 * 1024 / 4;
1290236926Skib		break;
1291236926Skib	case AGP_I810_PGTBL_SIZE_2MB:
1292236926Skib		sc->gtt_total_entries = 2 * 1024 * 1024 / 4;
1293236926Skib		break;
1294236926Skib	case AGP_I810_PGTBL_SIZE_1_5MB:
1295236926Skib		sc->gtt_total_entries = (1024 + 512) * 1024 / 4;
1296236926Skib		break;
1297236926Skib	default:
1298236926Skib		device_printf(dev, "Unknown page table size\n");
1299236926Skib		error = ENXIO;
1300171433Sanholt	}
1301236926Skib	return (error);
1302236926Skib}
1303171433Sanholt
1304236926Skibstatic void
1305236926Skibagp_gen5_adjust_pgtbl_size(device_t dev, uint32_t sz)
1306236926Skib{
1307236926Skib	struct agp_i810_softc *sc;
1308236926Skib	uint32_t pgetbl_ctl, pgetbl_ctl2;
130963010Sdfr
1310236926Skib	sc = device_get_softc(dev);
1311236926Skib
1312236926Skib	/* Disable per-process page table. */
1313236926Skib	pgetbl_ctl2 = bus_read_4(sc->sc_res[0], AGP_I965_PGTBL_CTL2);
1314236926Skib	pgetbl_ctl2 &= ~AGP_I810_PGTBL_ENABLED;
1315236926Skib	bus_write_4(sc->sc_res[0], AGP_I965_PGTBL_CTL2, pgetbl_ctl2);
1316236926Skib
1317236926Skib	/* Write the new ggtt size. */
1318236926Skib	pgetbl_ctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
1319236926Skib	pgetbl_ctl &= ~AGP_I810_PGTBL_SIZE_MASK;
1320236926Skib	pgetbl_ctl |= sz;
1321236926Skib	bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgetbl_ctl);
1322236926Skib}
1323236926Skib
1324236926Skibstatic int
1325236926Skibagp_gen5_get_gtt_total_entries(device_t dev)
1326236926Skib{
1327236926Skib	struct agp_i810_softc *sc;
1328236926Skib	uint16_t gcc1;
1329236926Skib
1330236926Skib	sc = device_get_softc(dev);
1331236926Skib
1332236926Skib	gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
1333236926Skib	switch (gcc1 & AGP_G4x_GCC1_SIZE_MASK) {
1334236926Skib	case AGP_G4x_GCC1_SIZE_1M:
1335236926Skib	case AGP_G4x_GCC1_SIZE_VT_1M:
1336236926Skib		agp_gen5_adjust_pgtbl_size(dev, AGP_I810_PGTBL_SIZE_1MB);
1337236926Skib		break;
1338236926Skib	case AGP_G4x_GCC1_SIZE_VT_1_5M:
1339236926Skib		agp_gen5_adjust_pgtbl_size(dev, AGP_I810_PGTBL_SIZE_1_5MB);
1340236926Skib		break;
1341236926Skib	case AGP_G4x_GCC1_SIZE_2M:
1342236926Skib	case AGP_G4x_GCC1_SIZE_VT_2M:
1343236926Skib		agp_gen5_adjust_pgtbl_size(dev, AGP_I810_PGTBL_SIZE_2MB);
1344236926Skib		break;
1345236926Skib	default:
1346236926Skib		device_printf(dev, "Unknown page table size\n");
1347236926Skib		return (ENXIO);
1348171433Sanholt	}
1349103243Sanholt
1350236926Skib	return (agp_i965_get_gtt_total_entries(dev));
1351236926Skib}
1352236926Skib
1353236926Skibstatic int
1354236926Skibagp_sb_get_gtt_total_entries(device_t dev)
1355236926Skib{
1356236926Skib	struct agp_i810_softc *sc;
1357236926Skib	uint16_t gcc1;
1358236926Skib
1359236926Skib	sc = device_get_softc(dev);
1360236926Skib
1361236926Skib	gcc1 = pci_read_config(sc->bdev, AGP_SNB_GCC1, 2);
1362236926Skib	switch (gcc1 & AGP_SNB_GTT_SIZE_MASK) {
1363236926Skib	default:
1364236926Skib	case AGP_SNB_GTT_SIZE_0M:
1365236926Skib		printf("Bad GTT size mask: 0x%04x\n", gcc1);
1366236926Skib		return (ENXIO);
1367236926Skib	case AGP_SNB_GTT_SIZE_1M:
1368236926Skib		sc->gtt_total_entries = 1024 * 1024 / 4;
1369236926Skib		break;
1370236926Skib	case AGP_SNB_GTT_SIZE_2M:
1371236926Skib		sc->gtt_total_entries = 2 * 1024 * 1024 / 4;
1372236926Skib		break;
137363010Sdfr	}
1374236926Skib	return (0);
1375236926Skib}
137663010Sdfr
1377236926Skibstatic int
1378236926Skibagp_i810_install_gatt(device_t dev)
1379236926Skib{
1380236926Skib	struct agp_i810_softc *sc;
138163010Sdfr
1382236926Skib	sc = device_get_softc(dev);
1383236926Skib
1384236926Skib	/* Some i810s have on-chip memory called dcache. */
1385236926Skib	if ((bus_read_1(sc->sc_res[0], AGP_I810_DRT) & AGP_I810_DRT_POPULATED)
1386236926Skib	    != 0)
1387236926Skib		sc->dcache_size = 4 * 1024 * 1024;
1388236926Skib	else
1389236926Skib		sc->dcache_size = 0;
1390236926Skib
1391236926Skib	/* According to the specs the gatt on the i810 must be 64k. */
1392236926Skib	sc->gatt->ag_virtual = contigmalloc(64 * 1024, M_AGP, 0, 0, ~0,
1393236926Skib	    PAGE_SIZE, 0);
1394236926Skib	if (sc->gatt->ag_virtual == NULL) {
1395236926Skib		if (bootverbose)
1396236926Skib			device_printf(dev, "contiguous allocation failed\n");
1397236926Skib		return (ENOMEM);
1398103243Sanholt	}
139963010Sdfr
1400236926Skib	bzero(sc->gatt->ag_virtual, sc->gatt->ag_entries * sizeof(u_int32_t));
1401236926Skib	sc->gatt->ag_physical = vtophys((vm_offset_t)sc->gatt->ag_virtual);
1402236926Skib	agp_flush_cache();
1403236926Skib	/* Install the GATT. */
1404236926Skib	bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL,
1405236926Skib	    sc->gatt->ag_physical | 1);
1406236926Skib	return (0);
1407236926Skib}
140863010Sdfr
1409236926Skibstatic int
1410236926Skibagp_i830_install_gatt(device_t dev)
1411236926Skib{
1412236926Skib	struct agp_i810_softc *sc;
1413236926Skib	uint32_t pgtblctl;
1414103243Sanholt
1415236926Skib	sc = device_get_softc(dev);
1416236926Skib
1417236926Skib	/*
1418236926Skib	 * The i830 automatically initializes the 128k gatt on boot.
1419236926Skib	 * GATT address is already in there, make sure it's enabled.
1420236926Skib	 */
1421236926Skib	pgtblctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
1422236926Skib	pgtblctl |= 1;
1423236926Skib	bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgtblctl);
1424103243Sanholt
1425236926Skib	sc->gatt->ag_physical = pgtblctl & ~1;
1426236926Skib	return (0);
1427236926Skib}
1428103243Sanholt
1429236926Skibstatic int
1430236926Skibagp_i810_attach(device_t dev)
1431236926Skib{
1432236926Skib	struct agp_i810_softc *sc;
1433236926Skib	int error;
1434103243Sanholt
1435236926Skib	sc = device_get_softc(dev);
1436236926Skib	sc->bdev = agp_i810_find_bridge(dev);
1437236926Skib	if (sc->bdev == NULL)
1438236926Skib		return (ENOENT);
1439153031Sanholt
1440236926Skib	sc->match = agp_i810_match(dev);
1441171433Sanholt
1442236926Skib	agp_set_aperture_resource(dev, sc->match->driver->gen <= 2 ?
1443236926Skib	    AGP_APBASE : AGP_I915_GMADR);
1444236926Skib	error = agp_generic_attach(dev);
1445236926Skib	if (error)
1446236926Skib		return (error);
1447183555Srnoland
1448236926Skib	if (ptoa((vm_paddr_t)Maxmem) >
1449236926Skib	    (1ULL << sc->match->driver->busdma_addr_mask_sz) - 1) {
1450236926Skib		device_printf(dev, "agp_i810 does not support physical "
1451236926Skib		    "memory above %ju.\n", (uintmax_t)(1ULL <<
1452236926Skib		    sc->match->driver->busdma_addr_mask_sz) - 1);
1453236926Skib		return (ENOENT);
1454236926Skib	}
1455183555Srnoland
1456236926Skib	if (bus_alloc_resources(dev, sc->match->driver->res_spec, sc->sc_res)) {
1457236926Skib		agp_generic_detach(dev);
1458236926Skib		return (ENODEV);
1459236926Skib	}
1460110785Sanholt
1461236926Skib	sc->initial_aperture = AGP_GET_APERTURE(dev);
1462236926Skib	sc->gatt = malloc(sizeof(struct agp_gatt), M_AGP, M_WAITOK);
1463236926Skib	sc->gatt->ag_entries = AGP_GET_APERTURE(dev) >> AGP_PAGE_SHIFT;
1464110785Sanholt
1465236926Skib	if ((error = sc->match->driver->get_stolen_size(dev)) != 0 ||
1466236926Skib	    (error = sc->match->driver->install_gatt(dev)) != 0 ||
1467236926Skib	    (error = sc->match->driver->get_gtt_mappable_entries(dev)) != 0 ||
1468236926Skib	    (error = sc->match->driver->get_gtt_total_entries(dev)) != 0 ||
1469236926Skib	    (error = sc->match->driver->chipset_flush_setup(dev)) != 0) {
1470236926Skib		bus_release_resources(dev, sc->match->driver->res_spec,
1471236926Skib		    sc->sc_res);
1472236926Skib		free(sc->gatt, M_AGP);
1473236926Skib		agp_generic_detach(dev);
1474236926Skib		return (error);
147563010Sdfr	}
147663010Sdfr
1477236926Skib	intel_agp = dev;
1478197191Sn_hibma	device_printf(dev, "aperture size is %dM",
1479197191Sn_hibma	    sc->initial_aperture / 1024 / 1024);
1480197191Sn_hibma	if (sc->stolen > 0)
1481197191Sn_hibma		printf(", detected %dk stolen memory\n", sc->stolen * 4);
1482197191Sn_hibma	else
1483197191Sn_hibma		printf("\n");
1484236926Skib	if (bootverbose) {
1485236926Skib		sc->match->driver->dump_regs(dev);
1486236926Skib		device_printf(dev, "Mappable GTT entries: %d\n",
1487236926Skib		    sc->gtt_mappable_entries);
1488236926Skib		device_printf(dev, "Total GTT entries: %d\n",
1489236926Skib		    sc->gtt_total_entries);
1490236926Skib	}
1491236926Skib	return (0);
1492236926Skib}
1493197076Sn_hibma
1494236926Skibstatic void
1495236926Skibagp_i810_deinstall_gatt(device_t dev)
1496236926Skib{
1497236926Skib	struct agp_i810_softc *sc;
1498171433Sanholt
1499236926Skib	sc = device_get_softc(dev);
1500236926Skib	bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, 0);
1501236926Skib	contigfree(sc->gatt->ag_virtual, 64 * 1024, M_AGP);
150263010Sdfr}
150363010Sdfr
1504236926Skibstatic void
1505236926Skibagp_i830_deinstall_gatt(device_t dev)
1506236926Skib{
1507236926Skib	struct agp_i810_softc *sc;
1508236926Skib	unsigned int pgtblctl;
1509236926Skib
1510236926Skib	sc = device_get_softc(dev);
1511236926Skib	pgtblctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
1512236926Skib	pgtblctl &= ~1;
1513236926Skib	bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgtblctl);
1514236926Skib}
1515236926Skib
151663010Sdfrstatic int
151763010Sdfragp_i810_detach(device_t dev)
151863010Sdfr{
1519236926Skib	struct agp_i810_softc *sc;
152063010Sdfr
1521236926Skib	sc = device_get_softc(dev);
1522173203Sjhb	agp_free_cdev(dev);
152363010Sdfr
152463010Sdfr	/* Clear the GATT base. */
1525236926Skib	sc->match->driver->deinstall_gatt(dev);
152663010Sdfr
1527236926Skib	sc->match->driver->chipset_flush_teardown(dev);
1528236926Skib
152963010Sdfr	/* Put the aperture back the way it started. */
153063010Sdfr	AGP_SET_APERTURE(dev, sc->initial_aperture);
153163010Sdfr
1532103243Sanholt	free(sc->gatt, M_AGP);
1533236926Skib	bus_release_resources(dev, sc->match->driver->res_spec, sc->sc_res);
1534173203Sjhb	agp_free_res(dev);
153563010Sdfr
1536236926Skib	return (0);
153763010Sdfr}
153863010Sdfr
1539177115Sremkostatic int
1540177115Sremkoagp_i810_resume(device_t dev)
1541177115Sremko{
1542177115Sremko	struct agp_i810_softc *sc;
1543177115Sremko	sc = device_get_softc(dev);
1544177115Sremko
1545177115Sremko	AGP_SET_APERTURE(dev, sc->initial_aperture);
1546177115Sremko
1547177115Sremko	/* Install the GATT. */
1548177115Sremko	bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL,
1549177115Sremko	sc->gatt->ag_physical | 1);
1550177115Sremko
1551177115Sremko	return (bus_generic_resume(dev));
1552177115Sremko}
1553177115Sremko
1554171433Sanholt/**
1555171433Sanholt * Sets the PCI resource size of the aperture on i830-class and below chipsets,
1556171433Sanholt * while returning failure on later chipsets when an actual change is
1557171433Sanholt * requested.
1558171433Sanholt *
1559171433Sanholt * This whole function is likely bogus, as the kernel would probably need to
1560171433Sanholt * reconfigure the placement of the AGP aperture if a larger size is requested,
1561171433Sanholt * which doesn't happen currently.
1562171433Sanholt */
156363010Sdfrstatic int
156463010Sdfragp_i810_set_aperture(device_t dev, u_int32_t aperture)
156563010Sdfr{
1566236926Skib	struct agp_i810_softc *sc;
1567236926Skib	u_int16_t miscc;
156863010Sdfr
1569236926Skib	sc = device_get_softc(dev);
1570236926Skib	/*
1571236926Skib	 * Double check for sanity.
1572236926Skib	 */
1573236926Skib	if (aperture != 32 * 1024 * 1024 && aperture != 64 * 1024 * 1024) {
1574236926Skib		device_printf(dev, "bad aperture size %d\n", aperture);
1575236926Skib		return (EINVAL);
1576236926Skib	}
1577153031Sanholt
1578236926Skib	miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
1579236926Skib	miscc &= ~AGP_I810_MISCC_WINSIZE;
1580236926Skib	if (aperture == 32 * 1024 * 1024)
1581236926Skib		miscc |= AGP_I810_MISCC_WINSIZE_32;
1582236926Skib	else
1583236926Skib		miscc |= AGP_I810_MISCC_WINSIZE_64;
1584103243Sanholt
1585236926Skib	pci_write_config(sc->bdev, AGP_I810_MISCC, miscc, 2);
1586236926Skib	return (0);
1587236926Skib}
158863010Sdfr
1589236926Skibstatic int
1590236926Skibagp_i830_set_aperture(device_t dev, u_int32_t aperture)
1591236926Skib{
1592236926Skib	struct agp_i810_softc *sc;
1593236926Skib	u_int16_t gcc1;
1594236926Skib
1595236926Skib	sc = device_get_softc(dev);
1596236926Skib
1597236926Skib	if (aperture != 64 * 1024 * 1024 &&
1598236926Skib	    aperture != 128 * 1024 * 1024) {
1599236926Skib		device_printf(dev, "bad aperture size %d\n", aperture);
1600236926Skib		return (EINVAL);
1601171433Sanholt	}
1602236926Skib	gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
1603236926Skib	gcc1 &= ~AGP_I830_GCC1_GMASIZE;
1604236926Skib	if (aperture == 64 * 1024 * 1024)
1605236926Skib		gcc1 |= AGP_I830_GCC1_GMASIZE_64;
1606236926Skib	else
1607236926Skib		gcc1 |= AGP_I830_GCC1_GMASIZE_128;
1608153031Sanholt
1609236926Skib	pci_write_config(sc->bdev, AGP_I830_GCC1, gcc1, 2);
1610236926Skib	return (0);
1611171433Sanholt}
1612153031Sanholt
1613236926Skibstatic int
1614236926Skibagp_i915_set_aperture(device_t dev, u_int32_t aperture)
1615236926Skib{
1616236926Skib
1617236926Skib	return (agp_generic_set_aperture(dev, aperture));
1618236926Skib}
1619236926Skib
1620236926Skibstatic int
1621236926Skibagp_i810_method_set_aperture(device_t dev, u_int32_t aperture)
1622236926Skib{
1623236926Skib	struct agp_i810_softc *sc;
1624236926Skib
1625236926Skib	sc = device_get_softc(dev);
1626236926Skib	return (sc->match->driver->set_aperture(dev, aperture));
1627236926Skib}
1628236926Skib
1629171433Sanholt/**
1630236926Skib * Writes a GTT entry mapping the page at the given offset from the
1631236926Skib * beginning of the aperture to the given physical address.  Setup the
1632236926Skib * caching mode according to flags.
1633236926Skib *
1634236926Skib * For gen 1, 2 and 3, GTT start is located at AGP_I810_GTT offset
1635236926Skib * from corresponding BAR start. For gen 4, offset is 512KB +
1636236926Skib * AGP_I810_GTT, for gen 5 and 6 it is 2MB + AGP_I810_GTT.
1637236926Skib *
1638236926Skib * Also, the bits of the physical page address above 4GB needs to be
1639236926Skib * placed into bits 40-32 of PTE.
1640171433Sanholt */
1641171433Sanholtstatic void
1642236926Skibagp_i810_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
1643236926Skib    int flags)
1644171433Sanholt{
1645236926Skib	uint32_t pte;
1646171433Sanholt
1647236926Skib	pte = (u_int32_t)physical | I810_PTE_VALID;
1648236926Skib	if (flags == AGP_DCACHE_MEMORY)
1649236926Skib		pte |= I810_PTE_LOCAL;
1650236926Skib	else if (flags == AGP_USER_CACHED_MEMORY)
1651236926Skib		pte |= I830_PTE_SYSTEM_CACHED;
1652236926Skib	agp_i810_write_gtt(dev, index, pte);
1653236926Skib}
1654171433Sanholt
1655236926Skibstatic void
1656236926Skibagp_i810_write_gtt(device_t dev, u_int index, uint32_t pte)
1657236926Skib{
1658236926Skib	struct agp_i810_softc *sc;
1659236926Skib
1660236926Skib	sc = device_get_softc(dev);
1661236926Skib	bus_write_4(sc->sc_res[0], AGP_I810_GTT + index * 4, pte);
1662236926Skib	CTR2(KTR_AGP_I810, "810_pte %x %x", index, pte);
166363010Sdfr}
166463010Sdfr
1665236926Skibstatic void
1666236926Skibagp_i830_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
1667236926Skib    int flags)
1668236926Skib{
1669236926Skib	uint32_t pte;
1670236926Skib
1671236926Skib	pte = (u_int32_t)physical | I810_PTE_VALID;
1672236926Skib	if (flags == AGP_USER_CACHED_MEMORY)
1673236926Skib		pte |= I830_PTE_SYSTEM_CACHED;
1674236926Skib	agp_i810_write_gtt(dev, index, pte);
1675236926Skib}
1676236926Skib
1677236926Skibstatic void
1678236926Skibagp_i915_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
1679236926Skib    int flags)
1680236926Skib{
1681236926Skib	uint32_t pte;
1682236926Skib
1683236926Skib	pte = (u_int32_t)physical | I810_PTE_VALID;
1684236926Skib	if (flags == AGP_USER_CACHED_MEMORY)
1685236926Skib		pte |= I830_PTE_SYSTEM_CACHED;
1686236926Skib	pte |= (physical & 0x0000000f00000000ull) >> 28;
1687236926Skib	agp_i915_write_gtt(dev, index, pte);
1688236926Skib}
1689236926Skib
1690236926Skibstatic void
1691236926Skibagp_i915_write_gtt(device_t dev, u_int index, uint32_t pte)
1692236926Skib{
1693236926Skib	struct agp_i810_softc *sc;
1694236926Skib
1695236926Skib	sc = device_get_softc(dev);
1696236926Skib	bus_write_4(sc->sc_res[1], index * 4, pte);
1697236926Skib	CTR2(KTR_AGP_I810, "915_pte %x %x", index, pte);
1698236926Skib}
1699236926Skib
1700236926Skibstatic void
1701236926Skibagp_i965_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
1702236926Skib    int flags)
1703236926Skib{
1704236926Skib	uint32_t pte;
1705236926Skib
1706236926Skib	pte = (u_int32_t)physical | I810_PTE_VALID;
1707236926Skib	if (flags == AGP_USER_CACHED_MEMORY)
1708236926Skib		pte |= I830_PTE_SYSTEM_CACHED;
1709236926Skib	pte |= (physical & 0x0000000f00000000ull) >> 28;
1710236926Skib	agp_i965_write_gtt(dev, index, pte);
1711236926Skib}
1712236926Skib
1713236926Skibstatic void
1714236926Skibagp_i965_write_gtt(device_t dev, u_int index, uint32_t pte)
1715236926Skib{
1716236926Skib	struct agp_i810_softc *sc;
1717236926Skib
1718236926Skib	sc = device_get_softc(dev);
1719236926Skib	bus_write_4(sc->sc_res[0], index * 4 + (512 * 1024), pte);
1720236926Skib	CTR2(KTR_AGP_I810, "965_pte %x %x", index, pte);
1721236926Skib}
1722236926Skib
1723236926Skibstatic void
1724236926Skibagp_g4x_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
1725236926Skib    int flags)
1726236926Skib{
1727236926Skib	uint32_t pte;
1728236926Skib
1729236926Skib	pte = (u_int32_t)physical | I810_PTE_VALID;
1730236926Skib	if (flags == AGP_USER_CACHED_MEMORY)
1731236926Skib		pte |= I830_PTE_SYSTEM_CACHED;
1732236926Skib	pte |= (physical & 0x0000000f00000000ull) >> 28;
1733236926Skib	agp_g4x_write_gtt(dev, index, pte);
1734236926Skib}
1735236926Skib
1736236926Skibstatic void
1737236926Skibagp_g4x_write_gtt(device_t dev, u_int index, uint32_t pte)
1738236926Skib{
1739236926Skib	struct agp_i810_softc *sc;
1740236926Skib
1741236926Skib	sc = device_get_softc(dev);
1742236926Skib	bus_write_4(sc->sc_res[0], index * 4 + (2 * 1024 * 1024), pte);
1743236926Skib	CTR2(KTR_AGP_I810, "g4x_pte %x %x", index, pte);
1744236926Skib}
1745236926Skib
1746236926Skibstatic void
1747236926Skibagp_sb_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
1748236926Skib    int flags)
1749236926Skib{
1750236926Skib	int type_mask, gfdt;
1751236926Skib	uint32_t pte;
1752236926Skib
1753236926Skib	pte = (u_int32_t)physical | I810_PTE_VALID;
1754236926Skib	type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT;
1755236926Skib	gfdt = (flags & AGP_USER_CACHED_MEMORY_GFDT) != 0 ? GEN6_PTE_GFDT : 0;
1756236926Skib
1757236926Skib	if (type_mask == AGP_USER_MEMORY)
1758236926Skib		pte |= GEN6_PTE_UNCACHED;
1759236926Skib	else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC)
1760236926Skib		pte |= GEN6_PTE_LLC_MLC | gfdt;
1761236926Skib	else
1762236926Skib		pte |= GEN6_PTE_LLC | gfdt;
1763236926Skib
1764236926Skib	pte |= (physical & 0x000000ff00000000ull) >> 28;
1765236926Skib	agp_sb_write_gtt(dev, index, pte);
1766236926Skib}
1767236926Skib
1768236926Skibstatic void
1769236926Skibagp_sb_write_gtt(device_t dev, u_int index, uint32_t pte)
1770236926Skib{
1771236926Skib	struct agp_i810_softc *sc;
1772236926Skib
1773236926Skib	sc = device_get_softc(dev);
1774236926Skib	bus_write_4(sc->sc_res[0], index * 4 + (2 * 1024 * 1024), pte);
1775236926Skib	CTR2(KTR_AGP_I810, "sb_pte %x %x", index, pte);
1776236926Skib}
1777236926Skib
177863010Sdfrstatic int
1779189578Simpagp_i810_bind_page(device_t dev, vm_offset_t offset, vm_offset_t physical)
178063010Sdfr{
178163010Sdfr	struct agp_i810_softc *sc = device_get_softc(dev);
1782236926Skib	u_int index;
178363010Sdfr
1784190169Srnoland	if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) {
1785236926Skib		device_printf(dev, "failed: offset is 0x%08jx, "
1786236926Skib		    "shift is %d, entries is %d\n", (intmax_t)offset,
1787236926Skib		    AGP_PAGE_SHIFT, sc->gatt->ag_entries);
1788236926Skib		return (EINVAL);
1789103243Sanholt	}
1790236926Skib	index = offset >> AGP_PAGE_SHIFT;
1791236926Skib	if (sc->stolen != 0 && index < sc->stolen) {
1792236926Skib		device_printf(dev, "trying to bind into stolen memory\n");
1793236926Skib		return (EINVAL);
1794103243Sanholt	}
1795236926Skib	sc->match->driver->install_gtt_pte(dev, index, physical, 0);
1796236926Skib	return (0);
179763010Sdfr}
179863010Sdfr
179963010Sdfrstatic int
1800189578Simpagp_i810_unbind_page(device_t dev, vm_offset_t offset)
180163010Sdfr{
1802236926Skib	struct agp_i810_softc *sc;
1803236926Skib	u_int index;
180463010Sdfr
1805236926Skib	sc = device_get_softc(dev);
1806190169Srnoland	if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
1807236926Skib		return (EINVAL);
1808236926Skib	index = offset >> AGP_PAGE_SHIFT;
1809236926Skib	if (sc->stolen != 0 && index < sc->stolen) {
1810236926Skib		device_printf(dev, "trying to unbind from stolen memory\n");
1811236926Skib		return (EINVAL);
1812103243Sanholt	}
1813236926Skib	sc->match->driver->install_gtt_pte(dev, index, 0, 0);
1814236926Skib	return (0);
1815236926Skib}
1816103243Sanholt
1817236926Skibstatic u_int32_t
1818236926Skibagp_i810_read_gtt_pte(device_t dev, u_int index)
1819236926Skib{
1820236926Skib	struct agp_i810_softc *sc;
1821236926Skib	u_int32_t pte;
1822171433Sanholt
1823236926Skib	sc = device_get_softc(dev);
1824236926Skib	pte = bus_read_4(sc->sc_res[0], AGP_I810_GTT + index * 4);
1825236926Skib	return (pte);
182663010Sdfr}
182763010Sdfr
1828236926Skibstatic u_int32_t
1829236926Skibagp_i915_read_gtt_pte(device_t dev, u_int index)
1830236926Skib{
1831236926Skib	struct agp_i810_softc *sc;
1832236926Skib	u_int32_t pte;
1833236926Skib
1834236926Skib	sc = device_get_softc(dev);
1835236926Skib	pte = bus_read_4(sc->sc_res[1], index * 4);
1836236926Skib	return (pte);
1837236926Skib}
1838236926Skib
1839236926Skibstatic u_int32_t
1840236926Skibagp_i965_read_gtt_pte(device_t dev, u_int index)
1841236926Skib{
1842236926Skib	struct agp_i810_softc *sc;
1843236926Skib	u_int32_t pte;
1844236926Skib
1845236926Skib	sc = device_get_softc(dev);
1846236926Skib	pte = bus_read_4(sc->sc_res[0], index * 4 + (512 * 1024));
1847236926Skib	return (pte);
1848236926Skib}
1849236926Skib
1850236926Skibstatic u_int32_t
1851236926Skibagp_g4x_read_gtt_pte(device_t dev, u_int index)
1852236926Skib{
1853236926Skib	struct agp_i810_softc *sc;
1854236926Skib	u_int32_t pte;
1855236926Skib
1856236926Skib	sc = device_get_softc(dev);
1857236926Skib	pte = bus_read_4(sc->sc_res[0], index * 4 + (2 * 1024 * 1024));
1858236926Skib	return (pte);
1859236926Skib}
1860236926Skib
1861236926Skibstatic vm_paddr_t
1862236926Skibagp_i810_read_gtt_pte_paddr(device_t dev, u_int index)
1863236926Skib{
1864236926Skib	struct agp_i810_softc *sc;
1865236926Skib	u_int32_t pte;
1866236926Skib	vm_paddr_t res;
1867236926Skib
1868236926Skib	sc = device_get_softc(dev);
1869236926Skib	pte = sc->match->driver->read_gtt_pte(dev, index);
1870236926Skib	res = pte & ~PAGE_MASK;
1871236926Skib	return (res);
1872236926Skib}
1873236926Skib
1874236926Skibstatic vm_paddr_t
1875236926Skibagp_i915_read_gtt_pte_paddr(device_t dev, u_int index)
1876236926Skib{
1877236926Skib	struct agp_i810_softc *sc;
1878236926Skib	u_int32_t pte;
1879236926Skib	vm_paddr_t res;
1880236926Skib
1881236926Skib	sc = device_get_softc(dev);
1882236926Skib	pte = sc->match->driver->read_gtt_pte(dev, index);
1883236926Skib	res = (pte & ~PAGE_MASK) | ((pte & 0xf0) << 28);
1884236926Skib	return (res);
1885236926Skib}
1886236926Skib
1887236926Skibstatic vm_paddr_t
1888236926Skibagp_sb_read_gtt_pte_paddr(device_t dev, u_int index)
1889236926Skib{
1890236926Skib	struct agp_i810_softc *sc;
1891236926Skib	u_int32_t pte;
1892236926Skib	vm_paddr_t res;
1893236926Skib
1894236926Skib	sc = device_get_softc(dev);
1895236926Skib	pte = sc->match->driver->read_gtt_pte(dev, index);
1896236926Skib	res = (pte & ~PAGE_MASK) | ((pte & 0xff0) << 28);
1897236926Skib	return (res);
1898236926Skib}
1899236926Skib
190063010Sdfr/*
190163010Sdfr * Writing via memory mapped registers already flushes all TLBs.
190263010Sdfr */
190363010Sdfrstatic void
190463010Sdfragp_i810_flush_tlb(device_t dev)
190563010Sdfr{
190663010Sdfr}
190763010Sdfr
190863010Sdfrstatic int
190963010Sdfragp_i810_enable(device_t dev, u_int32_t mode)
191063010Sdfr{
191163010Sdfr
1912236926Skib	return (0);
191363010Sdfr}
191463010Sdfr
191563010Sdfrstatic struct agp_memory *
191663010Sdfragp_i810_alloc_memory(device_t dev, int type, vm_size_t size)
191763010Sdfr{
1918236926Skib	struct agp_i810_softc *sc;
191963010Sdfr	struct agp_memory *mem;
1920236926Skib	vm_page_t m;
192163010Sdfr
1922236926Skib	sc = device_get_softc(dev);
192363010Sdfr
1924236926Skib	if ((size & (AGP_PAGE_SIZE - 1)) != 0 ||
1925236926Skib	    sc->agp.as_allocated + size > sc->agp.as_maxmem)
1926236926Skib		return (0);
192763010Sdfr
192863010Sdfr	if (type == 1) {
192963010Sdfr		/*
193063010Sdfr		 * Mapping local DRAM into GATT.
193163010Sdfr		 */
1932236926Skib		if (sc->match->driver->chiptype != CHIP_I810)
1933236926Skib			return (0);
193463010Sdfr		if (size != sc->dcache_size)
1935236926Skib			return (0);
193663010Sdfr	} else if (type == 2) {
193763010Sdfr		/*
1938158655Sanholt		 * Type 2 is the contiguous physical memory type, that hands
1939158655Sanholt		 * back a physical address.  This is used for cursors on i810.
1940158655Sanholt		 * Hand back as many single pages with physical as the user
1941158655Sanholt		 * wants, but only allow one larger allocation (ARGB cursor)
1942158655Sanholt		 * for simplicity.
194363010Sdfr		 */
1944158655Sanholt		if (size != AGP_PAGE_SIZE) {
1945158655Sanholt			if (sc->argb_cursor != NULL)
1946236926Skib				return (0);
1947158655Sanholt
1948158655Sanholt			/* Allocate memory for ARGB cursor, if we can. */
1949158655Sanholt			sc->argb_cursor = contigmalloc(size, M_AGP,
1950158655Sanholt			   0, 0, ~0, PAGE_SIZE, 0);
1951158655Sanholt			if (sc->argb_cursor == NULL)
1952236926Skib				return (0);
1953158655Sanholt		}
195463010Sdfr	}
195563010Sdfr
1956111119Simp	mem = malloc(sizeof *mem, M_AGP, M_WAITOK);
195763010Sdfr	mem->am_id = sc->agp.as_nextid++;
195863010Sdfr	mem->am_size = size;
195963010Sdfr	mem->am_type = type;
1960158655Sanholt	if (type != 1 && (type != 2 || size == AGP_PAGE_SIZE))
196163010Sdfr		mem->am_obj = vm_object_allocate(OBJT_DEFAULT,
1962236926Skib		    atop(round_page(size)));
196363010Sdfr	else
196463010Sdfr		mem->am_obj = 0;
196563010Sdfr
196663010Sdfr	if (type == 2) {
1967158655Sanholt		if (size == AGP_PAGE_SIZE) {
1968158655Sanholt			/*
1969158655Sanholt			 * Allocate and wire down the page now so that we can
1970158655Sanholt			 * get its physical address.
1971158655Sanholt			 */
1972158655Sanholt			VM_OBJECT_LOCK(mem->am_obj);
1973158655Sanholt			m = vm_page_grab(mem->am_obj, 0, VM_ALLOC_NOBUSY |
1974158655Sanholt			    VM_ALLOC_WIRED | VM_ALLOC_ZERO | VM_ALLOC_RETRY);
1975158655Sanholt			VM_OBJECT_UNLOCK(mem->am_obj);
1976158655Sanholt			mem->am_physical = VM_PAGE_TO_PHYS(m);
1977158655Sanholt		} else {
1978158655Sanholt			/* Our allocation is already nicely wired down for us.
1979158655Sanholt			 * Just grab the physical address.
1980158655Sanholt			 */
1981158655Sanholt			mem->am_physical = vtophys(sc->argb_cursor);
1982158655Sanholt		}
1983236926Skib	} else
198463010Sdfr		mem->am_physical = 0;
198563010Sdfr
198663010Sdfr	mem->am_offset = 0;
198763010Sdfr	mem->am_is_bound = 0;
198863010Sdfr	TAILQ_INSERT_TAIL(&sc->agp.as_memory, mem, am_link);
198963010Sdfr	sc->agp.as_allocated += size;
199063010Sdfr
1991236926Skib	return (mem);
199263010Sdfr}
199363010Sdfr
199463010Sdfrstatic int
199563010Sdfragp_i810_free_memory(device_t dev, struct agp_memory *mem)
199663010Sdfr{
1997236926Skib	struct agp_i810_softc *sc;
1998236926Skib	vm_page_t m;
199963010Sdfr
200063010Sdfr	if (mem->am_is_bound)
2001236926Skib		return (EBUSY);
200263010Sdfr
2003236926Skib	sc = device_get_softc(dev);
2004236926Skib
200563010Sdfr	if (mem->am_type == 2) {
2006158655Sanholt		if (mem->am_size == AGP_PAGE_SIZE) {
2007158655Sanholt			/*
2008158655Sanholt			 * Unwire the page which we wired in alloc_memory.
2009158655Sanholt			 */
2010158655Sanholt			VM_OBJECT_LOCK(mem->am_obj);
2011158655Sanholt			m = vm_page_lookup(mem->am_obj, 0);
2012207574Salc			vm_page_lock(m);
2013158655Sanholt			vm_page_unwire(m, 0);
2014207574Salc			vm_page_unlock(m);
2015207574Salc			VM_OBJECT_UNLOCK(mem->am_obj);
2016158655Sanholt		} else {
2017158655Sanholt			contigfree(sc->argb_cursor, mem->am_size, M_AGP);
2018158655Sanholt			sc->argb_cursor = NULL;
2019158655Sanholt		}
202063010Sdfr	}
202163010Sdfr
202263010Sdfr	sc->agp.as_allocated -= mem->am_size;
202363010Sdfr	TAILQ_REMOVE(&sc->agp.as_memory, mem, am_link);
202463010Sdfr	if (mem->am_obj)
202563010Sdfr		vm_object_deallocate(mem->am_obj);
202663010Sdfr	free(mem, M_AGP);
2027236926Skib	return (0);
202863010Sdfr}
202963010Sdfr
203063010Sdfrstatic int
2031236926Skibagp_i810_bind_memory(device_t dev, struct agp_memory *mem, vm_offset_t offset)
203263010Sdfr{
2033236926Skib	struct agp_i810_softc *sc;
203463010Sdfr	vm_offset_t i;
203563010Sdfr
2036158655Sanholt	/* Do some sanity checks first. */
2037190169Srnoland	if ((offset & (AGP_PAGE_SIZE - 1)) != 0 ||
2038158655Sanholt	    offset + mem->am_size > AGP_GET_APERTURE(dev)) {
2039158655Sanholt		device_printf(dev, "binding memory at bad offset %#x\n",
2040158655Sanholt		    (int)offset);
2041236926Skib		return (EINVAL);
2042158655Sanholt	}
2043158655Sanholt
2044236926Skib	sc = device_get_softc(dev);
2045158655Sanholt	if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) {
2046158655Sanholt		mtx_lock(&sc->agp.as_lock);
2047158655Sanholt		if (mem->am_is_bound) {
2048158655Sanholt			mtx_unlock(&sc->agp.as_lock);
2049236926Skib			return (EINVAL);
2050158655Sanholt		}
2051158655Sanholt		/* The memory's already wired down, just stick it in the GTT. */
2052158655Sanholt		for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
2053236926Skib			sc->match->driver->install_gtt_pte(dev, (offset + i) >>
2054236926Skib			    AGP_PAGE_SHIFT, mem->am_physical + i, 0);
2055158655Sanholt		}
2056158655Sanholt		agp_flush_cache();
2057158655Sanholt		mem->am_offset = offset;
2058158655Sanholt		mem->am_is_bound = 1;
2059158655Sanholt		mtx_unlock(&sc->agp.as_lock);
2060236926Skib		return (0);
2061158655Sanholt	}
2062158655Sanholt
206363010Sdfr	if (mem->am_type != 1)
2064236926Skib		return (agp_generic_bind_memory(dev, mem, offset));
206563010Sdfr
2066236926Skib	/*
2067236926Skib	 * Mapping local DRAM into GATT.
2068236926Skib	 */
2069236926Skib	if (sc->match->driver->chiptype != CHIP_I810)
2070236926Skib		return (EINVAL);
2071236926Skib	for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
2072171433Sanholt		bus_write_4(sc->sc_res[0],
2073171433Sanholt		    AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, i | 3);
207463010Sdfr
2075236926Skib	return (0);
207663010Sdfr}
207763010Sdfr
207863010Sdfrstatic int
207963010Sdfragp_i810_unbind_memory(device_t dev, struct agp_memory *mem)
208063010Sdfr{
2081236926Skib	struct agp_i810_softc *sc;
208263010Sdfr	vm_offset_t i;
208363010Sdfr
2084236926Skib	sc = device_get_softc(dev);
2085236926Skib
2086158655Sanholt	if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) {
2087158655Sanholt		mtx_lock(&sc->agp.as_lock);
2088158655Sanholt		if (!mem->am_is_bound) {
2089158655Sanholt			mtx_unlock(&sc->agp.as_lock);
2090236926Skib			return (EINVAL);
2091158655Sanholt		}
2092158655Sanholt
2093158655Sanholt		for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
2094236926Skib			sc->match->driver->install_gtt_pte(dev,
2095236926Skib			    (mem->am_offset + i) >> AGP_PAGE_SHIFT, 0, 0);
2096158655Sanholt		}
2097158655Sanholt		agp_flush_cache();
2098158655Sanholt		mem->am_is_bound = 0;
2099158655Sanholt		mtx_unlock(&sc->agp.as_lock);
2100236926Skib		return (0);
2101158655Sanholt	}
2102158655Sanholt
210363010Sdfr	if (mem->am_type != 1)
2104236926Skib		return (agp_generic_unbind_memory(dev, mem));
210563010Sdfr
2106236926Skib	if (sc->match->driver->chiptype != CHIP_I810)
2107236926Skib		return (EINVAL);
2108171433Sanholt	for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
2109236926Skib		sc->match->driver->install_gtt_pte(dev, i >> AGP_PAGE_SHIFT,
2110236926Skib		    0, 0);
2111171433Sanholt	}
2112236926Skib	return (0);
211363010Sdfr}
211463010Sdfr
211563010Sdfrstatic device_method_t agp_i810_methods[] = {
211663010Sdfr	/* Device interface */
2117155186Sjhb	DEVMETHOD(device_identify,	agp_i810_identify),
211863010Sdfr	DEVMETHOD(device_probe,		agp_i810_probe),
211963010Sdfr	DEVMETHOD(device_attach,	agp_i810_attach),
212063010Sdfr	DEVMETHOD(device_detach,	agp_i810_detach),
2121177115Sremko	DEVMETHOD(device_suspend,	bus_generic_suspend),
2122177115Sremko	DEVMETHOD(device_resume,	agp_i810_resume),
212363010Sdfr
212463010Sdfr	/* AGP interface */
2125171433Sanholt	DEVMETHOD(agp_get_aperture,	agp_generic_get_aperture),
2126236926Skib	DEVMETHOD(agp_set_aperture,	agp_i810_method_set_aperture),
212763010Sdfr	DEVMETHOD(agp_bind_page,	agp_i810_bind_page),
212863010Sdfr	DEVMETHOD(agp_unbind_page,	agp_i810_unbind_page),
212963010Sdfr	DEVMETHOD(agp_flush_tlb,	agp_i810_flush_tlb),
213063010Sdfr	DEVMETHOD(agp_enable,		agp_i810_enable),
213163010Sdfr	DEVMETHOD(agp_alloc_memory,	agp_i810_alloc_memory),
213263010Sdfr	DEVMETHOD(agp_free_memory,	agp_i810_free_memory),
213363010Sdfr	DEVMETHOD(agp_bind_memory,	agp_i810_bind_memory),
213463010Sdfr	DEVMETHOD(agp_unbind_memory,	agp_i810_unbind_memory),
2135236926Skib	DEVMETHOD(agp_chipset_flush,	agp_intel_gtt_chipset_flush),
213663010Sdfr
213763010Sdfr	{ 0, 0 }
213863010Sdfr};
213963010Sdfr
214063010Sdfrstatic driver_t agp_i810_driver = {
214163010Sdfr	"agp",
214263010Sdfr	agp_i810_methods,
214363010Sdfr	sizeof(struct agp_i810_softc),
214463010Sdfr};
214563010Sdfr
214663010Sdfrstatic devclass_t agp_devclass;
214763010Sdfr
2148153579SjhbDRIVER_MODULE(agp_i810, vgapci, agp_i810_driver, agp_devclass, 0, 0);
2149113506SmdoddMODULE_DEPEND(agp_i810, agp, 1, 1, 1);
2150113506SmdoddMODULE_DEPEND(agp_i810, pci, 1, 1, 1);
2151236926Skib
2152236926Skibextern vm_page_t bogus_page;
2153236926Skib
2154236926Skibvoid
2155236926Skibagp_intel_gtt_clear_range(device_t dev, u_int first_entry, u_int num_entries)
2156236926Skib{
2157236926Skib	struct agp_i810_softc *sc;
2158236926Skib	u_int i;
2159236926Skib
2160236926Skib	sc = device_get_softc(dev);
2161236926Skib	for (i = 0; i < num_entries; i++)
2162236926Skib		sc->match->driver->install_gtt_pte(dev, first_entry + i,
2163236926Skib		    VM_PAGE_TO_PHYS(bogus_page), 0);
2164236926Skib	sc->match->driver->read_gtt_pte(dev, first_entry + num_entries - 1);
2165236926Skib}
2166236926Skib
2167236926Skibvoid
2168236926Skibagp_intel_gtt_insert_pages(device_t dev, u_int first_entry, u_int num_entries,
2169236926Skib    vm_page_t *pages, u_int flags)
2170236926Skib{
2171236926Skib	struct agp_i810_softc *sc;
2172236926Skib	u_int i;
2173236926Skib
2174236926Skib	sc = device_get_softc(dev);
2175236926Skib	for (i = 0; i < num_entries; i++) {
2176236926Skib		MPASS(pages[i]->valid == VM_PAGE_BITS_ALL);
2177236926Skib		MPASS(pages[i]->wire_count > 0);
2178236926Skib		sc->match->driver->install_gtt_pte(dev, first_entry + i,
2179236926Skib		    VM_PAGE_TO_PHYS(pages[i]), flags);
2180236926Skib	}
2181236926Skib	sc->match->driver->read_gtt_pte(dev, first_entry + num_entries - 1);
2182236926Skib}
2183236926Skib
2184236926Skibstruct intel_gtt
2185236926Skibagp_intel_gtt_get(device_t dev)
2186236926Skib{
2187236926Skib	struct agp_i810_softc *sc;
2188236926Skib	struct intel_gtt res;
2189236926Skib
2190236926Skib	sc = device_get_softc(dev);
2191236926Skib	res.stolen_size = sc->stolen_size;
2192236926Skib	res.gtt_total_entries = sc->gtt_total_entries;
2193236926Skib	res.gtt_mappable_entries = sc->gtt_mappable_entries;
2194236926Skib	res.do_idle_maps = 0;
2195236926Skib	res.scratch_page_dma = VM_PAGE_TO_PHYS(bogus_page);
2196236926Skib	return (res);
2197236926Skib}
2198236926Skib
2199236926Skibstatic int
2200236926Skibagp_i810_chipset_flush_setup(device_t dev)
2201236926Skib{
2202236926Skib
2203236926Skib	return (0);
2204236926Skib}
2205236926Skib
2206236926Skibstatic void
2207236926Skibagp_i810_chipset_flush_teardown(device_t dev)
2208236926Skib{
2209236926Skib
2210236926Skib	/* Nothing to do. */
2211236926Skib}
2212236926Skib
2213236926Skibstatic void
2214236926Skibagp_i810_chipset_flush(device_t dev)
2215236926Skib{
2216236926Skib
2217236926Skib	/* Nothing to do. */
2218236926Skib}
2219236926Skib
2220236926Skibstatic void
2221236926Skibagp_i830_chipset_flush(device_t dev)
2222236926Skib{
2223236926Skib	struct agp_i810_softc *sc;
2224236926Skib	uint32_t hic;
2225236926Skib	int i;
2226236926Skib
2227236926Skib	sc = device_get_softc(dev);
2228236926Skib	pmap_invalidate_cache();
2229236926Skib	hic = bus_read_4(sc->sc_res[0], AGP_I830_HIC);
2230236926Skib	bus_write_4(sc->sc_res[0], AGP_I830_HIC, hic | (1 << 31));
2231236926Skib	for (i = 0; i < 20000 /* 1 sec */; i++) {
2232236926Skib		hic = bus_read_4(sc->sc_res[0], AGP_I830_HIC);
2233246611Skib		if ((hic & (1 << 31)) == 0)
2234236926Skib			break;
2235236926Skib		DELAY(50);
2236236926Skib	}
2237236926Skib}
2238236926Skib
2239236926Skibstatic int
2240236926Skibagp_i915_chipset_flush_alloc_page(device_t dev, uint64_t start, uint64_t end)
2241236926Skib{
2242236926Skib	struct agp_i810_softc *sc;
2243236926Skib	device_t vga;
2244236926Skib
2245236926Skib	sc = device_get_softc(dev);
2246236926Skib	vga = device_get_parent(dev);
2247236926Skib	sc->sc_flush_page_rid = 100;
2248236926Skib	sc->sc_flush_page_res = BUS_ALLOC_RESOURCE(device_get_parent(vga), dev,
2249236926Skib	    SYS_RES_MEMORY, &sc->sc_flush_page_rid, start, end, PAGE_SIZE,
2250236926Skib	    RF_ACTIVE);
2251236926Skib	if (sc->sc_flush_page_res == NULL) {
2252236926Skib		device_printf(dev, "Failed to allocate flush page at 0x%jx\n",
2253236926Skib		    (uintmax_t)start);
2254236926Skib		return (EINVAL);
2255236926Skib	}
2256236926Skib	sc->sc_flush_page_vaddr = rman_get_virtual(sc->sc_flush_page_res);
2257236926Skib	if (bootverbose) {
2258236926Skib		device_printf(dev, "Allocated flush page phys 0x%jx virt %p\n",
2259236926Skib		    (uintmax_t)rman_get_start(sc->sc_flush_page_res),
2260236926Skib		    sc->sc_flush_page_vaddr);
2261236926Skib	}
2262236926Skib	return (0);
2263236926Skib}
2264236926Skib
2265236926Skibstatic void
2266236926Skibagp_i915_chipset_flush_free_page(device_t dev)
2267236926Skib{
2268236926Skib	struct agp_i810_softc *sc;
2269236926Skib	device_t vga;
2270236926Skib
2271236926Skib	sc = device_get_softc(dev);
2272236926Skib	vga = device_get_parent(dev);
2273236926Skib	if (sc->sc_flush_page_res == NULL)
2274236926Skib		return;
2275236926Skib	BUS_DEACTIVATE_RESOURCE(device_get_parent(vga), dev, SYS_RES_MEMORY,
2276236926Skib	    sc->sc_flush_page_rid, sc->sc_flush_page_res);
2277236926Skib	BUS_RELEASE_RESOURCE(device_get_parent(vga), dev, SYS_RES_MEMORY,
2278236926Skib	    sc->sc_flush_page_rid, sc->sc_flush_page_res);
2279236926Skib}
2280236926Skib
2281236926Skibstatic int
2282236926Skibagp_i915_chipset_flush_setup(device_t dev)
2283236926Skib{
2284236926Skib	struct agp_i810_softc *sc;
2285236926Skib	uint32_t temp;
2286236926Skib	int error;
2287236926Skib
2288236926Skib	sc = device_get_softc(dev);
2289236926Skib	temp = pci_read_config(sc->bdev, AGP_I915_IFPADDR, 4);
2290236926Skib	if ((temp & 1) != 0) {
2291236926Skib		temp &= ~1;
2292236926Skib		if (bootverbose)
2293236926Skib			device_printf(dev,
2294236926Skib			    "Found already configured flush page at 0x%jx\n",
2295236926Skib			    (uintmax_t)temp);
2296236926Skib		sc->sc_bios_allocated_flush_page = 1;
2297236926Skib		/*
2298236926Skib		 * In the case BIOS initialized the flush pointer (?)
2299236926Skib		 * register, expect that BIOS also set up the resource
2300236926Skib		 * for the page.
2301236926Skib		 */
2302236926Skib		error = agp_i915_chipset_flush_alloc_page(dev, temp,
2303236926Skib		    temp + PAGE_SIZE - 1);
2304236926Skib		if (error != 0)
2305236926Skib			return (error);
2306236926Skib	} else {
2307236926Skib		sc->sc_bios_allocated_flush_page = 0;
2308236926Skib		error = agp_i915_chipset_flush_alloc_page(dev, 0, 0xffffffff);
2309236926Skib		if (error != 0)
2310236926Skib			return (error);
2311236926Skib		temp = rman_get_start(sc->sc_flush_page_res);
2312236926Skib		pci_write_config(sc->bdev, AGP_I915_IFPADDR, temp | 1, 4);
2313236926Skib	}
2314236926Skib	return (0);
2315236926Skib}
2316236926Skib
2317236926Skibstatic void
2318236926Skibagp_i915_chipset_flush_teardown(device_t dev)
2319236926Skib{
2320236926Skib	struct agp_i810_softc *sc;
2321236926Skib	uint32_t temp;
2322236926Skib
2323236926Skib	sc = device_get_softc(dev);
2324236926Skib	if (sc->sc_flush_page_res == NULL)
2325236926Skib		return;
2326236926Skib	if (!sc->sc_bios_allocated_flush_page) {
2327236926Skib		temp = pci_read_config(sc->bdev, AGP_I915_IFPADDR, 4);
2328236926Skib		temp &= ~1;
2329236926Skib		pci_write_config(sc->bdev, AGP_I915_IFPADDR, temp, 4);
2330236926Skib	}
2331236926Skib	agp_i915_chipset_flush_free_page(dev);
2332236926Skib}
2333236926Skib
2334236926Skibstatic int
2335236926Skibagp_i965_chipset_flush_setup(device_t dev)
2336236926Skib{
2337236926Skib	struct agp_i810_softc *sc;
2338236926Skib	uint64_t temp;
2339236926Skib	uint32_t temp_hi, temp_lo;
2340236926Skib	int error;
2341236926Skib
2342236926Skib	sc = device_get_softc(dev);
2343236926Skib
2344236926Skib	temp_hi = pci_read_config(sc->bdev, AGP_I965_IFPADDR + 4, 4);
2345236926Skib	temp_lo = pci_read_config(sc->bdev, AGP_I965_IFPADDR, 4);
2346236926Skib
2347236926Skib	if ((temp_lo & 1) != 0) {
2348236926Skib		temp = ((uint64_t)temp_hi << 32) | (temp_lo & ~1);
2349236926Skib		if (bootverbose)
2350236926Skib			device_printf(dev,
2351236926Skib			    "Found already configured flush page at 0x%jx\n",
2352236926Skib			    (uintmax_t)temp);
2353236926Skib		sc->sc_bios_allocated_flush_page = 1;
2354236926Skib		/*
2355236926Skib		 * In the case BIOS initialized the flush pointer (?)
2356236926Skib		 * register, expect that BIOS also set up the resource
2357236926Skib		 * for the page.
2358236926Skib		 */
2359236926Skib		error = agp_i915_chipset_flush_alloc_page(dev, temp,
2360236926Skib		    temp + PAGE_SIZE - 1);
2361236926Skib		if (error != 0)
2362236926Skib			return (error);
2363236926Skib	} else {
2364236926Skib		sc->sc_bios_allocated_flush_page = 0;
2365236926Skib		error = agp_i915_chipset_flush_alloc_page(dev, 0, ~0);
2366236926Skib		if (error != 0)
2367236926Skib			return (error);
2368236926Skib		temp = rman_get_start(sc->sc_flush_page_res);
2369236926Skib		pci_write_config(sc->bdev, AGP_I965_IFPADDR + 4,
2370236926Skib		    (temp >> 32) & UINT32_MAX, 4);
2371236926Skib		pci_write_config(sc->bdev, AGP_I965_IFPADDR,
2372236926Skib		    (temp & UINT32_MAX) | 1, 4);
2373236926Skib	}
2374236926Skib	return (0);
2375236926Skib}
2376236926Skib
2377236926Skibstatic void
2378236926Skibagp_i965_chipset_flush_teardown(device_t dev)
2379236926Skib{
2380236926Skib	struct agp_i810_softc *sc;
2381236926Skib	uint32_t temp_lo;
2382236926Skib
2383236926Skib	sc = device_get_softc(dev);
2384236926Skib	if (sc->sc_flush_page_res == NULL)
2385236926Skib		return;
2386236926Skib	if (!sc->sc_bios_allocated_flush_page) {
2387236926Skib		temp_lo = pci_read_config(sc->bdev, AGP_I965_IFPADDR, 4);
2388236926Skib		temp_lo &= ~1;
2389236926Skib		pci_write_config(sc->bdev, AGP_I965_IFPADDR, temp_lo, 4);
2390236926Skib	}
2391236926Skib	agp_i915_chipset_flush_free_page(dev);
2392236926Skib}
2393236926Skib
2394236926Skibstatic void
2395236926Skibagp_i915_chipset_flush(device_t dev)
2396236926Skib{
2397236926Skib	struct agp_i810_softc *sc;
2398236926Skib
2399236926Skib	sc = device_get_softc(dev);
2400236926Skib	*(uint32_t *)sc->sc_flush_page_vaddr = 1;
2401236926Skib}
2402236926Skib
2403236926Skibint
2404236926Skibagp_intel_gtt_chipset_flush(device_t dev)
2405236926Skib{
2406236926Skib	struct agp_i810_softc *sc;
2407236926Skib
2408236926Skib	sc = device_get_softc(dev);
2409236926Skib	sc->match->driver->chipset_flush(dev);
2410236926Skib	return (0);
2411236926Skib}
2412236926Skib
2413236926Skibvoid
2414236926Skibagp_intel_gtt_unmap_memory(device_t dev, struct sglist *sg_list)
2415236926Skib{
2416236926Skib}
2417236926Skib
2418236926Skibint
2419236926Skibagp_intel_gtt_map_memory(device_t dev, vm_page_t *pages, u_int num_entries,
2420236926Skib    struct sglist **sg_list)
2421236926Skib{
2422236926Skib	struct agp_i810_softc *sc;
2423236926Skib	struct sglist *sg;
2424236926Skib	int i;
2425236926Skib#if 0
2426236926Skib	int error;
2427236926Skib	bus_dma_tag_t dmat;
2428236926Skib#endif
2429236926Skib
2430236926Skib	if (*sg_list != NULL)
2431236926Skib		return (0);
2432236926Skib	sc = device_get_softc(dev);
2433236926Skib	sg = sglist_alloc(num_entries, M_WAITOK /* XXXKIB */);
2434236926Skib	for (i = 0; i < num_entries; i++) {
2435236926Skib		sg->sg_segs[i].ss_paddr = VM_PAGE_TO_PHYS(pages[i]);
2436236926Skib		sg->sg_segs[i].ss_len = PAGE_SIZE;
2437236926Skib	}
2438236926Skib
2439236926Skib#if 0
2440236926Skib	error = bus_dma_tag_create(bus_get_dma_tag(dev),
2441236926Skib	    1 /* alignment */, 0 /* boundary */,
2442236926Skib	    1ULL << sc->match->busdma_addr_mask_sz /* lowaddr */,
2443236926Skib	    BUS_SPACE_MAXADDR /* highaddr */,
2444236926Skib            NULL /* filtfunc */, NULL /* filtfuncarg */,
2445236926Skib	    BUS_SPACE_MAXADDR /* maxsize */,
2446236926Skib	    BUS_SPACE_UNRESTRICTED /* nsegments */,
2447236926Skib	    BUS_SPACE_MAXADDR /* maxsegsz */,
2448236926Skib	    0 /* flags */, NULL /* lockfunc */, NULL /* lockfuncarg */,
2449236926Skib	    &dmat);
2450236926Skib	if (error != 0) {
2451236926Skib		sglist_free(sg);
2452236926Skib		return (error);
2453236926Skib	}
2454236926Skib	/* XXXKIB */
2455236926Skib#endif
2456236926Skib	*sg_list = sg;
2457236926Skib	return (0);
2458236926Skib}
2459236926Skib
2460236926Skibvoid
2461236926Skibagp_intel_gtt_insert_sg_entries(device_t dev, struct sglist *sg_list,
2462236926Skib    u_int first_entry, u_int flags)
2463236926Skib{
2464236926Skib	struct agp_i810_softc *sc;
2465236926Skib	vm_paddr_t spaddr;
2466236926Skib	size_t slen;
2467236926Skib	u_int i, j;
2468236926Skib
2469236926Skib	sc = device_get_softc(dev);
2470236926Skib	for (i = j = 0; j < sg_list->sg_nseg; j++) {
2471236926Skib		spaddr = sg_list->sg_segs[i].ss_paddr;
2472236926Skib		slen = sg_list->sg_segs[i].ss_len;
2473236926Skib		for (; slen > 0; i++) {
2474236926Skib			sc->match->driver->install_gtt_pte(dev, first_entry + i,
2475236926Skib			    spaddr, flags);
2476236926Skib			spaddr += AGP_PAGE_SIZE;
2477236926Skib			slen -= AGP_PAGE_SIZE;
2478236926Skib		}
2479236926Skib	}
2480236926Skib	sc->match->driver->read_gtt_pte(dev, first_entry + i - 1);
2481236926Skib}
2482236926Skib
2483236926Skibvoid
2484236926Skibintel_gtt_clear_range(u_int first_entry, u_int num_entries)
2485236926Skib{
2486236926Skib
2487236926Skib	agp_intel_gtt_clear_range(intel_agp, first_entry, num_entries);
2488236926Skib}
2489236926Skib
2490236926Skibvoid
2491236926Skibintel_gtt_insert_pages(u_int first_entry, u_int num_entries, vm_page_t *pages,
2492236926Skib    u_int flags)
2493236926Skib{
2494236926Skib
2495236926Skib	agp_intel_gtt_insert_pages(intel_agp, first_entry, num_entries,
2496236926Skib	    pages, flags);
2497236926Skib}
2498236926Skib
2499236926Skibstruct intel_gtt
2500236926Skibintel_gtt_get(void)
2501236926Skib{
2502236926Skib
2503236926Skib	return (agp_intel_gtt_get(intel_agp));
2504236926Skib}
2505236926Skib
2506236926Skibint
2507236926Skibintel_gtt_chipset_flush(void)
2508236926Skib{
2509236926Skib
2510236926Skib	return (agp_intel_gtt_chipset_flush(intel_agp));
2511236926Skib}
2512236926Skib
2513236926Skibvoid
2514236926Skibintel_gtt_unmap_memory(struct sglist *sg_list)
2515236926Skib{
2516236926Skib
2517236926Skib	agp_intel_gtt_unmap_memory(intel_agp, sg_list);
2518236926Skib}
2519236926Skib
2520236926Skibint
2521236926Skibintel_gtt_map_memory(vm_page_t *pages, u_int num_entries,
2522236926Skib    struct sglist **sg_list)
2523236926Skib{
2524236926Skib
2525236926Skib	return (agp_intel_gtt_map_memory(intel_agp, pages, num_entries,
2526236926Skib	    sg_list));
2527236926Skib}
2528236926Skib
2529236926Skibvoid
2530236926Skibintel_gtt_insert_sg_entries(struct sglist *sg_list, u_int first_entry,
2531236926Skib    u_int flags)
2532236926Skib{
2533236926Skib
2534236926Skib	agp_intel_gtt_insert_sg_entries(intel_agp, sg_list, first_entry, flags);
2535236926Skib}
2536236926Skib
2537236926Skibdevice_t
2538236926Skibintel_gtt_get_bridge_device(void)
2539236926Skib{
2540236926Skib	struct agp_i810_softc *sc;
2541236926Skib
2542236926Skib	sc = device_get_softc(intel_agp);
2543236926Skib	return (sc->bdev);
2544236926Skib}
2545236926Skib
2546236926Skibvm_paddr_t
2547236926Skibintel_gtt_read_pte_paddr(u_int entry)
2548236926Skib{
2549236926Skib	struct agp_i810_softc *sc;
2550236926Skib
2551236926Skib	sc = device_get_softc(intel_agp);
2552236926Skib	return (sc->match->driver->read_gtt_pte_paddr(intel_agp, entry));
2553236926Skib}
2554236926Skib
2555236926Skibu_int32_t
2556236926Skibintel_gtt_read_pte(u_int entry)
2557236926Skib{
2558236926Skib	struct agp_i810_softc *sc;
2559236926Skib
2560236926Skib	sc = device_get_softc(intel_agp);
2561236926Skib	return (sc->match->driver->read_gtt_pte(intel_agp, entry));
2562236926Skib}
2563236926Skib
2564236926Skibvoid
2565236926Skibintel_gtt_write(u_int entry, uint32_t val)
2566236926Skib{
2567236926Skib	struct agp_i810_softc *sc;
2568236926Skib
2569236926Skib	sc = device_get_softc(intel_agp);
2570236926Skib	return (sc->match->driver->write_gtt(intel_agp, entry, val));
2571236926Skib}
2572