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