xref: /dflybsd-src/sys/dev/agp/intel-gtt.c (revision a85cb24f18e3804e75ab8bcda7692564d0563317)
18621f407SFrançois Tigeot /*
28621f407SFrançois Tigeot  * Copyright (c) 2000 Doug Rabson
38621f407SFrançois Tigeot  * Copyright (c) 2000 Ruslan Ermilov
48621f407SFrançois Tigeot  * Copyright (c) 2011 The FreeBSD Foundation
51487f786SFrançois Tigeot  * Copyright (c) 2017-2019 François Tigeot <ftigeot@wolfpond.org>
68621f407SFrançois Tigeot  * All rights reserved.
78621f407SFrançois Tigeot  *
88621f407SFrançois Tigeot  * Portions of this software were developed by Konstantin Belousov
98621f407SFrançois Tigeot  * under sponsorship from the FreeBSD Foundation.
108621f407SFrançois Tigeot  *
118621f407SFrançois Tigeot  * Redistribution and use in source and binary forms, with or without
128621f407SFrançois Tigeot  * modification, are permitted provided that the following conditions
138621f407SFrançois Tigeot  * are met:
148621f407SFrançois Tigeot  * 1. Redistributions of source code must retain the above copyright
158621f407SFrançois Tigeot  *    notice, this list of conditions and the following disclaimer.
168621f407SFrançois Tigeot  * 2. Redistributions in binary form must reproduce the above copyright
178621f407SFrançois Tigeot  *    notice, this list of conditions and the following disclaimer in the
188621f407SFrançois Tigeot  *    documentation and/or other materials provided with the distribution.
198621f407SFrançois Tigeot  *
208621f407SFrançois Tigeot  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
218621f407SFrançois Tigeot  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
228621f407SFrançois Tigeot  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
238621f407SFrançois Tigeot  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
248621f407SFrançois Tigeot  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
258621f407SFrançois Tigeot  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
268621f407SFrançois Tigeot  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
278621f407SFrançois Tigeot  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
288621f407SFrançois Tigeot  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
298621f407SFrançois Tigeot  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
308621f407SFrançois Tigeot  * SUCH DAMAGE.
318621f407SFrançois Tigeot  */
328621f407SFrançois Tigeot 
338621f407SFrançois Tigeot /*
348621f407SFrançois Tigeot  * Fixes for 830/845G support: David Dawes <dawes@xfree86.org>
358621f407SFrançois Tigeot  * 852GM/855GM/865G support added by David Dawes <dawes@xfree86.org>
368621f407SFrançois Tigeot  *
378621f407SFrançois Tigeot  * This is generic Intel GTT handling code, morphed from the AGP
388621f407SFrançois Tigeot  * bridge code.
398621f407SFrançois Tigeot  */
408621f407SFrançois Tigeot 
418621f407SFrançois Tigeot #if 0
428621f407SFrançois Tigeot #define	KTR_AGP_I810	KTR_DEV
438621f407SFrançois Tigeot #else
448621f407SFrançois Tigeot #define	KTR_AGP_I810	0
458621f407SFrançois Tigeot #endif
468621f407SFrançois Tigeot 
478621f407SFrançois Tigeot #include <sys/param.h>
488621f407SFrançois Tigeot #include <sys/systm.h>
498621f407SFrançois Tigeot #include <sys/malloc.h>
508621f407SFrançois Tigeot #include <sys/kernel.h>
518621f407SFrançois Tigeot #include <sys/bus.h>
528621f407SFrançois Tigeot #include <sys/lock.h>
538621f407SFrançois Tigeot #include <sys/rman.h>
548621f407SFrançois Tigeot 
558621f407SFrançois Tigeot #include "pcidevs.h"
568621f407SFrançois Tigeot #include <bus/pci/pcivar.h>
578621f407SFrançois Tigeot #include <bus/pci/pcireg.h>
588621f407SFrançois Tigeot #include "agppriv.h"
598621f407SFrançois Tigeot #include "agpreg.h"
608621f407SFrançois Tigeot 
618621f407SFrançois Tigeot #include <vm/vm.h>
628621f407SFrançois Tigeot #include <vm/vm_object.h>
638621f407SFrançois Tigeot #include <vm/vm_page.h>
648621f407SFrançois Tigeot #include <vm/vm_param.h>
658621f407SFrançois Tigeot #include <vm/vm_pageout.h>
668621f407SFrançois Tigeot #include <vm/pmap.h>
678621f407SFrançois Tigeot 
688621f407SFrançois Tigeot #include <vm/vm_page2.h>
698621f407SFrançois Tigeot 
708621f407SFrançois Tigeot #include <machine/md_var.h>
718621f407SFrançois Tigeot 
728621f407SFrançois Tigeot #include <linux/slab.h>
738621f407SFrançois Tigeot #include <linux/scatterlist.h>
748621f407SFrançois Tigeot #include <drm/intel-gtt.h>
758621f407SFrançois Tigeot 
768621f407SFrançois Tigeot struct agp_i810_match;
778621f407SFrançois Tigeot 
788621f407SFrançois Tigeot static int agp_i915_check_active(device_t bridge_dev);
798621f407SFrançois Tigeot 
808621f407SFrançois Tigeot static void agp_i810_set_desc(device_t dev, const struct agp_i810_match *match);
818621f407SFrançois Tigeot 
828621f407SFrançois Tigeot static void agp_i915_dump_regs(device_t dev);
838621f407SFrançois Tigeot static void agp_i965_dump_regs(device_t dev);
848621f407SFrançois Tigeot 
858621f407SFrançois Tigeot static int agp_i915_get_stolen_size(device_t dev);
868621f407SFrançois Tigeot 
878621f407SFrançois Tigeot static int agp_i915_get_gtt_mappable_entries(device_t dev);
888621f407SFrançois Tigeot 
898621f407SFrançois Tigeot static int agp_i810_get_gtt_total_entries(device_t dev);
908621f407SFrançois Tigeot static int agp_i965_get_gtt_total_entries(device_t dev);
918621f407SFrançois Tigeot static int agp_gen5_get_gtt_total_entries(device_t dev);
928621f407SFrançois Tigeot 
938621f407SFrançois Tigeot static int agp_i830_install_gatt(device_t dev);
948621f407SFrançois Tigeot 
958621f407SFrançois Tigeot static void agp_i830_deinstall_gatt(device_t dev);
968621f407SFrançois Tigeot 
978621f407SFrançois Tigeot static void agp_i915_install_gtt_pte(device_t dev, u_int index,
988621f407SFrançois Tigeot     vm_offset_t physical, int flags);
998621f407SFrançois Tigeot static void agp_i965_install_gtt_pte(device_t dev, u_int index,
1008621f407SFrançois Tigeot     vm_offset_t physical, int flags);
1018621f407SFrançois Tigeot static void agp_g4x_install_gtt_pte(device_t dev, u_int index,
1028621f407SFrançois Tigeot     vm_offset_t physical, int flags);
1038621f407SFrançois Tigeot 
1048621f407SFrançois Tigeot static void agp_i915_write_gtt(device_t dev, u_int index, uint32_t pte);
1058621f407SFrançois Tigeot static void agp_i965_write_gtt(device_t dev, u_int index, uint32_t pte);
1068621f407SFrançois Tigeot static void agp_g4x_write_gtt(device_t dev, u_int index, uint32_t pte);
1078621f407SFrançois Tigeot 
1088621f407SFrançois Tigeot static void agp_i915_sync_gtt_pte(device_t dev, u_int index);
1098621f407SFrançois Tigeot static void agp_i965_sync_gtt_pte(device_t dev, u_int index);
1108621f407SFrançois Tigeot static void agp_g4x_sync_gtt_pte(device_t dev, u_int index);
1118621f407SFrançois Tigeot 
1128621f407SFrançois Tigeot static int agp_i915_set_aperture(device_t dev, u_int32_t aperture);
1138621f407SFrançois Tigeot 
1148621f407SFrançois Tigeot static int agp_i915_chipset_flush_setup(device_t dev);
1158621f407SFrançois Tigeot static int agp_i965_chipset_flush_setup(device_t dev);
1168621f407SFrançois Tigeot 
1178621f407SFrançois Tigeot static void agp_i915_chipset_flush_teardown(device_t dev);
1188621f407SFrançois Tigeot static void agp_i965_chipset_flush_teardown(device_t dev);
1198621f407SFrançois Tigeot 
1208621f407SFrançois Tigeot static void agp_i915_chipset_flush(device_t dev);
1218621f407SFrançois Tigeot 
1228621f407SFrançois Tigeot enum {
1238621f407SFrançois Tigeot 	CHIP_I810,	/* i810/i815 */
1248621f407SFrançois Tigeot 	CHIP_I830,	/* 830M/845G */
1258621f407SFrançois Tigeot 	CHIP_I855,	/* 852GM/855GM/865G */
1268621f407SFrançois Tigeot 	CHIP_I915,	/* 915G/915GM */
1278621f407SFrançois Tigeot 	CHIP_I965,	/* G965 */
1288621f407SFrançois Tigeot 	CHIP_G33,	/* G33/Q33/Q35 */
1298621f407SFrançois Tigeot 	CHIP_IGD,	/* Pineview */
1308621f407SFrançois Tigeot 	CHIP_G4X,	/* G45/Q45 */
1318621f407SFrançois Tigeot };
1328621f407SFrançois Tigeot 
1338621f407SFrançois Tigeot /* The i810 through i855 have the registers at BAR 1, and the GATT gets
1348621f407SFrançois Tigeot  * allocated by us.  The i915 has registers in BAR 0 and the GATT is at the
1358621f407SFrançois Tigeot  * start of the stolen memory, and should only be accessed by the OS through
1368621f407SFrançois Tigeot  * BAR 3.  The G965 has registers and GATT in the same BAR (0) -- first 512KB
1378621f407SFrançois Tigeot  * is registers, second 512KB is GATT.
1388621f407SFrançois Tigeot  */
1398621f407SFrançois Tigeot static struct resource_spec agp_i915_res_spec[] = {
1408621f407SFrançois Tigeot 	{ SYS_RES_MEMORY, AGP_I915_MMADR, RF_ACTIVE | RF_SHAREABLE },
1418621f407SFrançois Tigeot 	{ SYS_RES_MEMORY, AGP_I915_GTTADR, RF_ACTIVE | RF_SHAREABLE },
1428621f407SFrançois Tigeot 	{ -1, 0 }
1438621f407SFrançois Tigeot };
1448621f407SFrançois Tigeot 
1458621f407SFrançois Tigeot static struct resource_spec agp_i965_res_spec[] = {
1468621f407SFrançois Tigeot 	{ SYS_RES_MEMORY, AGP_I965_GTTMMADR, RF_ACTIVE | RF_SHAREABLE },
1478621f407SFrançois Tigeot 	{ -1, 0 }
1488621f407SFrançois Tigeot };
1498621f407SFrançois Tigeot 
1508621f407SFrançois Tigeot struct agp_i810_softc {
1518621f407SFrançois Tigeot 	struct agp_softc agp;
1528621f407SFrançois Tigeot 	u_int32_t initial_aperture;	/* aperture size at startup */
1538621f407SFrançois Tigeot 	struct agp_gatt *gatt;
1548621f407SFrançois Tigeot 	u_int32_t dcache_size;		/* i810 only */
1558621f407SFrançois Tigeot 	u_int32_t stolen;		/* number of i830/845 gtt
1568621f407SFrançois Tigeot 					   entries for stolen memory */
1578621f407SFrançois Tigeot 	u_int stolen_size;		/* BIOS-reserved graphics memory */
1588621f407SFrançois Tigeot 	u_int gtt_total_entries;	/* Total number of gtt ptes */
1598621f407SFrançois Tigeot 	u_int gtt_mappable_entries;	/* Number of gtt ptes mappable by CPU */
1608621f407SFrançois Tigeot 	device_t bdev;			/* bridge device */
1618621f407SFrançois Tigeot 	void *argb_cursor;		/* contigmalloc area for ARGB cursor */
1628621f407SFrançois Tigeot 	struct resource *sc_res[3];
1638621f407SFrançois Tigeot 	const struct agp_i810_match *match;
1648621f407SFrançois Tigeot 	int sc_flush_page_rid;
1658621f407SFrançois Tigeot 	struct resource *sc_flush_page_res;
1668621f407SFrançois Tigeot 	void *sc_flush_page_vaddr;
1678621f407SFrançois Tigeot 	int sc_bios_allocated_flush_page;
1688621f407SFrançois Tigeot };
1698621f407SFrançois Tigeot 
1708621f407SFrançois Tigeot static device_t intel_agp;
1718621f407SFrançois Tigeot 
1728621f407SFrançois Tigeot struct agp_i810_driver {
1738621f407SFrançois Tigeot 	int chiptype;
1748621f407SFrançois Tigeot 	int gen;
1758621f407SFrançois Tigeot 	int busdma_addr_mask_sz;
1768621f407SFrançois Tigeot 	struct resource_spec *res_spec;
1778621f407SFrançois Tigeot 	int (*check_active)(device_t);
1788621f407SFrançois Tigeot 	void (*set_desc)(device_t, const struct agp_i810_match *);
1798621f407SFrançois Tigeot 	void (*dump_regs)(device_t);
1808621f407SFrançois Tigeot 	int (*get_stolen_size)(device_t);
1818621f407SFrançois Tigeot 	int (*get_gtt_total_entries)(device_t);
1828621f407SFrançois Tigeot 	int (*get_gtt_mappable_entries)(device_t);
1838621f407SFrançois Tigeot 	int (*install_gatt)(device_t);
1848621f407SFrançois Tigeot 	void (*deinstall_gatt)(device_t);
1858621f407SFrançois Tigeot 	void (*write_gtt)(device_t, u_int, uint32_t);
1868621f407SFrançois Tigeot 	void (*install_gtt_pte)(device_t, u_int, vm_offset_t, int);
1878621f407SFrançois Tigeot 	void (*sync_gtt_pte)(device_t, u_int);
1888621f407SFrançois Tigeot 	int (*set_aperture)(device_t, u_int32_t);
1898621f407SFrançois Tigeot 	int (*chipset_flush_setup)(device_t);
1908621f407SFrançois Tigeot 	void (*chipset_flush_teardown)(device_t);
1918621f407SFrançois Tigeot 	void (*chipset_flush)(device_t);
1928621f407SFrançois Tigeot };
1938621f407SFrançois Tigeot 
1948621f407SFrançois Tigeot static struct {
1958621f407SFrançois Tigeot 	struct intel_gtt base;
1968621f407SFrançois Tigeot } intel_private;
1978621f407SFrançois Tigeot 
1988621f407SFrançois Tigeot static const struct agp_i810_driver agp_i810_i915_driver = {
1998621f407SFrançois Tigeot 	.chiptype = CHIP_I915,
2008621f407SFrançois Tigeot 	.gen = 3,
2018621f407SFrançois Tigeot 	.busdma_addr_mask_sz = 32,
2028621f407SFrançois Tigeot 	.res_spec = agp_i915_res_spec,
2038621f407SFrançois Tigeot 	.check_active = agp_i915_check_active,
2048621f407SFrançois Tigeot 	.set_desc = agp_i810_set_desc,
2058621f407SFrançois Tigeot 	.dump_regs = agp_i915_dump_regs,
2068621f407SFrançois Tigeot 	.get_stolen_size = agp_i915_get_stolen_size,
2078621f407SFrançois Tigeot 	.get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
2088621f407SFrançois Tigeot 	.get_gtt_total_entries = agp_i810_get_gtt_total_entries,
2098621f407SFrançois Tigeot 	.install_gatt = agp_i830_install_gatt,
2108621f407SFrançois Tigeot 	.deinstall_gatt = agp_i830_deinstall_gatt,
2118621f407SFrançois Tigeot 	.write_gtt = agp_i915_write_gtt,
2128621f407SFrançois Tigeot 	.install_gtt_pte = agp_i915_install_gtt_pte,
2138621f407SFrançois Tigeot 	.sync_gtt_pte = agp_i915_sync_gtt_pte,
2148621f407SFrançois Tigeot 	.set_aperture = agp_i915_set_aperture,
2158621f407SFrançois Tigeot 	.chipset_flush_setup = agp_i915_chipset_flush_setup,
2168621f407SFrançois Tigeot 	.chipset_flush_teardown = agp_i915_chipset_flush_teardown,
2178621f407SFrançois Tigeot 	.chipset_flush = agp_i915_chipset_flush,
2188621f407SFrançois Tigeot };
2198621f407SFrançois Tigeot 
2208621f407SFrançois Tigeot static const struct agp_i810_driver agp_i810_g965_driver = {
2218621f407SFrançois Tigeot 	.chiptype = CHIP_I965,
2228621f407SFrançois Tigeot 	.gen = 4,
2238621f407SFrançois Tigeot 	.busdma_addr_mask_sz = 36,
2248621f407SFrançois Tigeot 	.res_spec = agp_i965_res_spec,
2258621f407SFrançois Tigeot 	.check_active = agp_i915_check_active,
2268621f407SFrançois Tigeot 	.set_desc = agp_i810_set_desc,
2278621f407SFrançois Tigeot 	.dump_regs = agp_i965_dump_regs,
2288621f407SFrançois Tigeot 	.get_stolen_size = agp_i915_get_stolen_size,
2298621f407SFrançois Tigeot 	.get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
2308621f407SFrançois Tigeot 	.get_gtt_total_entries = agp_i965_get_gtt_total_entries,
2318621f407SFrançois Tigeot 	.install_gatt = agp_i830_install_gatt,
2328621f407SFrançois Tigeot 	.deinstall_gatt = agp_i830_deinstall_gatt,
2338621f407SFrançois Tigeot 	.write_gtt = agp_i965_write_gtt,
2348621f407SFrançois Tigeot 	.install_gtt_pte = agp_i965_install_gtt_pte,
2358621f407SFrançois Tigeot 	.sync_gtt_pte = agp_i965_sync_gtt_pte,
2368621f407SFrançois Tigeot 	.set_aperture = agp_i915_set_aperture,
2378621f407SFrançois Tigeot 	.chipset_flush_setup = agp_i965_chipset_flush_setup,
2388621f407SFrançois Tigeot 	.chipset_flush_teardown = agp_i965_chipset_flush_teardown,
2398621f407SFrançois Tigeot 	.chipset_flush = agp_i915_chipset_flush,
2408621f407SFrançois Tigeot };
2418621f407SFrançois Tigeot 
2428621f407SFrançois Tigeot static const struct agp_i810_driver agp_i810_g33_driver = {
2438621f407SFrançois Tigeot 	.chiptype = CHIP_G33,
2448621f407SFrançois Tigeot 	.gen = 3,
2458621f407SFrançois Tigeot 	.busdma_addr_mask_sz = 36,
2468621f407SFrançois Tigeot 	.res_spec = agp_i915_res_spec,
2478621f407SFrançois Tigeot 	.check_active = agp_i915_check_active,
2488621f407SFrançois Tigeot 	.set_desc = agp_i810_set_desc,
2498621f407SFrançois Tigeot 	.dump_regs = agp_i965_dump_regs,
2508621f407SFrançois Tigeot 	.get_stolen_size = agp_i915_get_stolen_size,
2518621f407SFrançois Tigeot 	.get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
2528621f407SFrançois Tigeot 	.get_gtt_total_entries = agp_i965_get_gtt_total_entries,
2538621f407SFrançois Tigeot 	.install_gatt = agp_i830_install_gatt,
2548621f407SFrançois Tigeot 	.deinstall_gatt = agp_i830_deinstall_gatt,
2558621f407SFrançois Tigeot 	.write_gtt = agp_i915_write_gtt,
2568621f407SFrançois Tigeot 	.install_gtt_pte = agp_i965_install_gtt_pte,
2578621f407SFrançois Tigeot 	.sync_gtt_pte = agp_i915_sync_gtt_pte,
2588621f407SFrançois Tigeot 	.set_aperture = agp_i915_set_aperture,
2598621f407SFrançois Tigeot 	.chipset_flush_setup = agp_i965_chipset_flush_setup,
2608621f407SFrançois Tigeot 	.chipset_flush_teardown = agp_i965_chipset_flush_teardown,
2618621f407SFrançois Tigeot 	.chipset_flush = agp_i915_chipset_flush,
2628621f407SFrançois Tigeot };
2638621f407SFrançois Tigeot 
2648621f407SFrançois Tigeot static const struct agp_i810_driver pineview_gtt_driver = {
2658621f407SFrançois Tigeot 	.chiptype = CHIP_IGD,
2668621f407SFrançois Tigeot 	.gen = 3,
2678621f407SFrançois Tigeot 	.busdma_addr_mask_sz = 36,
2688621f407SFrançois Tigeot 	.res_spec = agp_i915_res_spec,
2698621f407SFrançois Tigeot 	.check_active = agp_i915_check_active,
2708621f407SFrançois Tigeot 	.set_desc = agp_i810_set_desc,
2718621f407SFrançois Tigeot 	.dump_regs = agp_i915_dump_regs,
2728621f407SFrançois Tigeot 	.get_stolen_size = agp_i915_get_stolen_size,
2738621f407SFrançois Tigeot 	.get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
2748621f407SFrançois Tigeot 	.get_gtt_total_entries = agp_i965_get_gtt_total_entries,
2758621f407SFrançois Tigeot 	.install_gatt = agp_i830_install_gatt,
2768621f407SFrançois Tigeot 	.deinstall_gatt = agp_i830_deinstall_gatt,
2778621f407SFrançois Tigeot 	.write_gtt = agp_i915_write_gtt,
2788621f407SFrançois Tigeot 	.install_gtt_pte = agp_i965_install_gtt_pte,
2798621f407SFrançois Tigeot 	.sync_gtt_pte = agp_i915_sync_gtt_pte,
2808621f407SFrançois Tigeot 	.set_aperture = agp_i915_set_aperture,
2818621f407SFrançois Tigeot 	.chipset_flush_setup = agp_i965_chipset_flush_setup,
2828621f407SFrançois Tigeot 	.chipset_flush_teardown = agp_i965_chipset_flush_teardown,
2838621f407SFrançois Tigeot 	.chipset_flush = agp_i915_chipset_flush,
2848621f407SFrançois Tigeot };
2858621f407SFrançois Tigeot 
2868621f407SFrançois Tigeot static const struct agp_i810_driver agp_i810_g4x_driver = {
2878621f407SFrançois Tigeot 	.chiptype = CHIP_G4X,
2888621f407SFrançois Tigeot 	.gen = 5,
2898621f407SFrançois Tigeot 	.busdma_addr_mask_sz = 36,
2908621f407SFrançois Tigeot 	.res_spec = agp_i965_res_spec,
2918621f407SFrançois Tigeot 	.check_active = agp_i915_check_active,
2928621f407SFrançois Tigeot 	.set_desc = agp_i810_set_desc,
2938621f407SFrançois Tigeot 	.dump_regs = agp_i965_dump_regs,
2948621f407SFrançois Tigeot 	.get_stolen_size = agp_i915_get_stolen_size,
2958621f407SFrançois Tigeot 	.get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
2968621f407SFrançois Tigeot 	.get_gtt_total_entries = agp_gen5_get_gtt_total_entries,
2978621f407SFrançois Tigeot 	.install_gatt = agp_i830_install_gatt,
2988621f407SFrançois Tigeot 	.deinstall_gatt = agp_i830_deinstall_gatt,
2998621f407SFrançois Tigeot 	.write_gtt = agp_g4x_write_gtt,
3008621f407SFrançois Tigeot 	.install_gtt_pte = agp_g4x_install_gtt_pte,
3018621f407SFrançois Tigeot 	.sync_gtt_pte = agp_g4x_sync_gtt_pte,
3028621f407SFrançois Tigeot 	.set_aperture = agp_i915_set_aperture,
3038621f407SFrançois Tigeot 	.chipset_flush_setup = agp_i965_chipset_flush_setup,
3048621f407SFrançois Tigeot 	.chipset_flush_teardown = agp_i965_chipset_flush_teardown,
3058621f407SFrançois Tigeot 	.chipset_flush = agp_i915_chipset_flush,
3068621f407SFrançois Tigeot };
3078621f407SFrançois Tigeot 
3088621f407SFrançois Tigeot /* For adding new devices, devid is the id of the graphics controller
3098621f407SFrançois Tigeot  * (pci:0:2:0, for example).  The placeholder (usually at pci:0:2:1) for the
3108621f407SFrançois Tigeot  * second head should never be added.  The bridge_offset is the offset to
3118621f407SFrançois Tigeot  * subtract from devid to get the id of the hostb that the device is on.
3128621f407SFrançois Tigeot  */
3138621f407SFrançois Tigeot static const struct agp_i810_match {
3148621f407SFrançois Tigeot 	uint16_t devid;
3158621f407SFrançois Tigeot 	char *name;
3168621f407SFrançois Tigeot 	const struct agp_i810_driver *driver;
3178621f407SFrançois Tigeot } agp_i810_matches[] = {
3188621f407SFrançois Tigeot 	{
3198621f407SFrançois Tigeot 		.devid = 0x2582,
3208621f407SFrançois Tigeot 		.name = "Intel 82915G (915G GMCH) SVGA controller",
3218621f407SFrançois Tigeot 		.driver = &agp_i810_i915_driver
3228621f407SFrançois Tigeot 	},
3238621f407SFrançois Tigeot 	{
3248621f407SFrançois Tigeot 		.devid = 0x258A,
3258621f407SFrançois Tigeot 		.name = "Intel E7221 SVGA controller",
3268621f407SFrançois Tigeot 		.driver = &agp_i810_i915_driver
3278621f407SFrançois Tigeot 	},
3288621f407SFrançois Tigeot 	{
3298621f407SFrançois Tigeot 		.devid = 0x2592,
3308621f407SFrançois Tigeot 		.name = "Intel 82915GM (915GM GMCH) SVGA controller",
3318621f407SFrançois Tigeot 		.driver = &agp_i810_i915_driver
3328621f407SFrançois Tigeot 	},
3338621f407SFrançois Tigeot 	{
3348621f407SFrançois Tigeot 		.devid = 0x2772,
3358621f407SFrançois Tigeot 		.name = "Intel 82945G (945G GMCH) SVGA controller",
3368621f407SFrançois Tigeot 		.driver = &agp_i810_i915_driver
3378621f407SFrançois Tigeot 	},
3388621f407SFrançois Tigeot 	{
3398621f407SFrançois Tigeot 		.devid = 0x27A2,
3408621f407SFrançois Tigeot 		.name = "Intel 82945GM (945GM GMCH) SVGA controller",
3418621f407SFrançois Tigeot 		.driver = &agp_i810_i915_driver
3428621f407SFrançois Tigeot 	},
3438621f407SFrançois Tigeot 	{
3448621f407SFrançois Tigeot 		.devid = 0x27AE,
3458621f407SFrançois Tigeot 		.name = "Intel 945GME SVGA controller",
3468621f407SFrançois Tigeot 		.driver = &agp_i810_i915_driver
3478621f407SFrançois Tigeot 	},
3488621f407SFrançois Tigeot 	{
3498621f407SFrançois Tigeot 		.devid = 0x2972,
3508621f407SFrançois Tigeot 		.name = "Intel 946GZ SVGA controller",
3518621f407SFrançois Tigeot 		.driver = &agp_i810_g965_driver
3528621f407SFrançois Tigeot 	},
3538621f407SFrançois Tigeot 	{
3548621f407SFrançois Tigeot 		.devid = 0x2982,
3558621f407SFrançois Tigeot 		.name = "Intel G965 SVGA controller",
3568621f407SFrançois Tigeot 		.driver = &agp_i810_g965_driver
3578621f407SFrançois Tigeot 	},
3588621f407SFrançois Tigeot 	{
3598621f407SFrançois Tigeot 		.devid = 0x2992,
3608621f407SFrançois Tigeot 		.name = "Intel Q965 SVGA controller",
3618621f407SFrançois Tigeot 		.driver = &agp_i810_g965_driver
3628621f407SFrançois Tigeot 	},
3638621f407SFrançois Tigeot 	{
3648621f407SFrançois Tigeot 		.devid = 0x29A2,
3658621f407SFrançois Tigeot 		.name = "Intel G965 SVGA controller",
3668621f407SFrançois Tigeot 		.driver = &agp_i810_g965_driver
3678621f407SFrançois Tigeot 	},
3688621f407SFrançois Tigeot 	{
3698621f407SFrançois Tigeot 		.devid = 0x29B2,
3708621f407SFrançois Tigeot 		.name = "Intel Q35 SVGA controller",
3718621f407SFrançois Tigeot 		.driver = &agp_i810_g33_driver
3728621f407SFrançois Tigeot 	},
3738621f407SFrançois Tigeot 	{
3748621f407SFrançois Tigeot 		.devid = 0x29C2,
3758621f407SFrançois Tigeot 		.name = "Intel G33 SVGA controller",
3768621f407SFrançois Tigeot 		.driver = &agp_i810_g33_driver
3778621f407SFrançois Tigeot 	},
3788621f407SFrançois Tigeot 	{
3798621f407SFrançois Tigeot 		.devid = 0x29D2,
3808621f407SFrançois Tigeot 		.name = "Intel Q33 SVGA controller",
3818621f407SFrançois Tigeot 		.driver = &agp_i810_g33_driver
3828621f407SFrançois Tigeot 	},
3838621f407SFrançois Tigeot 	{
3848621f407SFrançois Tigeot 		.devid = 0xA001,
3858621f407SFrançois Tigeot 		.name = "Intel Pineview SVGA controller",
3868621f407SFrançois Tigeot 		.driver = &pineview_gtt_driver
3878621f407SFrançois Tigeot 	},
3888621f407SFrançois Tigeot 	{
3898621f407SFrançois Tigeot 		.devid = 0xA011,
3908621f407SFrançois Tigeot 		.name = "Intel Pineview (M) SVGA controller",
3918621f407SFrançois Tigeot 		.driver = &pineview_gtt_driver
3928621f407SFrançois Tigeot 	},
3938621f407SFrançois Tigeot 	{
3948621f407SFrançois Tigeot 		.devid = 0x2A02,
3958621f407SFrançois Tigeot 		.name = "Intel GM965 SVGA controller",
3968621f407SFrançois Tigeot 		.driver = &agp_i810_g965_driver
3978621f407SFrançois Tigeot 	},
3988621f407SFrançois Tigeot 	{
3998621f407SFrançois Tigeot 		.devid = 0x2A12,
4008621f407SFrançois Tigeot 		.name = "Intel GME965 SVGA controller",
4018621f407SFrançois Tigeot 		.driver = &agp_i810_g965_driver
4028621f407SFrançois Tigeot 	},
4038621f407SFrançois Tigeot 	{
4048621f407SFrançois Tigeot 		.devid = 0x2A42,
4058621f407SFrançois Tigeot 		.name = "Intel GM45 SVGA controller",
4068621f407SFrançois Tigeot 		.driver = &agp_i810_g4x_driver
4078621f407SFrançois Tigeot 	},
4088621f407SFrançois Tigeot 	{
4098621f407SFrançois Tigeot 		.devid = 0x2E02,
4108621f407SFrançois Tigeot 		.name = "Intel Eaglelake SVGA controller",
4118621f407SFrançois Tigeot 		.driver = &agp_i810_g4x_driver
4128621f407SFrançois Tigeot 	},
4138621f407SFrançois Tigeot 	{
4148621f407SFrançois Tigeot 		.devid = 0x2E12,
4158621f407SFrançois Tigeot 		.name = "Intel Q45 SVGA controller",
4168621f407SFrançois Tigeot 		.driver = &agp_i810_g4x_driver
4178621f407SFrançois Tigeot 	},
4188621f407SFrançois Tigeot 	{
4198621f407SFrançois Tigeot 		.devid = 0x2E22,
4208621f407SFrançois Tigeot 		.name = "Intel G45 SVGA controller",
4218621f407SFrançois Tigeot 		.driver = &agp_i810_g4x_driver
4228621f407SFrançois Tigeot 	},
4238621f407SFrançois Tigeot 	{
4248621f407SFrançois Tigeot 		.devid = 0x2E32,
4258621f407SFrançois Tigeot 		.name = "Intel G41 SVGA controller",
4268621f407SFrançois Tigeot 		.driver = &agp_i810_g4x_driver
4278621f407SFrançois Tigeot 	},
4288621f407SFrançois Tigeot 	{
4298621f407SFrançois Tigeot 		.devid = 0x0042,
4308621f407SFrançois Tigeot 		.name = "Intel Ironlake (D) SVGA controller",
4318621f407SFrançois Tigeot 		.driver = &agp_i810_g4x_driver
4328621f407SFrançois Tigeot 	},
4338621f407SFrançois Tigeot 	{
4348621f407SFrançois Tigeot 		.devid = 0x0046,
4358621f407SFrançois Tigeot 		.name = "Intel Ironlake (M) SVGA controller",
4368621f407SFrançois Tigeot 		.driver = &agp_i810_g4x_driver
4378621f407SFrançois Tigeot 	},
4388621f407SFrançois Tigeot 
4398621f407SFrançois Tigeot 	{
4408621f407SFrançois Tigeot 		.devid = 0,
4418621f407SFrançois Tigeot 	}
4428621f407SFrançois Tigeot };
4438621f407SFrançois Tigeot 
4448621f407SFrançois Tigeot static const struct agp_i810_match*
agp_i810_match(device_t dev)4458621f407SFrançois Tigeot agp_i810_match(device_t dev)
4468621f407SFrançois Tigeot {
4478621f407SFrançois Tigeot 	int i, devid;
4488621f407SFrançois Tigeot 
4498621f407SFrançois Tigeot 	if (pci_get_vendor(dev) != PCI_VENDOR_INTEL)
4508621f407SFrançois Tigeot 		return (NULL);
4518621f407SFrançois Tigeot 
4528621f407SFrançois Tigeot 	devid = pci_get_device(dev);
4538621f407SFrançois Tigeot 	for (i = 0; agp_i810_matches[i].devid != 0; i++) {
4548621f407SFrançois Tigeot 		if (agp_i810_matches[i].devid == devid)
4558621f407SFrançois Tigeot 			break;
4568621f407SFrançois Tigeot 	}
4578621f407SFrançois Tigeot 	if (agp_i810_matches[i].devid == 0)
4588621f407SFrançois Tigeot 		return (NULL);
4598621f407SFrançois Tigeot 	else
4608621f407SFrançois Tigeot 		return (&agp_i810_matches[i]);
4618621f407SFrançois Tigeot }
4628621f407SFrançois Tigeot 
4638621f407SFrançois Tigeot /*
4648621f407SFrançois Tigeot  * Find bridge device.
4658621f407SFrançois Tigeot  */
4668621f407SFrançois Tigeot static device_t
agp_i810_find_bridge(device_t dev)4678621f407SFrançois Tigeot agp_i810_find_bridge(device_t dev)
4688621f407SFrançois Tigeot {
4698621f407SFrançois Tigeot 
4708621f407SFrançois Tigeot 	return (pci_find_dbsf(0, 0, 0, 0));
4718621f407SFrançois Tigeot }
4728621f407SFrançois Tigeot 
4738621f407SFrançois Tigeot static void
agp_i810_identify(driver_t * driver,device_t parent)4748621f407SFrançois Tigeot agp_i810_identify(driver_t *driver, device_t parent)
4758621f407SFrançois Tigeot {
4768621f407SFrançois Tigeot 
4778621f407SFrançois Tigeot 	if (device_find_child(parent, "agp", -1) == NULL &&
4788621f407SFrançois Tigeot 	    agp_i810_match(parent))
4798621f407SFrançois Tigeot 		device_add_child(parent, "agp", -1);
4808621f407SFrançois Tigeot }
4818621f407SFrançois Tigeot 
4828621f407SFrançois Tigeot static int
agp_i915_check_active(device_t bridge_dev)4838621f407SFrançois Tigeot agp_i915_check_active(device_t bridge_dev)
4848621f407SFrançois Tigeot {
4858621f407SFrançois Tigeot 	int deven;
4868621f407SFrançois Tigeot 
4878621f407SFrançois Tigeot 	deven = pci_read_config(bridge_dev, AGP_I915_DEVEN, 4);
4888621f407SFrançois Tigeot 	if ((deven & AGP_I915_DEVEN_D2F0) == AGP_I915_DEVEN_D2F0_DISABLED)
4898621f407SFrançois Tigeot 		return (ENXIO);
4908621f407SFrançois Tigeot 	return (0);
4918621f407SFrançois Tigeot }
4928621f407SFrançois Tigeot 
4938621f407SFrançois Tigeot static void
agp_i810_set_desc(device_t dev,const struct agp_i810_match * match)4948621f407SFrançois Tigeot agp_i810_set_desc(device_t dev, const struct agp_i810_match *match)
4958621f407SFrançois Tigeot {
4968621f407SFrançois Tigeot 
4978621f407SFrançois Tigeot 	device_set_desc(dev, match->name);
4988621f407SFrançois Tigeot }
4998621f407SFrançois Tigeot 
5008621f407SFrançois Tigeot static int
agp_i810_probe(device_t dev)5018621f407SFrançois Tigeot agp_i810_probe(device_t dev)
5028621f407SFrançois Tigeot {
5038621f407SFrançois Tigeot 	device_t bdev;
5048621f407SFrançois Tigeot 	const struct agp_i810_match *match;
5058621f407SFrançois Tigeot 	int err = 0;
5068621f407SFrançois Tigeot 
5078621f407SFrançois Tigeot 	if (resource_disabled("agp", device_get_unit(dev)))
5088621f407SFrançois Tigeot 		return (ENXIO);
5098621f407SFrançois Tigeot 	match = agp_i810_match(dev);
5108621f407SFrançois Tigeot 	if (match == NULL)
5118621f407SFrançois Tigeot 		return (ENXIO);
5128621f407SFrançois Tigeot 
5138621f407SFrançois Tigeot 	bdev = agp_i810_find_bridge(dev);
5148621f407SFrançois Tigeot 	if (bdev == NULL) {
5158621f407SFrançois Tigeot 		if (bootverbose)
5168621f407SFrançois Tigeot 			kprintf("I810: can't find bridge device\n");
5178621f407SFrançois Tigeot 		return (ENXIO);
5188621f407SFrançois Tigeot 	}
5198621f407SFrançois Tigeot 
5208621f407SFrançois Tigeot 	/*
5218621f407SFrançois Tigeot 	 * checking whether internal graphics device has been activated.
5228621f407SFrançois Tigeot 	 */
5238621f407SFrançois Tigeot 	if (match->driver->check_active != NULL) {
5248621f407SFrançois Tigeot 		err = match->driver->check_active(bdev);
5258621f407SFrançois Tigeot 		if (err != 0) {
5268621f407SFrançois Tigeot 			if (bootverbose)
5278621f407SFrançois Tigeot 				kprintf("i810: disabled, not probing\n");
5288621f407SFrançois Tigeot 			return (err);
5298621f407SFrançois Tigeot 		}
5308621f407SFrançois Tigeot 	}
5318621f407SFrançois Tigeot 
5328621f407SFrançois Tigeot 	match->driver->set_desc(dev, match);
5338621f407SFrançois Tigeot 	return (BUS_PROBE_DEFAULT);
5348621f407SFrançois Tigeot }
5358621f407SFrançois Tigeot 
5368621f407SFrançois Tigeot static void
agp_i915_dump_regs(device_t dev)5378621f407SFrançois Tigeot agp_i915_dump_regs(device_t dev)
5388621f407SFrançois Tigeot {
5398621f407SFrançois Tigeot 	struct agp_i810_softc *sc = device_get_softc(dev);
5408621f407SFrançois Tigeot 
5418621f407SFrançois Tigeot 	device_printf(dev, "AGP_I810_PGTBL_CTL: %08x\n",
5428621f407SFrançois Tigeot 	    bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL));
5438621f407SFrançois Tigeot 	device_printf(dev, "AGP_I855_GCC1: 0x%02x\n",
5448621f407SFrançois Tigeot 	    pci_read_config(sc->bdev, AGP_I855_GCC1, 1));
5458621f407SFrançois Tigeot 	device_printf(dev, "AGP_I915_MSAC: 0x%02x\n",
5468621f407SFrançois Tigeot 	    pci_read_config(sc->bdev, AGP_I915_MSAC, 1));
5478621f407SFrançois Tigeot }
5488621f407SFrançois Tigeot 
5498621f407SFrançois Tigeot static void
agp_i965_dump_regs(device_t dev)5508621f407SFrançois Tigeot agp_i965_dump_regs(device_t dev)
5518621f407SFrançois Tigeot {
5528621f407SFrançois Tigeot 	struct agp_i810_softc *sc = device_get_softc(dev);
5538621f407SFrançois Tigeot 
5548621f407SFrançois Tigeot 	device_printf(dev, "AGP_I965_PGTBL_CTL2: %08x\n",
5558621f407SFrançois Tigeot 	    bus_read_4(sc->sc_res[0], AGP_I965_PGTBL_CTL2));
5568621f407SFrançois Tigeot 	device_printf(dev, "AGP_I855_GCC1: 0x%02x\n",
5578621f407SFrançois Tigeot 	    pci_read_config(dev, AGP_I855_GCC1, 1));
5588621f407SFrançois Tigeot 	device_printf(dev, "AGP_I965_MSAC: 0x%02x\n",
5598621f407SFrançois Tigeot 	    pci_read_config(dev, AGP_I965_MSAC, 1));
5608621f407SFrançois Tigeot }
5618621f407SFrançois Tigeot 
5628621f407SFrançois Tigeot static int
agp_i915_get_stolen_size(device_t dev)5638621f407SFrançois Tigeot agp_i915_get_stolen_size(device_t dev)
5648621f407SFrançois Tigeot {
5658621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
5668621f407SFrançois Tigeot 	unsigned int gcc1, stolen, gtt_size;
5678621f407SFrançois Tigeot 
5688621f407SFrançois Tigeot 	sc = device_get_softc(dev);
5698621f407SFrançois Tigeot 
5708621f407SFrançois Tigeot 	/*
5718621f407SFrançois Tigeot 	 * Stolen memory is set up at the beginning of the aperture by
5728621f407SFrançois Tigeot 	 * the BIOS, consisting of the GATT followed by 4kb for the
5738621f407SFrançois Tigeot 	 * BIOS display.
5748621f407SFrançois Tigeot 	 */
5758621f407SFrançois Tigeot 	switch (sc->match->driver->chiptype) {
5768621f407SFrançois Tigeot 	case CHIP_I855:
5778621f407SFrançois Tigeot 		gtt_size = 128;
5788621f407SFrançois Tigeot 		break;
5798621f407SFrançois Tigeot 	case CHIP_I915:
5808621f407SFrançois Tigeot 		gtt_size = 256;
5818621f407SFrançois Tigeot 		break;
5828621f407SFrançois Tigeot 	case CHIP_I965:
5838621f407SFrançois Tigeot 		switch (bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL) &
5848621f407SFrançois Tigeot 			AGP_I810_PGTBL_SIZE_MASK) {
5858621f407SFrançois Tigeot 		case AGP_I810_PGTBL_SIZE_128KB:
5868621f407SFrançois Tigeot 			gtt_size = 128;
5878621f407SFrançois Tigeot 			break;
5888621f407SFrançois Tigeot 		case AGP_I810_PGTBL_SIZE_256KB:
5898621f407SFrançois Tigeot 			gtt_size = 256;
5908621f407SFrançois Tigeot 			break;
5918621f407SFrançois Tigeot 		case AGP_I810_PGTBL_SIZE_512KB:
5928621f407SFrançois Tigeot 			gtt_size = 512;
5938621f407SFrançois Tigeot 			break;
5948621f407SFrançois Tigeot 		case AGP_I965_PGTBL_SIZE_1MB:
5958621f407SFrançois Tigeot 			gtt_size = 1024;
5968621f407SFrançois Tigeot 			break;
5978621f407SFrançois Tigeot 		case AGP_I965_PGTBL_SIZE_2MB:
5988621f407SFrançois Tigeot 			gtt_size = 2048;
5998621f407SFrançois Tigeot 			break;
6008621f407SFrançois Tigeot 		case AGP_I965_PGTBL_SIZE_1_5MB:
6018621f407SFrançois Tigeot 			gtt_size = 1024 + 512;
6028621f407SFrançois Tigeot 			break;
6038621f407SFrançois Tigeot 		default:
6048621f407SFrançois Tigeot 			device_printf(dev, "Bad PGTBL size\n");
6058621f407SFrançois Tigeot 			return (EINVAL);
6068621f407SFrançois Tigeot 		}
6078621f407SFrançois Tigeot 		break;
6088621f407SFrançois Tigeot 	case CHIP_G33:
6098621f407SFrançois Tigeot 		gcc1 = pci_read_config(sc->bdev, AGP_I855_GCC1, 2);
6108621f407SFrançois Tigeot 		switch (gcc1 & AGP_G33_MGGC_GGMS_MASK) {
6118621f407SFrançois Tigeot 		case AGP_G33_MGGC_GGMS_SIZE_1M:
6128621f407SFrançois Tigeot 			gtt_size = 1024;
6138621f407SFrançois Tigeot 			break;
6148621f407SFrançois Tigeot 		case AGP_G33_MGGC_GGMS_SIZE_2M:
6158621f407SFrançois Tigeot 			gtt_size = 2048;
6168621f407SFrançois Tigeot 			break;
6178621f407SFrançois Tigeot 		default:
6188621f407SFrançois Tigeot 			device_printf(dev, "Bad PGTBL size\n");
6198621f407SFrançois Tigeot 			return (EINVAL);
6208621f407SFrançois Tigeot 		}
6218621f407SFrançois Tigeot 		break;
6228621f407SFrançois Tigeot 	case CHIP_IGD:
6238621f407SFrançois Tigeot 	case CHIP_G4X:
6248621f407SFrançois Tigeot 		gtt_size = 0;
6258621f407SFrançois Tigeot 		break;
6268621f407SFrançois Tigeot 	default:
6278621f407SFrançois Tigeot 		device_printf(dev, "Bad chiptype\n");
6288621f407SFrançois Tigeot 		return (EINVAL);
6298621f407SFrançois Tigeot 	}
6308621f407SFrançois Tigeot 
6318621f407SFrançois Tigeot 	/* GCC1 is called MGGC on i915+ */
6328621f407SFrançois Tigeot 	gcc1 = pci_read_config(sc->bdev, AGP_I855_GCC1, 1);
6338621f407SFrançois Tigeot 	switch (gcc1 & AGP_I855_GCC1_GMS) {
6348621f407SFrançois Tigeot 	case AGP_I855_GCC1_GMS_STOLEN_1M:
6358621f407SFrançois Tigeot 		stolen = 1024;
6368621f407SFrançois Tigeot 		break;
6378621f407SFrançois Tigeot 	case AGP_I855_GCC1_GMS_STOLEN_4M:
6388621f407SFrançois Tigeot 		stolen = 4 * 1024;
6398621f407SFrançois Tigeot 		break;
6408621f407SFrançois Tigeot 	case AGP_I855_GCC1_GMS_STOLEN_8M:
6418621f407SFrançois Tigeot 		stolen = 8 * 1024;
6428621f407SFrançois Tigeot 		break;
6438621f407SFrançois Tigeot 	case AGP_I855_GCC1_GMS_STOLEN_16M:
6448621f407SFrançois Tigeot 		stolen = 16 * 1024;
6458621f407SFrançois Tigeot 		break;
6468621f407SFrançois Tigeot 	case AGP_I855_GCC1_GMS_STOLEN_32M:
6478621f407SFrançois Tigeot 		stolen = 32 * 1024;
6488621f407SFrançois Tigeot 		break;
6498621f407SFrançois Tigeot 	case AGP_I915_GCC1_GMS_STOLEN_48M:
6508621f407SFrançois Tigeot 		stolen = sc->match->driver->gen > 2 ? 48 * 1024 : 0;
6518621f407SFrançois Tigeot 		break;
6528621f407SFrançois Tigeot 	case AGP_I915_GCC1_GMS_STOLEN_64M:
6538621f407SFrançois Tigeot 		stolen = sc->match->driver->gen > 2 ? 64 * 1024 : 0;
6548621f407SFrançois Tigeot 		break;
6558621f407SFrançois Tigeot 	case AGP_G33_GCC1_GMS_STOLEN_128M:
6568621f407SFrançois Tigeot 		stolen = sc->match->driver->gen > 2 ? 128 * 1024 : 0;
6578621f407SFrançois Tigeot 		break;
6588621f407SFrançois Tigeot 	case AGP_G33_GCC1_GMS_STOLEN_256M:
6598621f407SFrançois Tigeot 		stolen = sc->match->driver->gen > 2 ? 256 * 1024 : 0;
6608621f407SFrançois Tigeot 		break;
6618621f407SFrançois Tigeot 	case AGP_G4X_GCC1_GMS_STOLEN_96M:
6628621f407SFrançois Tigeot 		if (sc->match->driver->chiptype == CHIP_I965 ||
6638621f407SFrançois Tigeot 		    sc->match->driver->chiptype == CHIP_G4X)
6648621f407SFrançois Tigeot 			stolen = 96 * 1024;
6658621f407SFrançois Tigeot 		else
6668621f407SFrançois Tigeot 			stolen = 0;
6678621f407SFrançois Tigeot 		break;
6688621f407SFrançois Tigeot 	case AGP_G4X_GCC1_GMS_STOLEN_160M:
6698621f407SFrançois Tigeot 		if (sc->match->driver->chiptype == CHIP_I965 ||
6708621f407SFrançois Tigeot 		    sc->match->driver->chiptype == CHIP_G4X)
6718621f407SFrançois Tigeot 			stolen = 160 * 1024;
6728621f407SFrançois Tigeot 		else
6738621f407SFrançois Tigeot 			stolen = 0;
6748621f407SFrançois Tigeot 		break;
6758621f407SFrançois Tigeot 	case AGP_G4X_GCC1_GMS_STOLEN_224M:
6768621f407SFrançois Tigeot 		if (sc->match->driver->chiptype == CHIP_I965 ||
6778621f407SFrançois Tigeot 		    sc->match->driver->chiptype == CHIP_G4X)
6788621f407SFrançois Tigeot 			stolen = 224 * 1024;
6798621f407SFrançois Tigeot 		else
6808621f407SFrançois Tigeot 			stolen = 0;
6818621f407SFrançois Tigeot 		break;
6828621f407SFrançois Tigeot 	case AGP_G4X_GCC1_GMS_STOLEN_352M:
6838621f407SFrançois Tigeot 		if (sc->match->driver->chiptype == CHIP_I965 ||
6848621f407SFrançois Tigeot 		    sc->match->driver->chiptype == CHIP_G4X)
6858621f407SFrançois Tigeot 			stolen = 352 * 1024;
6868621f407SFrançois Tigeot 		else
6878621f407SFrançois Tigeot 			stolen = 0;
6888621f407SFrançois Tigeot 		break;
6898621f407SFrançois Tigeot 	default:
6908621f407SFrançois Tigeot 		device_printf(dev,
6918621f407SFrançois Tigeot 		    "unknown memory configuration, disabling (GCC1 %x)\n",
6928621f407SFrançois Tigeot 		    gcc1);
6938621f407SFrançois Tigeot 		return (EINVAL);
6948621f407SFrançois Tigeot 	}
6958621f407SFrançois Tigeot 
6968621f407SFrançois Tigeot 	gtt_size += 4;
6978621f407SFrançois Tigeot 	sc->stolen_size = stolen * 1024;
6988621f407SFrançois Tigeot 	sc->stolen = (stolen - gtt_size) * 1024 / 4096;
6998621f407SFrançois Tigeot 
7008621f407SFrançois Tigeot 	return (0);
7018621f407SFrançois Tigeot }
7028621f407SFrançois Tigeot 
7038621f407SFrançois Tigeot static int
agp_i915_get_gtt_mappable_entries(device_t dev)7048621f407SFrançois Tigeot agp_i915_get_gtt_mappable_entries(device_t dev)
7058621f407SFrançois Tigeot {
7068621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
7078621f407SFrançois Tigeot 	uint32_t ap;
7088621f407SFrançois Tigeot 
7098621f407SFrançois Tigeot 	sc = device_get_softc(dev);
7108621f407SFrançois Tigeot 	ap = AGP_GET_APERTURE(dev);
7118621f407SFrançois Tigeot 	sc->gtt_mappable_entries = ap >> AGP_PAGE_SHIFT;
7128621f407SFrançois Tigeot 	return (0);
7138621f407SFrançois Tigeot }
7148621f407SFrançois Tigeot 
7158621f407SFrançois Tigeot static int
agp_i810_get_gtt_total_entries(device_t dev)7168621f407SFrançois Tigeot agp_i810_get_gtt_total_entries(device_t dev)
7178621f407SFrançois Tigeot {
7188621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
7198621f407SFrançois Tigeot 
7208621f407SFrançois Tigeot 	sc = device_get_softc(dev);
7218621f407SFrançois Tigeot 	sc->gtt_total_entries = sc->gtt_mappable_entries;
7228621f407SFrançois Tigeot 	return (0);
7238621f407SFrançois Tigeot }
7248621f407SFrançois Tigeot 
7258621f407SFrançois Tigeot static int
agp_i965_get_gtt_total_entries(device_t dev)7268621f407SFrançois Tigeot agp_i965_get_gtt_total_entries(device_t dev)
7278621f407SFrançois Tigeot {
7288621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
7298621f407SFrançois Tigeot 	uint32_t pgetbl_ctl;
7308621f407SFrançois Tigeot 	int error;
7318621f407SFrançois Tigeot 
7328621f407SFrançois Tigeot 	sc = device_get_softc(dev);
7338621f407SFrançois Tigeot 	error = 0;
7348621f407SFrançois Tigeot 	pgetbl_ctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
7358621f407SFrançois Tigeot 	switch (pgetbl_ctl & AGP_I810_PGTBL_SIZE_MASK) {
7368621f407SFrançois Tigeot 	case AGP_I810_PGTBL_SIZE_128KB:
7378621f407SFrançois Tigeot 		sc->gtt_total_entries = 128 * 1024 / 4;
7388621f407SFrançois Tigeot 		break;
7398621f407SFrançois Tigeot 	case AGP_I810_PGTBL_SIZE_256KB:
7408621f407SFrançois Tigeot 		sc->gtt_total_entries = 256 * 1024 / 4;
7418621f407SFrançois Tigeot 		break;
7428621f407SFrançois Tigeot 	case AGP_I810_PGTBL_SIZE_512KB:
7438621f407SFrançois Tigeot 		sc->gtt_total_entries = 512 * 1024 / 4;
7448621f407SFrançois Tigeot 		break;
7458621f407SFrançois Tigeot 	/* GTT pagetable sizes bigger than 512KB are not possible on G33! */
7468621f407SFrançois Tigeot 	case AGP_I810_PGTBL_SIZE_1MB:
7478621f407SFrançois Tigeot 		sc->gtt_total_entries = 1024 * 1024 / 4;
7488621f407SFrançois Tigeot 		break;
7498621f407SFrançois Tigeot 	case AGP_I810_PGTBL_SIZE_2MB:
7508621f407SFrançois Tigeot 		sc->gtt_total_entries = 2 * 1024 * 1024 / 4;
7518621f407SFrançois Tigeot 		break;
7528621f407SFrançois Tigeot 	case AGP_I810_PGTBL_SIZE_1_5MB:
7538621f407SFrançois Tigeot 		sc->gtt_total_entries = (1024 + 512) * 1024 / 4;
7548621f407SFrançois Tigeot 		break;
7558621f407SFrançois Tigeot 	default:
7568621f407SFrançois Tigeot 		device_printf(dev, "Unknown page table size\n");
7578621f407SFrançois Tigeot 		error = ENXIO;
7588621f407SFrançois Tigeot 	}
7598621f407SFrançois Tigeot 	return (error);
7608621f407SFrançois Tigeot }
7618621f407SFrançois Tigeot 
7628621f407SFrançois Tigeot static void
agp_gen5_adjust_pgtbl_size(device_t dev,uint32_t sz)7638621f407SFrançois Tigeot agp_gen5_adjust_pgtbl_size(device_t dev, uint32_t sz)
7648621f407SFrançois Tigeot {
7658621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
7668621f407SFrançois Tigeot 	uint32_t pgetbl_ctl, pgetbl_ctl2;
7678621f407SFrançois Tigeot 
7688621f407SFrançois Tigeot 	sc = device_get_softc(dev);
7698621f407SFrançois Tigeot 
7708621f407SFrançois Tigeot 	/* Disable per-process page table. */
7718621f407SFrançois Tigeot 	pgetbl_ctl2 = bus_read_4(sc->sc_res[0], AGP_I965_PGTBL_CTL2);
7728621f407SFrançois Tigeot 	pgetbl_ctl2 &= ~AGP_I810_PGTBL_ENABLED;
7738621f407SFrançois Tigeot 	bus_write_4(sc->sc_res[0], AGP_I965_PGTBL_CTL2, pgetbl_ctl2);
7748621f407SFrançois Tigeot 
7758621f407SFrançois Tigeot 	/* Write the new ggtt size. */
7768621f407SFrançois Tigeot 	pgetbl_ctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
7778621f407SFrançois Tigeot 	pgetbl_ctl &= ~AGP_I810_PGTBL_SIZE_MASK;
7788621f407SFrançois Tigeot 	pgetbl_ctl |= sz;
7798621f407SFrançois Tigeot 	bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgetbl_ctl);
7808621f407SFrançois Tigeot }
7818621f407SFrançois Tigeot 
7828621f407SFrançois Tigeot static int
agp_gen5_get_gtt_total_entries(device_t dev)7838621f407SFrançois Tigeot agp_gen5_get_gtt_total_entries(device_t dev)
7848621f407SFrançois Tigeot {
7858621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
7868621f407SFrançois Tigeot 	uint16_t gcc1;
7878621f407SFrançois Tigeot 
7888621f407SFrançois Tigeot 	sc = device_get_softc(dev);
7898621f407SFrançois Tigeot 
7908621f407SFrançois Tigeot 	gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
7918621f407SFrançois Tigeot 	switch (gcc1 & AGP_G4x_GCC1_SIZE_MASK) {
7928621f407SFrançois Tigeot 	case AGP_G4x_GCC1_SIZE_1M:
7938621f407SFrançois Tigeot 	case AGP_G4x_GCC1_SIZE_VT_1M:
7948621f407SFrançois Tigeot 		agp_gen5_adjust_pgtbl_size(dev, AGP_I810_PGTBL_SIZE_1MB);
7958621f407SFrançois Tigeot 		break;
7968621f407SFrançois Tigeot 	case AGP_G4x_GCC1_SIZE_VT_1_5M:
7978621f407SFrançois Tigeot 		agp_gen5_adjust_pgtbl_size(dev, AGP_I810_PGTBL_SIZE_1_5MB);
7988621f407SFrançois Tigeot 		break;
7998621f407SFrançois Tigeot 	case AGP_G4x_GCC1_SIZE_2M:
8008621f407SFrançois Tigeot 	case AGP_G4x_GCC1_SIZE_VT_2M:
8018621f407SFrançois Tigeot 		agp_gen5_adjust_pgtbl_size(dev, AGP_I810_PGTBL_SIZE_2MB);
8028621f407SFrançois Tigeot 		break;
8038621f407SFrançois Tigeot 	default:
8048621f407SFrançois Tigeot 		device_printf(dev, "Unknown page table size\n");
8058621f407SFrançois Tigeot 		return (ENXIO);
8068621f407SFrançois Tigeot 	}
8078621f407SFrançois Tigeot 
8088621f407SFrançois Tigeot 	return (agp_i965_get_gtt_total_entries(dev));
8098621f407SFrançois Tigeot }
8108621f407SFrançois Tigeot 
8118621f407SFrançois Tigeot static int
agp_i830_install_gatt(device_t dev)8128621f407SFrançois Tigeot agp_i830_install_gatt(device_t dev)
8138621f407SFrançois Tigeot {
8148621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
8158621f407SFrançois Tigeot 	uint32_t pgtblctl;
8168621f407SFrançois Tigeot 
8178621f407SFrançois Tigeot 	sc = device_get_softc(dev);
8188621f407SFrançois Tigeot 
8198621f407SFrançois Tigeot 	/*
8208621f407SFrançois Tigeot 	 * The i830 automatically initializes the 128k gatt on boot.
8218621f407SFrançois Tigeot 	 * GATT address is already in there, make sure it's enabled.
8228621f407SFrançois Tigeot 	 */
8238621f407SFrançois Tigeot 	pgtblctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
8248621f407SFrançois Tigeot 	pgtblctl |= 1;
8258621f407SFrançois Tigeot 	bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgtblctl);
8268621f407SFrançois Tigeot 
8278621f407SFrançois Tigeot 	sc->gatt->ag_physical = pgtblctl & ~1;
8288621f407SFrançois Tigeot 	return (0);
8298621f407SFrançois Tigeot }
8308621f407SFrançois Tigeot 
8318621f407SFrançois Tigeot static int
agp_i810_attach(device_t dev)8328621f407SFrançois Tigeot agp_i810_attach(device_t dev)
8338621f407SFrançois Tigeot {
8348621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
8358621f407SFrançois Tigeot 	int error;
8368621f407SFrançois Tigeot 
8378621f407SFrançois Tigeot 	sc = device_get_softc(dev);
8388621f407SFrançois Tigeot 	sc->bdev = agp_i810_find_bridge(dev);
8398621f407SFrançois Tigeot 	if (sc->bdev == NULL)
8408621f407SFrançois Tigeot 		return (ENOENT);
8418621f407SFrançois Tigeot 
8428621f407SFrançois Tigeot 	sc->match = agp_i810_match(dev);
8438621f407SFrançois Tigeot 
8448621f407SFrançois Tigeot 	agp_set_aperture_resource(dev, sc->match->driver->gen <= 2 ?
8458621f407SFrançois Tigeot 	    AGP_APBASE : AGP_I915_GMADR);
8468621f407SFrançois Tigeot 	error = agp_generic_attach(dev);
8478621f407SFrançois Tigeot 	if (error)
8488621f407SFrançois Tigeot 		return (error);
8498621f407SFrançois Tigeot 
8508621f407SFrançois Tigeot 	if (ptoa((vm_paddr_t)Maxmem) >
8518621f407SFrançois Tigeot 	    (1ULL << sc->match->driver->busdma_addr_mask_sz) - 1) {
8528621f407SFrançois Tigeot 		device_printf(dev, "agp_i810 does not support physical "
8538621f407SFrançois Tigeot 		    "memory above %ju.\n", (uintmax_t)(1ULL <<
8548621f407SFrançois Tigeot 		    sc->match->driver->busdma_addr_mask_sz) - 1);
8558621f407SFrançois Tigeot 		return (ENOENT);
8568621f407SFrançois Tigeot 	}
8578621f407SFrançois Tigeot 
8588621f407SFrançois Tigeot 	if (bus_alloc_resources(dev, sc->match->driver->res_spec, sc->sc_res)) {
8598621f407SFrançois Tigeot 		agp_generic_detach(dev);
8608621f407SFrançois Tigeot 		return (ENODEV);
8618621f407SFrançois Tigeot 	}
8628621f407SFrançois Tigeot 
8638621f407SFrançois Tigeot 	sc->initial_aperture = AGP_GET_APERTURE(dev);
8648621f407SFrançois Tigeot 	sc->gatt = kmalloc(sizeof(struct agp_gatt), M_DRM, M_WAITOK);
8658621f407SFrançois Tigeot 	sc->gatt->ag_entries = AGP_GET_APERTURE(dev) >> AGP_PAGE_SHIFT;
8668621f407SFrançois Tigeot 
8678621f407SFrançois Tigeot 	if ((error = sc->match->driver->get_stolen_size(dev)) != 0 ||
8688621f407SFrançois Tigeot 	    (error = sc->match->driver->install_gatt(dev)) != 0 ||
8698621f407SFrançois Tigeot 	    (error = sc->match->driver->get_gtt_mappable_entries(dev)) != 0 ||
8708621f407SFrançois Tigeot 	    (error = sc->match->driver->get_gtt_total_entries(dev)) != 0 ||
8718621f407SFrançois Tigeot 	    (error = sc->match->driver->chipset_flush_setup(dev)) != 0) {
8728621f407SFrançois Tigeot 		bus_release_resources(dev, sc->match->driver->res_spec,
8738621f407SFrançois Tigeot 		    sc->sc_res);
8748621f407SFrançois Tigeot 		kfree(sc->gatt);
8758621f407SFrançois Tigeot 		agp_generic_detach(dev);
8768621f407SFrançois Tigeot 		return (error);
8778621f407SFrançois Tigeot 	}
8788621f407SFrançois Tigeot 
8798621f407SFrançois Tigeot 	intel_agp = dev;
8808621f407SFrançois Tigeot 	device_printf(dev, "aperture size is %dM",
8818621f407SFrançois Tigeot 	    sc->initial_aperture / 1024 / 1024);
8828621f407SFrançois Tigeot 	if (sc->stolen > 0)
8838621f407SFrançois Tigeot 		kprintf(", detected %dk stolen memory\n", sc->stolen * 4);
8848621f407SFrançois Tigeot 	else
8858621f407SFrançois Tigeot 		kprintf("\n");
8868621f407SFrançois Tigeot 	if (bootverbose) {
8878621f407SFrançois Tigeot 		sc->match->driver->dump_regs(dev);
8888621f407SFrançois Tigeot 		device_printf(dev, "Mappable GTT entries: %d\n",
8898621f407SFrançois Tigeot 		    sc->gtt_mappable_entries);
8908621f407SFrançois Tigeot 		device_printf(dev, "Total GTT entries: %d\n",
8918621f407SFrançois Tigeot 		    sc->gtt_total_entries);
8928621f407SFrançois Tigeot 	}
8938621f407SFrançois Tigeot 	return (0);
8948621f407SFrançois Tigeot }
8958621f407SFrançois Tigeot 
8968621f407SFrançois Tigeot static void
agp_i830_deinstall_gatt(device_t dev)8978621f407SFrançois Tigeot agp_i830_deinstall_gatt(device_t dev)
8988621f407SFrançois Tigeot {
8998621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
9008621f407SFrançois Tigeot 	unsigned int pgtblctl;
9018621f407SFrançois Tigeot 
9028621f407SFrançois Tigeot 	sc = device_get_softc(dev);
9038621f407SFrançois Tigeot 	pgtblctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
9048621f407SFrançois Tigeot 	pgtblctl &= ~1;
9058621f407SFrançois Tigeot 	bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgtblctl);
9068621f407SFrançois Tigeot }
9078621f407SFrançois Tigeot 
9088621f407SFrançois Tigeot static int
agp_i810_detach(device_t dev)9098621f407SFrançois Tigeot agp_i810_detach(device_t dev)
9108621f407SFrançois Tigeot {
9118621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
9128621f407SFrançois Tigeot 
9138621f407SFrançois Tigeot 	sc = device_get_softc(dev);
9148621f407SFrançois Tigeot 	agp_free_cdev(dev);
9158621f407SFrançois Tigeot 
9168621f407SFrançois Tigeot 	/* Clear the GATT base. */
9178621f407SFrançois Tigeot 	sc->match->driver->deinstall_gatt(dev);
9188621f407SFrançois Tigeot 
9198621f407SFrançois Tigeot 	sc->match->driver->chipset_flush_teardown(dev);
9208621f407SFrançois Tigeot 
9218621f407SFrançois Tigeot 	/* Put the aperture back the way it started. */
9228621f407SFrançois Tigeot 	AGP_SET_APERTURE(dev, sc->initial_aperture);
9238621f407SFrançois Tigeot 
9248621f407SFrançois Tigeot 	kfree(sc->gatt);
9258621f407SFrançois Tigeot 	bus_release_resources(dev, sc->match->driver->res_spec, sc->sc_res);
9268621f407SFrançois Tigeot 	agp_free_res(dev);
9278621f407SFrançois Tigeot 
9288621f407SFrançois Tigeot 	return (0);
9298621f407SFrançois Tigeot }
9308621f407SFrançois Tigeot 
9318621f407SFrançois Tigeot static int
agp_i810_resume(device_t dev)9328621f407SFrançois Tigeot agp_i810_resume(device_t dev)
9338621f407SFrançois Tigeot {
9348621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
9358621f407SFrançois Tigeot 	sc = device_get_softc(dev);
9368621f407SFrançois Tigeot 
9378621f407SFrançois Tigeot 	AGP_SET_APERTURE(dev, sc->initial_aperture);
9388621f407SFrançois Tigeot 
9398621f407SFrançois Tigeot 	/* Install the GATT. */
9408621f407SFrançois Tigeot 	bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL,
9418621f407SFrançois Tigeot 	sc->gatt->ag_physical | 1);
9428621f407SFrançois Tigeot 
9438621f407SFrançois Tigeot 	return (bus_generic_resume(dev));
9448621f407SFrançois Tigeot }
9458621f407SFrançois Tigeot 
9468621f407SFrançois Tigeot /**
9478621f407SFrançois Tigeot  * Sets the PCI resource size of the aperture on i830-class and below chipsets,
9488621f407SFrançois Tigeot  * while returning failure on later chipsets when an actual change is
9498621f407SFrançois Tigeot  * requested.
9508621f407SFrançois Tigeot  *
9518621f407SFrançois Tigeot  * This whole function is likely bogus, as the kernel would probably need to
9528621f407SFrançois Tigeot  * reconfigure the placement of the AGP aperture if a larger size is requested,
9538621f407SFrançois Tigeot  * which doesn't happen currently.
9548621f407SFrançois Tigeot  */
9558621f407SFrançois Tigeot 
9568621f407SFrançois Tigeot static int
agp_i915_set_aperture(device_t dev,u_int32_t aperture)9578621f407SFrançois Tigeot agp_i915_set_aperture(device_t dev, u_int32_t aperture)
9588621f407SFrançois Tigeot {
9598621f407SFrançois Tigeot 
9608621f407SFrançois Tigeot 	return (agp_generic_set_aperture(dev, aperture));
9618621f407SFrançois Tigeot }
9628621f407SFrançois Tigeot 
9638621f407SFrançois Tigeot static int
agp_i810_method_set_aperture(device_t dev,u_int32_t aperture)9648621f407SFrançois Tigeot agp_i810_method_set_aperture(device_t dev, u_int32_t aperture)
9658621f407SFrançois Tigeot {
9668621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
9678621f407SFrançois Tigeot 
9688621f407SFrançois Tigeot 	sc = device_get_softc(dev);
9698621f407SFrançois Tigeot 	return (sc->match->driver->set_aperture(dev, aperture));
9708621f407SFrançois Tigeot }
9718621f407SFrançois Tigeot 
9728621f407SFrançois Tigeot /**
9738621f407SFrançois Tigeot  * Writes a GTT entry mapping the page at the given offset from the
9748621f407SFrançois Tigeot  * beginning of the aperture to the given physical address.  Setup the
9758621f407SFrançois Tigeot  * caching mode according to flags.
9768621f407SFrançois Tigeot  *
9778621f407SFrançois Tigeot  * For gen 1, 2 and 3, GTT start is located at AGP_I810_GTT offset
9788621f407SFrançois Tigeot  * from corresponding BAR start. For gen 4, offset is 512KB +
9798621f407SFrançois Tigeot  * AGP_I810_GTT, for gen 5 and 6 it is 2MB + AGP_I810_GTT.
9808621f407SFrançois Tigeot  *
9818621f407SFrançois Tigeot  * Also, the bits of the physical page address above 4GB needs to be
9828621f407SFrançois Tigeot  * placed into bits 40-32 of PTE.
9838621f407SFrançois Tigeot  */
9848621f407SFrançois Tigeot static void
agp_i915_install_gtt_pte(device_t dev,u_int index,vm_offset_t physical,int flags)9858621f407SFrançois Tigeot agp_i915_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
9868621f407SFrançois Tigeot     int flags)
9878621f407SFrançois Tigeot {
9888621f407SFrançois Tigeot 	uint32_t pte;
9898621f407SFrançois Tigeot 
9908621f407SFrançois Tigeot 	pte = (u_int32_t)physical | I810_PTE_VALID;
9918621f407SFrançois Tigeot 	if (flags == AGP_USER_CACHED_MEMORY)
9928621f407SFrançois Tigeot 		pte |= I830_PTE_SYSTEM_CACHED;
9938621f407SFrançois Tigeot 
9948621f407SFrançois Tigeot 	agp_i915_write_gtt(dev, index, pte);
9958621f407SFrançois Tigeot }
9968621f407SFrançois Tigeot 
9978621f407SFrançois Tigeot static void
agp_i915_write_gtt(device_t dev,u_int index,uint32_t pte)9988621f407SFrançois Tigeot agp_i915_write_gtt(device_t dev, u_int index, uint32_t pte)
9998621f407SFrançois Tigeot {
10008621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
10018621f407SFrançois Tigeot 
10028621f407SFrançois Tigeot 	sc = device_get_softc(dev);
10038621f407SFrançois Tigeot 	bus_write_4(sc->sc_res[0], index * 4, pte);
10048621f407SFrançois Tigeot }
10058621f407SFrançois Tigeot 
10068621f407SFrançois Tigeot static void
agp_i965_install_gtt_pte(device_t dev,u_int index,vm_offset_t physical,int flags)10078621f407SFrançois Tigeot agp_i965_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
10088621f407SFrançois Tigeot     int flags)
10098621f407SFrançois Tigeot {
10108621f407SFrançois Tigeot 	uint32_t pte;
10118621f407SFrançois Tigeot 
10128621f407SFrançois Tigeot 	pte = (u_int32_t)physical | I810_PTE_VALID;
10138621f407SFrançois Tigeot 	if (flags == AGP_USER_CACHED_MEMORY)
10148621f407SFrançois Tigeot 		pte |= I830_PTE_SYSTEM_CACHED;
10158621f407SFrançois Tigeot 
10168621f407SFrançois Tigeot 	pte |= (physical >> 28) & 0xf0;
10178621f407SFrançois Tigeot 	agp_i965_write_gtt(dev, index, pte);
10188621f407SFrançois Tigeot }
10198621f407SFrançois Tigeot 
10208621f407SFrançois Tigeot static void
agp_i965_write_gtt(device_t dev,u_int index,uint32_t pte)10218621f407SFrançois Tigeot agp_i965_write_gtt(device_t dev, u_int index, uint32_t pte)
10228621f407SFrançois Tigeot {
10238621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
10248621f407SFrançois Tigeot 
10258621f407SFrançois Tigeot 	sc = device_get_softc(dev);
10268621f407SFrançois Tigeot 	bus_write_4(sc->sc_res[0], index * 4 + (512 * 1024), pte);
10278621f407SFrançois Tigeot }
10288621f407SFrançois Tigeot 
10298621f407SFrançois Tigeot static void
agp_g4x_install_gtt_pte(device_t dev,u_int index,vm_offset_t physical,int flags)10308621f407SFrançois Tigeot agp_g4x_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
10318621f407SFrançois Tigeot     int flags)
10328621f407SFrançois Tigeot {
10338621f407SFrançois Tigeot 	uint32_t pte;
10348621f407SFrançois Tigeot 
10358621f407SFrançois Tigeot 	pte = (u_int32_t)physical | I810_PTE_VALID;
10368621f407SFrançois Tigeot 	if (flags == AGP_USER_CACHED_MEMORY)
10378621f407SFrançois Tigeot 		pte |= I830_PTE_SYSTEM_CACHED;
10388621f407SFrançois Tigeot 
10398621f407SFrançois Tigeot 	pte |= (physical >> 28) & 0xf0;
10408621f407SFrançois Tigeot 	agp_g4x_write_gtt(dev, index, pte);
10418621f407SFrançois Tigeot }
10428621f407SFrançois Tigeot 
10438621f407SFrançois Tigeot static void
agp_g4x_write_gtt(device_t dev,u_int index,uint32_t pte)10448621f407SFrançois Tigeot agp_g4x_write_gtt(device_t dev, u_int index, uint32_t pte)
10458621f407SFrançois Tigeot {
10468621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
10478621f407SFrançois Tigeot 
10488621f407SFrançois Tigeot 	sc = device_get_softc(dev);
10498621f407SFrançois Tigeot 	bus_write_4(sc->sc_res[0], index * 4 + (2 * 1024 * 1024), pte);
10508621f407SFrançois Tigeot }
10518621f407SFrançois Tigeot 
10528621f407SFrançois Tigeot static int
agp_i810_bind_page(device_t dev,vm_offset_t offset,vm_offset_t physical)10538621f407SFrançois Tigeot agp_i810_bind_page(device_t dev, vm_offset_t offset, vm_offset_t physical)
10548621f407SFrançois Tigeot {
10558621f407SFrançois Tigeot 	struct agp_i810_softc *sc = device_get_softc(dev);
10568621f407SFrançois Tigeot 	u_int index;
10578621f407SFrançois Tigeot 
10588621f407SFrançois Tigeot 	if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) {
10598621f407SFrançois Tigeot 		device_printf(dev, "failed: offset is 0x%08jx, "
10608621f407SFrançois Tigeot 		    "shift is %d, entries is %d\n", (intmax_t)offset,
10618621f407SFrançois Tigeot 		    AGP_PAGE_SHIFT, sc->gatt->ag_entries);
10628621f407SFrançois Tigeot 		return (EINVAL);
10638621f407SFrançois Tigeot 	}
10648621f407SFrançois Tigeot 	index = offset >> AGP_PAGE_SHIFT;
10658621f407SFrançois Tigeot 	if (sc->stolen != 0 && index < sc->stolen) {
10668621f407SFrançois Tigeot 		device_printf(dev, "trying to bind into stolen memory\n");
10678621f407SFrançois Tigeot 		return (EINVAL);
10688621f407SFrançois Tigeot 	}
10698621f407SFrançois Tigeot 	sc->match->driver->install_gtt_pte(dev, index, physical, 0);
10708621f407SFrançois Tigeot 	return (0);
10718621f407SFrançois Tigeot }
10728621f407SFrançois Tigeot 
10738621f407SFrançois Tigeot static int
agp_i810_unbind_page(device_t dev,vm_offset_t offset)10748621f407SFrançois Tigeot agp_i810_unbind_page(device_t dev, vm_offset_t offset)
10758621f407SFrançois Tigeot {
10768621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
10778621f407SFrançois Tigeot 	u_int index;
10788621f407SFrançois Tigeot 
10798621f407SFrançois Tigeot 	sc = device_get_softc(dev);
10808621f407SFrançois Tigeot 	if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
10818621f407SFrançois Tigeot 		return (EINVAL);
10828621f407SFrançois Tigeot 	index = offset >> AGP_PAGE_SHIFT;
10838621f407SFrançois Tigeot 	if (sc->stolen != 0 && index < sc->stolen) {
10848621f407SFrançois Tigeot 		device_printf(dev, "trying to unbind from stolen memory\n");
10858621f407SFrançois Tigeot 		return (EINVAL);
10868621f407SFrançois Tigeot 	}
10878621f407SFrançois Tigeot 	sc->match->driver->install_gtt_pte(dev, index, 0, 0);
10888621f407SFrançois Tigeot 	return (0);
10898621f407SFrançois Tigeot }
10908621f407SFrançois Tigeot 
10918621f407SFrançois Tigeot static void
agp_i915_sync_gtt_pte(device_t dev,u_int index)10928621f407SFrançois Tigeot agp_i915_sync_gtt_pte(device_t dev, u_int index)
10938621f407SFrançois Tigeot {
10948621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
10958621f407SFrançois Tigeot 
10968621f407SFrançois Tigeot 	sc = device_get_softc(dev);
10978621f407SFrançois Tigeot 	bus_read_4(sc->sc_res[1], index * 4);
10988621f407SFrançois Tigeot }
10998621f407SFrançois Tigeot 
11008621f407SFrançois Tigeot static void
agp_i965_sync_gtt_pte(device_t dev,u_int index)11018621f407SFrançois Tigeot agp_i965_sync_gtt_pte(device_t dev, u_int index)
11028621f407SFrançois Tigeot {
11038621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
11048621f407SFrançois Tigeot 
11058621f407SFrançois Tigeot 	sc = device_get_softc(dev);
11068621f407SFrançois Tigeot 	bus_read_4(sc->sc_res[0], index * 4 + (512 * 1024));
11078621f407SFrançois Tigeot }
11088621f407SFrançois Tigeot 
11098621f407SFrançois Tigeot static void
agp_g4x_sync_gtt_pte(device_t dev,u_int index)11108621f407SFrançois Tigeot agp_g4x_sync_gtt_pte(device_t dev, u_int index)
11118621f407SFrançois Tigeot {
11128621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
11138621f407SFrançois Tigeot 
11148621f407SFrançois Tigeot 	sc = device_get_softc(dev);
11158621f407SFrançois Tigeot 	bus_read_4(sc->sc_res[0], index * 4 + (2 * 1024 * 1024));
11168621f407SFrançois Tigeot }
11178621f407SFrançois Tigeot 
11188621f407SFrançois Tigeot /*
11198621f407SFrançois Tigeot  * Writing via memory mapped registers already flushes all TLBs.
11208621f407SFrançois Tigeot  */
11218621f407SFrançois Tigeot static void
agp_i810_flush_tlb(device_t dev)11228621f407SFrançois Tigeot agp_i810_flush_tlb(device_t dev)
11238621f407SFrançois Tigeot {
11248621f407SFrançois Tigeot }
11258621f407SFrançois Tigeot 
11268621f407SFrançois Tigeot static int
agp_i810_enable(device_t dev,u_int32_t mode)11278621f407SFrançois Tigeot agp_i810_enable(device_t dev, u_int32_t mode)
11288621f407SFrançois Tigeot {
11298621f407SFrançois Tigeot 
11308621f407SFrançois Tigeot 	return (0);
11318621f407SFrançois Tigeot }
11328621f407SFrançois Tigeot 
11338621f407SFrançois Tigeot static struct agp_memory *
agp_i810_alloc_memory(device_t dev,int type,vm_size_t size)11348621f407SFrançois Tigeot agp_i810_alloc_memory(device_t dev, int type, vm_size_t size)
11358621f407SFrançois Tigeot {
11368621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
11378621f407SFrançois Tigeot 	struct agp_memory *mem;
11388621f407SFrançois Tigeot 	vm_page_t m;
11398621f407SFrançois Tigeot 
11408621f407SFrançois Tigeot 	sc = device_get_softc(dev);
11418621f407SFrançois Tigeot 
11428621f407SFrançois Tigeot 	if ((size & (AGP_PAGE_SIZE - 1)) != 0 ||
11438621f407SFrançois Tigeot 	    sc->agp.as_allocated + size > sc->agp.as_maxmem)
11448621f407SFrançois Tigeot 		return (0);
11458621f407SFrançois Tigeot 
11468621f407SFrançois Tigeot 	if (type == 1) {
11478621f407SFrançois Tigeot 		/*
11488621f407SFrançois Tigeot 		 * Mapping local DRAM into GATT.
11498621f407SFrançois Tigeot 		 */
11508621f407SFrançois Tigeot 		if (sc->match->driver->chiptype != CHIP_I810)
11518621f407SFrançois Tigeot 			return (0);
11528621f407SFrançois Tigeot 		if (size != sc->dcache_size)
11538621f407SFrançois Tigeot 			return (0);
11548621f407SFrançois Tigeot 	} else if (type == 2) {
11558621f407SFrançois Tigeot 		/*
11568621f407SFrançois Tigeot 		 * Type 2 is the contiguous physical memory type, that hands
11578621f407SFrançois Tigeot 		 * back a physical address.  This is used for cursors on i810.
11588621f407SFrançois Tigeot 		 * Hand back as many single pages with physical as the user
11598621f407SFrançois Tigeot 		 * wants, but only allow one larger allocation (ARGB cursor)
11608621f407SFrançois Tigeot 		 * for simplicity.
11618621f407SFrançois Tigeot 		 */
11628621f407SFrançois Tigeot 		if (size != AGP_PAGE_SIZE) {
11638621f407SFrançois Tigeot 			if (sc->argb_cursor != NULL)
11648621f407SFrançois Tigeot 				return (0);
11658621f407SFrançois Tigeot 
11668621f407SFrançois Tigeot 			/* Allocate memory for ARGB cursor, if we can. */
11678621f407SFrançois Tigeot 			sc->argb_cursor = contigmalloc(size, M_DRM,
11688621f407SFrançois Tigeot 			   0, 0, ~0, PAGE_SIZE, 0);
11698621f407SFrançois Tigeot 			if (sc->argb_cursor == NULL)
11708621f407SFrançois Tigeot 				return (0);
11718621f407SFrançois Tigeot 		}
11728621f407SFrançois Tigeot 	}
11738621f407SFrançois Tigeot 
11748621f407SFrançois Tigeot 	mem = kmalloc(sizeof *mem, M_DRM, M_INTWAIT);
11758621f407SFrançois Tigeot 	mem->am_id = sc->agp.as_nextid++;
11768621f407SFrançois Tigeot 	mem->am_size = size;
11778621f407SFrançois Tigeot 	mem->am_type = type;
11788621f407SFrançois Tigeot 	if (type != 1 && (type != 2 || size == AGP_PAGE_SIZE))
11798621f407SFrançois Tigeot 		mem->am_obj = vm_object_allocate(OBJT_DEFAULT,
11808621f407SFrançois Tigeot 		    atop(round_page(size)));
11818621f407SFrançois Tigeot 	else
11828621f407SFrançois Tigeot 		mem->am_obj = 0;
11838621f407SFrançois Tigeot 
11848621f407SFrançois Tigeot 	if (type == 2) {
11858621f407SFrançois Tigeot 		if (size == AGP_PAGE_SIZE) {
11868621f407SFrançois Tigeot 			/*
11878621f407SFrançois Tigeot 			 * Allocate and wire down the page now so that we can
11888621f407SFrançois Tigeot 			 * get its physical address.
11898621f407SFrançois Tigeot 			 */
11908621f407SFrançois Tigeot 			VM_OBJECT_LOCK(mem->am_obj);
11918621f407SFrançois Tigeot 			m = vm_page_grab(mem->am_obj, 0, VM_ALLOC_NORMAL |
11928621f407SFrançois Tigeot 							 VM_ALLOC_ZERO |
11938621f407SFrançois Tigeot 							 VM_ALLOC_RETRY);
11948621f407SFrançois Tigeot 			vm_page_wire(m);
11958621f407SFrançois Tigeot 			VM_OBJECT_UNLOCK(mem->am_obj);
11968621f407SFrançois Tigeot 			mem->am_physical = VM_PAGE_TO_PHYS(m);
11978621f407SFrançois Tigeot 			vm_page_wakeup(m);
11988621f407SFrançois Tigeot 		} else {
11998621f407SFrançois Tigeot 			/* Our allocation is already nicely wired down for us.
12008621f407SFrançois Tigeot 			 * Just grab the physical address.
12018621f407SFrançois Tigeot 			 */
12028621f407SFrançois Tigeot 			mem->am_physical = vtophys(sc->argb_cursor);
12038621f407SFrançois Tigeot 		}
12048621f407SFrançois Tigeot 	} else
12058621f407SFrançois Tigeot 		mem->am_physical = 0;
12068621f407SFrançois Tigeot 
12078621f407SFrançois Tigeot 	mem->am_offset = 0;
12088621f407SFrançois Tigeot 	mem->am_is_bound = 0;
12098621f407SFrançois Tigeot 	TAILQ_INSERT_TAIL(&sc->agp.as_memory, mem, am_link);
12108621f407SFrançois Tigeot 	sc->agp.as_allocated += size;
12118621f407SFrançois Tigeot 
12128621f407SFrançois Tigeot 	return (mem);
12138621f407SFrançois Tigeot }
12148621f407SFrançois Tigeot 
12158621f407SFrançois Tigeot static int
agp_i810_free_memory(device_t dev,struct agp_memory * mem)12168621f407SFrançois Tigeot agp_i810_free_memory(device_t dev, struct agp_memory *mem)
12178621f407SFrançois Tigeot {
12188621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
12198621f407SFrançois Tigeot 
12208621f407SFrançois Tigeot 	if (mem->am_is_bound)
12218621f407SFrançois Tigeot 		return (EBUSY);
12228621f407SFrançois Tigeot 
12238621f407SFrançois Tigeot 	sc = device_get_softc(dev);
12248621f407SFrançois Tigeot 
12258621f407SFrançois Tigeot 	if (mem->am_type == 2) {
12268621f407SFrançois Tigeot 		if (mem->am_size == AGP_PAGE_SIZE) {
12278621f407SFrançois Tigeot 			/*
12288621f407SFrançois Tigeot 			 * Unwire the page which we wired in alloc_memory.
12298621f407SFrançois Tigeot 			 */
12308621f407SFrançois Tigeot 			vm_page_t m;
12318621f407SFrançois Tigeot 
12328621f407SFrançois Tigeot 			vm_object_hold(mem->am_obj);
12338621f407SFrançois Tigeot 			m = vm_page_lookup_busy_wait(mem->am_obj, 0,
12348621f407SFrançois Tigeot 						     FALSE, "agppg");
12358621f407SFrançois Tigeot 			vm_object_drop(mem->am_obj);
12368621f407SFrançois Tigeot 			vm_page_unwire(m, 0);
12378621f407SFrançois Tigeot 			vm_page_wakeup(m);
12388621f407SFrançois Tigeot 		} else {
12398621f407SFrançois Tigeot 			contigfree(sc->argb_cursor, mem->am_size, M_DRM);
12408621f407SFrançois Tigeot 			sc->argb_cursor = NULL;
12418621f407SFrançois Tigeot 		}
12428621f407SFrançois Tigeot 	}
12438621f407SFrançois Tigeot 
12448621f407SFrançois Tigeot 	sc->agp.as_allocated -= mem->am_size;
12458621f407SFrançois Tigeot 	TAILQ_REMOVE(&sc->agp.as_memory, mem, am_link);
12468621f407SFrançois Tigeot 	if (mem->am_obj)
12478621f407SFrançois Tigeot 		vm_object_deallocate(mem->am_obj);
12488621f407SFrançois Tigeot 	kfree(mem);
12498621f407SFrançois Tigeot 	return (0);
12508621f407SFrançois Tigeot }
12518621f407SFrançois Tigeot 
12528621f407SFrançois Tigeot static int
agp_i810_bind_memory(device_t dev,struct agp_memory * mem,vm_offset_t offset)12538621f407SFrançois Tigeot agp_i810_bind_memory(device_t dev, struct agp_memory *mem, vm_offset_t offset)
12548621f407SFrançois Tigeot {
12558621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
12568621f407SFrançois Tigeot 	vm_offset_t i;
12578621f407SFrançois Tigeot 
12588621f407SFrançois Tigeot 	/* Do some sanity checks first. */
12598621f407SFrançois Tigeot 	if ((offset & (AGP_PAGE_SIZE - 1)) != 0 ||
12608621f407SFrançois Tigeot 	    offset + mem->am_size > AGP_GET_APERTURE(dev)) {
12618621f407SFrançois Tigeot 		device_printf(dev, "binding memory at bad offset %#x\n",
12628621f407SFrançois Tigeot 		    (int)offset);
12638621f407SFrançois Tigeot 		return (EINVAL);
12648621f407SFrançois Tigeot 	}
12658621f407SFrançois Tigeot 
12668621f407SFrançois Tigeot 	sc = device_get_softc(dev);
12678621f407SFrançois Tigeot 	if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) {
12688621f407SFrançois Tigeot 		lockmgr(&sc->agp.as_lock, LK_EXCLUSIVE);
12698621f407SFrançois Tigeot 		if (mem->am_is_bound) {
12708621f407SFrançois Tigeot 			lockmgr(&sc->agp.as_lock, LK_RELEASE);
12718621f407SFrançois Tigeot 			return EINVAL;
12728621f407SFrançois Tigeot 		}
12738621f407SFrançois Tigeot 		/* The memory's already wired down, just stick it in the GTT. */
12748621f407SFrançois Tigeot 		for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
12758621f407SFrançois Tigeot 			sc->match->driver->install_gtt_pte(dev, (offset + i) >>
12768621f407SFrançois Tigeot 			    AGP_PAGE_SHIFT, mem->am_physical + i, 0);
12778621f407SFrançois Tigeot 		}
12788621f407SFrançois Tigeot 		agp_flush_cache();
12798621f407SFrançois Tigeot 		mem->am_offset = offset;
12808621f407SFrançois Tigeot 		mem->am_is_bound = 1;
12818621f407SFrançois Tigeot 		lockmgr(&sc->agp.as_lock, LK_RELEASE);
12828621f407SFrançois Tigeot 		return (0);
12838621f407SFrançois Tigeot 	}
12848621f407SFrançois Tigeot 
12858621f407SFrançois Tigeot 	if (mem->am_type != 1)
12868621f407SFrançois Tigeot 		return (agp_generic_bind_memory(dev, mem, offset));
12878621f407SFrançois Tigeot 
12888621f407SFrançois Tigeot 	/*
12898621f407SFrançois Tigeot 	 * Mapping local DRAM into GATT.
12908621f407SFrançois Tigeot 	 */
12918621f407SFrançois Tigeot 	if (sc->match->driver->chiptype != CHIP_I810)
12928621f407SFrançois Tigeot 		return (EINVAL);
12938621f407SFrançois Tigeot 	for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
12948621f407SFrançois Tigeot 		bus_write_4(sc->sc_res[0],
12958621f407SFrançois Tigeot 		    AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, i | 3);
12968621f407SFrançois Tigeot 
12978621f407SFrançois Tigeot 	return (0);
12988621f407SFrançois Tigeot }
12998621f407SFrançois Tigeot 
13008621f407SFrançois Tigeot static int
agp_i810_unbind_memory(device_t dev,struct agp_memory * mem)13018621f407SFrançois Tigeot agp_i810_unbind_memory(device_t dev, struct agp_memory *mem)
13028621f407SFrançois Tigeot {
13038621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
13048621f407SFrançois Tigeot 	vm_offset_t i;
13058621f407SFrançois Tigeot 
13068621f407SFrançois Tigeot 	sc = device_get_softc(dev);
13078621f407SFrançois Tigeot 
13088621f407SFrançois Tigeot 	if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) {
13098621f407SFrançois Tigeot 		lockmgr(&sc->agp.as_lock, LK_EXCLUSIVE);
13108621f407SFrançois Tigeot 		if (!mem->am_is_bound) {
13118621f407SFrançois Tigeot 			lockmgr(&sc->agp.as_lock, LK_RELEASE);
13128621f407SFrançois Tigeot 			return (EINVAL);
13138621f407SFrançois Tigeot 		}
13148621f407SFrançois Tigeot 
13158621f407SFrançois Tigeot 		for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
13168621f407SFrançois Tigeot 			sc->match->driver->install_gtt_pte(dev,
13178621f407SFrançois Tigeot 			    (mem->am_offset + i) >> AGP_PAGE_SHIFT, 0, 0);
13188621f407SFrançois Tigeot 		}
13198621f407SFrançois Tigeot 		agp_flush_cache();
13208621f407SFrançois Tigeot 		mem->am_is_bound = 0;
13218621f407SFrançois Tigeot 		lockmgr(&sc->agp.as_lock, LK_RELEASE);
13228621f407SFrançois Tigeot 		return (0);
13238621f407SFrançois Tigeot 	}
13248621f407SFrançois Tigeot 
13258621f407SFrançois Tigeot 	if (mem->am_type != 1)
13268621f407SFrançois Tigeot 		return (agp_generic_unbind_memory(dev, mem));
13278621f407SFrançois Tigeot 
13288621f407SFrançois Tigeot 	if (sc->match->driver->chiptype != CHIP_I810)
13298621f407SFrançois Tigeot 		return (EINVAL);
13308621f407SFrançois Tigeot 	for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
13318621f407SFrançois Tigeot 		sc->match->driver->install_gtt_pte(dev, i >> AGP_PAGE_SHIFT,
13328621f407SFrançois Tigeot 		    0, 0);
13338621f407SFrançois Tigeot 	}
13348621f407SFrançois Tigeot 	return (0);
13358621f407SFrançois Tigeot }
13368621f407SFrançois Tigeot 
13378621f407SFrançois Tigeot static device_method_t agp_i810_methods[] = {
13388621f407SFrançois Tigeot 	/* Device interface */
13398621f407SFrançois Tigeot 	DEVMETHOD(device_identify,	agp_i810_identify),
13408621f407SFrançois Tigeot 	DEVMETHOD(device_probe,		agp_i810_probe),
13418621f407SFrançois Tigeot 	DEVMETHOD(device_attach,	agp_i810_attach),
13428621f407SFrançois Tigeot 	DEVMETHOD(device_detach,	agp_i810_detach),
13438621f407SFrançois Tigeot 	DEVMETHOD(device_suspend,	bus_generic_suspend),
13448621f407SFrançois Tigeot 	DEVMETHOD(device_resume,	agp_i810_resume),
13458621f407SFrançois Tigeot 
13468621f407SFrançois Tigeot 	/* AGP interface */
13478621f407SFrançois Tigeot 	DEVMETHOD(agp_get_aperture,	agp_generic_get_aperture),
13488621f407SFrançois Tigeot 	DEVMETHOD(agp_set_aperture,	agp_i810_method_set_aperture),
13498621f407SFrançois Tigeot 	DEVMETHOD(agp_bind_page,	agp_i810_bind_page),
13508621f407SFrançois Tigeot 	DEVMETHOD(agp_unbind_page,	agp_i810_unbind_page),
13518621f407SFrançois Tigeot 	DEVMETHOD(agp_flush_tlb,	agp_i810_flush_tlb),
13528621f407SFrançois Tigeot 	DEVMETHOD(agp_enable,		agp_i810_enable),
13538621f407SFrançois Tigeot 	DEVMETHOD(agp_alloc_memory,	agp_i810_alloc_memory),
13548621f407SFrançois Tigeot 	DEVMETHOD(agp_free_memory,	agp_i810_free_memory),
13558621f407SFrançois Tigeot 	DEVMETHOD(agp_bind_memory,	agp_i810_bind_memory),
13568621f407SFrançois Tigeot 	DEVMETHOD(agp_unbind_memory,	agp_i810_unbind_memory),
13578621f407SFrançois Tigeot 	DEVMETHOD(agp_chipset_flush,	agp_intel_gtt_chipset_flush),
13588621f407SFrançois Tigeot 
13598621f407SFrançois Tigeot 	DEVMETHOD_END
13608621f407SFrançois Tigeot };
13618621f407SFrançois Tigeot 
13628621f407SFrançois Tigeot static driver_t agp_i810_driver = {
13638621f407SFrançois Tigeot 	"agp",
13648621f407SFrançois Tigeot 	agp_i810_methods,
13658621f407SFrançois Tigeot 	sizeof(struct agp_i810_softc),
13668621f407SFrançois Tigeot };
13678621f407SFrançois Tigeot 
13688621f407SFrançois Tigeot static devclass_t agp_devclass;
13698621f407SFrançois Tigeot 
13708621f407SFrançois Tigeot DRIVER_MODULE(agp_i810, vgapci, agp_i810_driver, agp_devclass, NULL, NULL);
13718621f407SFrançois Tigeot MODULE_DEPEND(agp_i810, agp, 1, 1, 1);
13728621f407SFrançois Tigeot MODULE_DEPEND(agp_i810, pci, 1, 1, 1);
13738621f407SFrançois Tigeot 
13748621f407SFrançois Tigeot extern vm_page_t bogus_page;
13758621f407SFrançois Tigeot 
13768621f407SFrançois Tigeot void
agp_intel_gtt_clear_range(device_t dev,u_int first_entry,u_int num_entries)13778621f407SFrançois Tigeot agp_intel_gtt_clear_range(device_t dev, u_int first_entry, u_int num_entries)
13788621f407SFrançois Tigeot {
13798621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
13808621f407SFrançois Tigeot 	u_int i;
13818621f407SFrançois Tigeot 
13828621f407SFrançois Tigeot 	sc = device_get_softc(dev);
13838621f407SFrançois Tigeot 	for (i = 0; i < num_entries; i++)
13848621f407SFrançois Tigeot 		sc->match->driver->install_gtt_pte(dev, first_entry + i,
13858621f407SFrançois Tigeot 		    VM_PAGE_TO_PHYS(bogus_page), 0);
13868621f407SFrançois Tigeot 	sc->match->driver->sync_gtt_pte(dev, first_entry + num_entries - 1);
13878621f407SFrançois Tigeot }
13888621f407SFrançois Tigeot 
13898621f407SFrançois Tigeot void
agp_intel_gtt_insert_pages(device_t dev,u_int first_entry,u_int num_entries,vm_page_t * pages,u_int flags)13908621f407SFrançois Tigeot agp_intel_gtt_insert_pages(device_t dev, u_int first_entry, u_int num_entries,
13918621f407SFrançois Tigeot     vm_page_t *pages, u_int flags)
13928621f407SFrançois Tigeot {
13938621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
13948621f407SFrançois Tigeot 	u_int i;
13958621f407SFrançois Tigeot 
13968621f407SFrançois Tigeot 	sc = device_get_softc(dev);
13978621f407SFrançois Tigeot 	for (i = 0; i < num_entries; i++) {
13988621f407SFrançois Tigeot 		KKASSERT(pages[i]->valid == VM_PAGE_BITS_ALL);
13998621f407SFrançois Tigeot 		KKASSERT(pages[i]->wire_count > 0);
14008621f407SFrançois Tigeot 		sc->match->driver->install_gtt_pte(dev, first_entry + i,
14018621f407SFrançois Tigeot 		    VM_PAGE_TO_PHYS(pages[i]), flags);
14028621f407SFrançois Tigeot 	}
14038621f407SFrançois Tigeot 	sc->match->driver->sync_gtt_pte(dev, first_entry + num_entries - 1);
14048621f407SFrançois Tigeot }
14058621f407SFrançois Tigeot 
14068621f407SFrançois Tigeot void
intel_gtt_insert_page(dma_addr_t addr,unsigned int pg,unsigned int flags)14071487f786SFrançois Tigeot intel_gtt_insert_page(dma_addr_t addr, unsigned int pg, unsigned int flags)
14081487f786SFrançois Tigeot {
14091487f786SFrançois Tigeot 	struct agp_i810_softc *sc = device_get_softc(intel_agp);
14101487f786SFrançois Tigeot 
14111487f786SFrançois Tigeot 	sc->match->driver->install_gtt_pte(intel_agp, addr, pg, flags);
14121487f786SFrançois Tigeot }
14131487f786SFrançois Tigeot 
14141487f786SFrançois Tigeot void
intel_gtt_insert_sg_entries(struct sg_table * st,unsigned int pg_start,unsigned int flags)14158621f407SFrançois Tigeot intel_gtt_insert_sg_entries(struct sg_table *st,
14168621f407SFrançois Tigeot 			    unsigned int pg_start,
14178621f407SFrançois Tigeot 			    unsigned int flags)
14188621f407SFrançois Tigeot {
14198621f407SFrançois Tigeot 	struct agp_i810_softc *sc = device_get_softc(intel_agp);
14208621f407SFrançois Tigeot 	struct scatterlist *sg;
14218621f407SFrançois Tigeot 	dma_addr_t page;
14228621f407SFrançois Tigeot 	int i, j, npages, subpage;
14238621f407SFrançois Tigeot 
14248621f407SFrançois Tigeot 	i = 0;
14258621f407SFrançois Tigeot 	for_each_sg(st->sgl, sg, st->nents, j) {
14268621f407SFrançois Tigeot 		npages = sg_dma_len(sg) / PAGE_SIZE;
14278621f407SFrançois Tigeot 		for (subpage = 0; subpage < npages; subpage++) {
14288621f407SFrançois Tigeot 			page = sg_dma_address(sg) + subpage * PAGE_SIZE;
14298621f407SFrançois Tigeot 			sc->match->driver->install_gtt_pte(intel_agp,
14308621f407SFrançois Tigeot 				pg_start + i, page, flags);
14318621f407SFrançois Tigeot 			i++;
14328621f407SFrançois Tigeot 		}
14338621f407SFrançois Tigeot 	}
14348621f407SFrançois Tigeot 	sc->match->driver->sync_gtt_pte(intel_agp, pg_start + i - 1);
14358621f407SFrançois Tigeot }
14368621f407SFrançois Tigeot 
14378621f407SFrançois Tigeot 
14388621f407SFrançois Tigeot struct intel_gtt
agp_intel_gtt_get(device_t dev)14398621f407SFrançois Tigeot agp_intel_gtt_get(device_t dev)
14408621f407SFrançois Tigeot {
14418621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
14428621f407SFrançois Tigeot 	struct intel_gtt res;
14438621f407SFrançois Tigeot 
14448621f407SFrançois Tigeot 	sc = device_get_softc(dev);
14458621f407SFrançois Tigeot 	res.stolen_size = sc->stolen_size;
14468621f407SFrançois Tigeot 	res.gtt_total_entries = sc->gtt_total_entries;
14478621f407SFrançois Tigeot 	res.gtt_mappable_entries = sc->gtt_mappable_entries;
14488621f407SFrançois Tigeot 	res.do_idle_maps = 0;
14498621f407SFrançois Tigeot 	res.scratch_page_dma = VM_PAGE_TO_PHYS(bogus_page);
14508621f407SFrançois Tigeot 	return (res);
14518621f407SFrançois Tigeot }
14528621f407SFrançois Tigeot 
14538621f407SFrançois Tigeot static int
agp_i915_chipset_flush_alloc_page(device_t dev,uint64_t start,uint64_t end)14548621f407SFrançois Tigeot agp_i915_chipset_flush_alloc_page(device_t dev, uint64_t start, uint64_t end)
14558621f407SFrançois Tigeot {
14568621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
14578621f407SFrançois Tigeot 	device_t vga;
14588621f407SFrançois Tigeot 
14598621f407SFrançois Tigeot 	sc = device_get_softc(dev);
14608621f407SFrançois Tigeot 	vga = device_get_parent(dev);
14618621f407SFrançois Tigeot 	sc->sc_flush_page_rid = 100;
14628621f407SFrançois Tigeot 	sc->sc_flush_page_res = BUS_ALLOC_RESOURCE(device_get_parent(vga), dev,
14638621f407SFrançois Tigeot 	    SYS_RES_MEMORY, &sc->sc_flush_page_rid, start, end, PAGE_SIZE,
14648621f407SFrançois Tigeot 	    RF_ACTIVE, -1);
14658621f407SFrançois Tigeot 	if (sc->sc_flush_page_res == NULL) {
14668621f407SFrançois Tigeot 		device_printf(dev, "Failed to allocate flush page at 0x%jx\n",
14678621f407SFrançois Tigeot 		    (uintmax_t)start);
14688621f407SFrançois Tigeot 		return (EINVAL);
14698621f407SFrançois Tigeot 	}
14708621f407SFrançois Tigeot 	sc->sc_flush_page_vaddr = rman_get_virtual(sc->sc_flush_page_res);
14718621f407SFrançois Tigeot 	if (bootverbose) {
14728621f407SFrançois Tigeot 		device_printf(dev, "Allocated flush page phys 0x%jx virt %p\n",
14738621f407SFrançois Tigeot 		    (uintmax_t)rman_get_start(sc->sc_flush_page_res),
14748621f407SFrançois Tigeot 		    sc->sc_flush_page_vaddr);
14758621f407SFrançois Tigeot 	}
14768621f407SFrançois Tigeot 	return (0);
14778621f407SFrançois Tigeot }
14788621f407SFrançois Tigeot 
14798621f407SFrançois Tigeot static void
agp_i915_chipset_flush_free_page(device_t dev)14808621f407SFrançois Tigeot agp_i915_chipset_flush_free_page(device_t dev)
14818621f407SFrançois Tigeot {
14828621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
14838621f407SFrançois Tigeot 	device_t vga;
14848621f407SFrançois Tigeot 
14858621f407SFrançois Tigeot 	sc = device_get_softc(dev);
14868621f407SFrançois Tigeot 	vga = device_get_parent(dev);
14878621f407SFrançois Tigeot 	if (sc->sc_flush_page_res == NULL)
14888621f407SFrançois Tigeot 		return;
14898621f407SFrançois Tigeot 	BUS_DEACTIVATE_RESOURCE(device_get_parent(vga), dev, SYS_RES_MEMORY,
14908621f407SFrançois Tigeot 	    sc->sc_flush_page_rid, sc->sc_flush_page_res);
14918621f407SFrançois Tigeot 	BUS_RELEASE_RESOURCE(device_get_parent(vga), dev, SYS_RES_MEMORY,
14928621f407SFrançois Tigeot 	    sc->sc_flush_page_rid, sc->sc_flush_page_res);
14938621f407SFrançois Tigeot }
14948621f407SFrançois Tigeot 
14958621f407SFrançois Tigeot static int
agp_i915_chipset_flush_setup(device_t dev)14968621f407SFrançois Tigeot agp_i915_chipset_flush_setup(device_t dev)
14978621f407SFrançois Tigeot {
14988621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
14998621f407SFrançois Tigeot 	uint32_t temp;
15008621f407SFrançois Tigeot 	int error;
15018621f407SFrançois Tigeot 
15028621f407SFrançois Tigeot 	sc = device_get_softc(dev);
15038621f407SFrançois Tigeot 	temp = pci_read_config(sc->bdev, AGP_I915_IFPADDR, 4);
15048621f407SFrançois Tigeot 	if ((temp & 1) != 0) {
15058621f407SFrançois Tigeot 		temp &= ~1;
15068621f407SFrançois Tigeot 		if (bootverbose)
15078621f407SFrançois Tigeot 			device_printf(dev,
15088621f407SFrançois Tigeot 			    "Found already configured flush page at 0x%jx\n",
15098621f407SFrançois Tigeot 			    (uintmax_t)temp);
15108621f407SFrançois Tigeot 		sc->sc_bios_allocated_flush_page = 1;
15118621f407SFrançois Tigeot 		/*
15128621f407SFrançois Tigeot 		 * In the case BIOS initialized the flush pointer (?)
15138621f407SFrançois Tigeot 		 * register, expect that BIOS also set up the resource
15148621f407SFrançois Tigeot 		 * for the page.
15158621f407SFrançois Tigeot 		 */
15168621f407SFrançois Tigeot 		error = agp_i915_chipset_flush_alloc_page(dev, temp,
15178621f407SFrançois Tigeot 		    temp + PAGE_SIZE - 1);
15188621f407SFrançois Tigeot 		if (error != 0)
15198621f407SFrançois Tigeot 			return (error);
15208621f407SFrançois Tigeot 	} else {
15218621f407SFrançois Tigeot 		sc->sc_bios_allocated_flush_page = 0;
15228621f407SFrançois Tigeot 		error = agp_i915_chipset_flush_alloc_page(dev, 0, 0xffffffff);
15238621f407SFrançois Tigeot 		if (error != 0)
15248621f407SFrançois Tigeot 			return (error);
15258621f407SFrançois Tigeot 		temp = rman_get_start(sc->sc_flush_page_res);
15268621f407SFrançois Tigeot 		pci_write_config(sc->bdev, AGP_I915_IFPADDR, temp | 1, 4);
15278621f407SFrançois Tigeot 	}
15288621f407SFrançois Tigeot 	return (0);
15298621f407SFrançois Tigeot }
15308621f407SFrançois Tigeot 
15318621f407SFrançois Tigeot static void
agp_i915_chipset_flush_teardown(device_t dev)15328621f407SFrançois Tigeot agp_i915_chipset_flush_teardown(device_t dev)
15338621f407SFrançois Tigeot {
15348621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
15358621f407SFrançois Tigeot 	uint32_t temp;
15368621f407SFrançois Tigeot 
15378621f407SFrançois Tigeot 	sc = device_get_softc(dev);
15388621f407SFrançois Tigeot 	if (sc->sc_flush_page_res == NULL)
15398621f407SFrançois Tigeot 		return;
15408621f407SFrançois Tigeot 	if (!sc->sc_bios_allocated_flush_page) {
15418621f407SFrançois Tigeot 		temp = pci_read_config(sc->bdev, AGP_I915_IFPADDR, 4);
15428621f407SFrançois Tigeot 		temp &= ~1;
15438621f407SFrançois Tigeot 		pci_write_config(sc->bdev, AGP_I915_IFPADDR, temp, 4);
15448621f407SFrançois Tigeot 	}
15458621f407SFrançois Tigeot 	agp_i915_chipset_flush_free_page(dev);
15468621f407SFrançois Tigeot }
15478621f407SFrançois Tigeot 
15488621f407SFrançois Tigeot static int
agp_i965_chipset_flush_setup(device_t dev)15498621f407SFrançois Tigeot agp_i965_chipset_flush_setup(device_t dev)
15508621f407SFrançois Tigeot {
15518621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
15528621f407SFrançois Tigeot 	uint64_t temp;
15538621f407SFrançois Tigeot 	uint32_t temp_hi, temp_lo;
15548621f407SFrançois Tigeot 	int error;
15558621f407SFrançois Tigeot 
15568621f407SFrançois Tigeot 	sc = device_get_softc(dev);
15578621f407SFrançois Tigeot 
15588621f407SFrançois Tigeot 	temp_hi = pci_read_config(sc->bdev, AGP_I965_IFPADDR + 4, 4);
15598621f407SFrançois Tigeot 	temp_lo = pci_read_config(sc->bdev, AGP_I965_IFPADDR, 4);
15608621f407SFrançois Tigeot 
15618621f407SFrançois Tigeot 	if ((temp_lo & 1) != 0) {
15628621f407SFrançois Tigeot 		temp = ((uint64_t)temp_hi << 32) | (temp_lo & ~1);
15638621f407SFrançois Tigeot 		if (bootverbose)
15648621f407SFrançois Tigeot 			device_printf(dev,
15658621f407SFrançois Tigeot 			    "Found already configured flush page at 0x%jx\n",
15668621f407SFrançois Tigeot 			    (uintmax_t)temp);
15678621f407SFrançois Tigeot 		sc->sc_bios_allocated_flush_page = 1;
15688621f407SFrançois Tigeot 		/*
15698621f407SFrançois Tigeot 		 * In the case BIOS initialized the flush pointer (?)
15708621f407SFrançois Tigeot 		 * register, expect that BIOS also set up the resource
15718621f407SFrançois Tigeot 		 * for the page.
15728621f407SFrançois Tigeot 		 */
15738621f407SFrançois Tigeot 		error = agp_i915_chipset_flush_alloc_page(dev, temp,
15748621f407SFrançois Tigeot 		    temp + PAGE_SIZE - 1);
15758621f407SFrançois Tigeot 		if (error != 0)
15768621f407SFrançois Tigeot 			return (error);
15778621f407SFrançois Tigeot 	} else {
15788621f407SFrançois Tigeot 		sc->sc_bios_allocated_flush_page = 0;
15798621f407SFrançois Tigeot 		error = agp_i915_chipset_flush_alloc_page(dev, 0, ~0);
15808621f407SFrançois Tigeot 		if (error != 0)
15818621f407SFrançois Tigeot 			return (error);
15828621f407SFrançois Tigeot 		temp = rman_get_start(sc->sc_flush_page_res);
15838621f407SFrançois Tigeot 		pci_write_config(sc->bdev, AGP_I965_IFPADDR + 4,
15848621f407SFrançois Tigeot 		    (temp >> 32) & UINT32_MAX, 4);
15858621f407SFrançois Tigeot 		pci_write_config(sc->bdev, AGP_I965_IFPADDR,
15868621f407SFrançois Tigeot 		    (temp & UINT32_MAX) | 1, 4);
15878621f407SFrançois Tigeot 	}
15888621f407SFrançois Tigeot 	return (0);
15898621f407SFrançois Tigeot }
15908621f407SFrançois Tigeot 
15918621f407SFrançois Tigeot static void
agp_i965_chipset_flush_teardown(device_t dev)15928621f407SFrançois Tigeot agp_i965_chipset_flush_teardown(device_t dev)
15938621f407SFrançois Tigeot {
15948621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
15958621f407SFrançois Tigeot 	uint32_t temp_lo;
15968621f407SFrançois Tigeot 
15978621f407SFrançois Tigeot 	sc = device_get_softc(dev);
15988621f407SFrançois Tigeot 	if (sc->sc_flush_page_res == NULL)
15998621f407SFrançois Tigeot 		return;
16008621f407SFrançois Tigeot 	if (!sc->sc_bios_allocated_flush_page) {
16018621f407SFrançois Tigeot 		temp_lo = pci_read_config(sc->bdev, AGP_I965_IFPADDR, 4);
16028621f407SFrançois Tigeot 		temp_lo &= ~1;
16038621f407SFrançois Tigeot 		pci_write_config(sc->bdev, AGP_I965_IFPADDR, temp_lo, 4);
16048621f407SFrançois Tigeot 	}
16058621f407SFrançois Tigeot 	agp_i915_chipset_flush_free_page(dev);
16068621f407SFrançois Tigeot }
16078621f407SFrançois Tigeot 
16088621f407SFrançois Tigeot static void
agp_i915_chipset_flush(device_t dev)16098621f407SFrançois Tigeot agp_i915_chipset_flush(device_t dev)
16108621f407SFrançois Tigeot {
16118621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
16128621f407SFrançois Tigeot 
16138621f407SFrançois Tigeot 	sc = device_get_softc(dev);
16148621f407SFrançois Tigeot 	*(uint32_t *)sc->sc_flush_page_vaddr = 1;
16158621f407SFrançois Tigeot }
16168621f407SFrançois Tigeot 
16178621f407SFrançois Tigeot int
agp_intel_gtt_chipset_flush(device_t dev)16188621f407SFrançois Tigeot agp_intel_gtt_chipset_flush(device_t dev)
16198621f407SFrançois Tigeot {
16208621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
16218621f407SFrançois Tigeot 
16228621f407SFrançois Tigeot 	sc = device_get_softc(dev);
16238621f407SFrançois Tigeot 	sc->match->driver->chipset_flush(dev);
16248621f407SFrançois Tigeot 	return (0);
16258621f407SFrançois Tigeot }
16268621f407SFrançois Tigeot 
16278621f407SFrançois Tigeot void
intel_gtt_clear_range(u_int first_entry,u_int num_entries)16288621f407SFrançois Tigeot intel_gtt_clear_range(u_int first_entry, u_int num_entries)
16298621f407SFrançois Tigeot {
16308621f407SFrançois Tigeot 
16318621f407SFrançois Tigeot 	agp_intel_gtt_clear_range(intel_agp, first_entry, num_entries);
16328621f407SFrançois Tigeot }
16338621f407SFrançois Tigeot 
intel_gtt_get(u64 * gtt_total,u32 * stolen_size,phys_addr_t * mappable_base,u64 * mappable_end)1634*a85cb24fSFrançois Tigeot void intel_gtt_get(u64 *gtt_total,
1635*a85cb24fSFrançois Tigeot 		   u32 *stolen_size,
1636*a85cb24fSFrançois Tigeot 		   phys_addr_t *mappable_base,
1637*a85cb24fSFrançois Tigeot 		   u64 *mappable_end)
16388621f407SFrançois Tigeot {
16398621f407SFrançois Tigeot 	struct agp_info ainfo;
16408621f407SFrançois Tigeot 
16418621f407SFrançois Tigeot 	intel_private.base = agp_intel_gtt_get(intel_agp);
16428621f407SFrançois Tigeot 
16438621f407SFrançois Tigeot 	*gtt_total = intel_private.base.gtt_total_entries << PAGE_SHIFT;
16448621f407SFrançois Tigeot 	*stolen_size = intel_private.base.stolen_size;
16458621f407SFrançois Tigeot 	agp_get_info(intel_agp, &ainfo);
16468621f407SFrançois Tigeot 	*mappable_base = ainfo.ai_aperture_base;
16478621f407SFrançois Tigeot 	*mappable_end = intel_private.base.gtt_mappable_entries << PAGE_SHIFT;
16488621f407SFrançois Tigeot }
16498621f407SFrançois Tigeot 
16508621f407SFrançois Tigeot int
intel_gtt_chipset_flush(void)16518621f407SFrançois Tigeot intel_gtt_chipset_flush(void)
16528621f407SFrançois Tigeot {
16538621f407SFrançois Tigeot 
16548621f407SFrançois Tigeot 	return (agp_intel_gtt_chipset_flush(intel_agp));
16558621f407SFrançois Tigeot }
16568621f407SFrançois Tigeot 
16578621f407SFrançois Tigeot /*
16588621f407SFrançois Tigeot  * Only used by gen6
16598621f407SFrançois Tigeot  */
16608621f407SFrançois Tigeot void
intel_gtt_sync_pte(u_int entry)16618621f407SFrançois Tigeot intel_gtt_sync_pte(u_int entry)
16628621f407SFrançois Tigeot {
16638621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
16648621f407SFrançois Tigeot 
16658621f407SFrançois Tigeot 	sc = device_get_softc(intel_agp);
16668621f407SFrançois Tigeot 	sc->match->driver->sync_gtt_pte(intel_agp, entry);
16678621f407SFrançois Tigeot }
16688621f407SFrançois Tigeot 
16698621f407SFrançois Tigeot /*
16708621f407SFrançois Tigeot  * Only used by gen6
16718621f407SFrançois Tigeot  */
16728621f407SFrançois Tigeot void
intel_gtt_write(u_int entry,uint32_t val)16738621f407SFrançois Tigeot intel_gtt_write(u_int entry, uint32_t val)
16748621f407SFrançois Tigeot {
16758621f407SFrançois Tigeot 	struct agp_i810_softc *sc;
16768621f407SFrançois Tigeot 
16778621f407SFrançois Tigeot 	sc = device_get_softc(intel_agp);
16788621f407SFrançois Tigeot 	sc->match->driver->write_gtt(intel_agp, entry, val);
16798621f407SFrançois Tigeot }
16808621f407SFrançois Tigeot 
16818621f407SFrançois Tigeot #define GFX_FLSH_CNTL	0x2170
16828621f407SFrançois Tigeot 
16838621f407SFrançois Tigeot bool
intel_enable_gtt(void)16848621f407SFrançois Tigeot intel_enable_gtt(void)
16858621f407SFrançois Tigeot {
16868621f407SFrançois Tigeot 	struct agp_i810_softc *sc = device_get_softc(intel_agp);
16878621f407SFrançois Tigeot 
16888621f407SFrançois Tigeot 	/* Some chipsets such as Pineview can't report if the GTT
16898621f407SFrançois Tigeot 	 * has been enabled or not.
16908621f407SFrançois Tigeot 	 * Assume everything is fine. */
16918621f407SFrançois Tigeot 
16928621f407SFrançois Tigeot 	/* Flush all chipset write buffers nevertheless */
16938621f407SFrançois Tigeot 	bus_write_4(sc->sc_res[0], GFX_FLSH_CNTL, 1);
16948621f407SFrançois Tigeot 	bus_write_4(sc->sc_res[0], GFX_FLSH_CNTL, 0);
16958621f407SFrançois Tigeot 
16968621f407SFrançois Tigeot 	return true;
16978621f407SFrançois Tigeot }
1698