intel-gtt: consolidate i830 setup
[linux-block.git] / drivers / char / agp / intel-gtt.c
index d22ffb811bf2cea4001a97d485327d668ff9d85a..fd977aa4a17dc0828b12692cff1bd78622d68a6d 100644 (file)
  * /fairy-tale-mode off
  */
 
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pagemap.h>
+#include <linux/agp_backend.h>
+#include <asm/smp.h>
+#include "agp.h"
+#include "intel-agp.h"
+#include <linux/intel-gtt.h>
+#include <drm/intel-gtt.h>
+
 /*
  * If we have Intel graphics, we're not going to have anything other than
  * an Intel IOMMU. So make the correct use of the PCI DMA API contingent
@@ -49,18 +61,45 @@ static struct gatt_mask intel_i810_masks[] =
         .type = INTEL_AGP_CACHED_MEMORY}
 };
 
+#define INTEL_AGP_UNCACHED_MEMORY              0
+#define INTEL_AGP_CACHED_MEMORY_LLC            1
+#define INTEL_AGP_CACHED_MEMORY_LLC_GFDT       2
+#define INTEL_AGP_CACHED_MEMORY_LLC_MLC        3
+#define INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT   4
+
+static struct gatt_mask intel_gen6_masks[] =
+{
+       {.mask = I810_PTE_VALID | GEN6_PTE_UNCACHED,
+        .type = INTEL_AGP_UNCACHED_MEMORY },
+       {.mask = I810_PTE_VALID | GEN6_PTE_LLC,
+         .type = INTEL_AGP_CACHED_MEMORY_LLC },
+       {.mask = I810_PTE_VALID | GEN6_PTE_LLC | GEN6_PTE_GFDT,
+         .type = INTEL_AGP_CACHED_MEMORY_LLC_GFDT },
+       {.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC,
+         .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC },
+       {.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC | GEN6_PTE_GFDT,
+         .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT },
+};
+
+struct intel_gtt_driver {
+       unsigned int gen : 8;
+       unsigned int is_g33 : 1;
+       unsigned int is_pineview : 1;
+       unsigned int is_ironlake : 1;
+       /* Chipset specific GTT setup */
+       int (*setup)(void);
+};
+
 static struct _intel_private {
+       struct intel_gtt base;
+       const struct intel_gtt_driver *driver;
        struct pci_dev *pcidev; /* device one */
+       struct pci_dev *bridge_dev;
        u8 __iomem *registers;
+       phys_addr_t gtt_bus_addr;
+       phys_addr_t gma_bus_addr;
        u32 __iomem *gtt;               /* I915G */
        int num_dcache_entries;
-       /* gtt_entries is the number of gtt entries that are already mapped
-        * to stolen memory.  Stolen memory is larger than the memory mapped
-        * through gtt_entries, as it includes some reserved space for the BIOS
-        * popup and for the GTT.
-        */
-       int gtt_entries;                        /* i830+ */
-       int gtt_total_size;
        union {
                void __iomem *i9xx_flush_page;
                void *i8xx_flush_page;
@@ -70,6 +109,11 @@ static struct _intel_private {
        int resource_valid;
 } intel_private;
 
+#define INTEL_GTT_GEN  intel_private.driver->gen
+#define IS_G33         intel_private.driver->is_g33
+#define IS_PINEVIEW    intel_private.driver->is_pineview
+#define IS_IRONLAKE    intel_private.driver->is_ironlake
+
 #ifdef USE_PCI_DMA_API
 static int intel_agp_map_page(struct page *page, dma_addr_t *ret)
 {
@@ -178,13 +222,6 @@ static void intel_agp_insert_sg_entries(struct agp_memory *mem,
                                        off_t pg_start, int mask_type)
 {
        int i, j;
-       u32 cache_bits = 0;
-
-       if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
-           agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
-       {
-               cache_bits = GEN6_PTE_LLC_MLC;
-       }
 
        for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
                writel(agp_bridge->driver->mask_memory(agp_bridge,
@@ -202,11 +239,12 @@ static int intel_i810_fetch_size(void)
        u32 smram_miscc;
        struct aper_size_info_fixed *values;
 
-       pci_read_config_dword(agp_bridge->dev, I810_SMRAM_MISCC, &smram_miscc);
+       pci_read_config_dword(intel_private.bridge_dev,
+                             I810_SMRAM_MISCC, &smram_miscc);
        values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
 
        if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) {
-               dev_warn(&agp_bridge->dev->dev, "i810 is disabled\n");
+               dev_warn(&intel_private.bridge_dev->dev, "i810 is disabled\n");
                return 0;
        }
        if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) {
@@ -271,7 +309,7 @@ static void intel_i810_cleanup(void)
        iounmap(intel_private.registers);
 }
 
-static void intel_i810_agp_enable(struct agp_bridge_data *bridge, u32 mode)
+static void intel_fake_agp_enable(struct agp_bridge_data *bridge, u32 mode)
 {
        return;
 }
@@ -317,6 +355,23 @@ static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge,
                return 0;
 }
 
+static int intel_gen6_type_to_mask_type(struct agp_bridge_data *bridge,
+                                       int type)
+{
+       unsigned int type_mask = type & ~AGP_USER_CACHED_MEMORY_GFDT;
+       unsigned int gfdt = type & AGP_USER_CACHED_MEMORY_GFDT;
+
+       if (type_mask == AGP_USER_UNCACHED_MEMORY)
+               return INTEL_AGP_UNCACHED_MEMORY;
+       else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC)
+               return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT :
+                             INTEL_AGP_CACHED_MEMORY_LLC_MLC;
+       else /* set 'normal'/'cached' to LLC by default */
+               return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_GFDT :
+                             INTEL_AGP_CACHED_MEMORY_LLC;
+}
+
+
 static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
                                int type)
 {
@@ -484,7 +539,7 @@ static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge,
        return addr | bridge->driver->masks[type].mask;
 }
 
-static struct aper_size_info_fixed intel_i830_sizes[] =
+static struct aper_size_info_fixed intel_fake_agp_sizes[] =
 {
        {128, 32768, 5},
        /* The 64M mode still requires a 128k gatt */
@@ -493,103 +548,49 @@ static struct aper_size_info_fixed intel_i830_sizes[] =
        {512, 131072, 7},
 };
 
-static void intel_i830_init_gtt_entries(void)
+static unsigned int intel_gtt_stolen_entries(void)
 {
        u16 gmch_ctrl;
-       int gtt_entries = 0;
        u8 rdct;
        int local = 0;
        static const int ddt[4] = { 0, 16, 32, 64 };
-       int size; /* reserved space (in kb) at the top of stolen memory */
+       unsigned int overhead_entries, stolen_entries;
+       unsigned int stolen_size = 0;
 
-       pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
+       pci_read_config_word(intel_private.bridge_dev,
+                            I830_GMCH_CTRL, &gmch_ctrl);
 
-       if (IS_I965) {
-               u32 pgetbl_ctl;
-               pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL);
+       if (INTEL_GTT_GEN > 4 || IS_PINEVIEW)
+               overhead_entries = 0;
+       else
+               overhead_entries = intel_private.base.gtt_mappable_entries
+                       / 1024;
 
-               /* The 965 has a field telling us the size of the GTT,
-                * which may be larger than what is necessary to map the
-                * aperture.
-                */
-               switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) {
-               case I965_PGETBL_SIZE_128KB:
-                       size = 128;
-                       break;
-               case I965_PGETBL_SIZE_256KB:
-                       size = 256;
-                       break;
-               case I965_PGETBL_SIZE_512KB:
-                       size = 512;
-                       break;
-               case I965_PGETBL_SIZE_1MB:
-                       size = 1024;
-                       break;
-               case I965_PGETBL_SIZE_2MB:
-                       size = 2048;
-                       break;
-               case I965_PGETBL_SIZE_1_5MB:
-                       size = 1024 + 512;
-                       break;
-               default:
-                       dev_info(&intel_private.pcidev->dev,
-                                "unknown page table size, assuming 512KB\n");
-                       size = 512;
-               }
-               size += 4; /* add in BIOS popup space */
-       } else if (IS_G33 && !IS_PINEVIEW) {
-       /* G33's GTT size defined in gmch_ctrl */
-               switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) {
-               case G33_PGETBL_SIZE_1M:
-                       size = 1024;
-                       break;
-               case G33_PGETBL_SIZE_2M:
-                       size = 2048;
-                       break;
-               default:
-                       dev_info(&agp_bridge->dev->dev,
-                                "unknown page table size 0x%x, assuming 512KB\n",
-                               (gmch_ctrl & G33_PGETBL_SIZE_MASK));
-                       size = 512;
-               }
-               size += 4;
-       } else if (IS_G4X || IS_PINEVIEW) {
-               /* On 4 series hardware, GTT stolen is separate from graphics
-                * stolen, ignore it in stolen gtt entries counting.  However,
-                * 4KB of the stolen memory doesn't get mapped to the GTT.
-                */
-               size = 4;
-       } else {
-               /* On previous hardware, the GTT size was just what was
-                * required to map the aperture.
-                */
-               size = agp_bridge->driver->fetch_size() + 4;
-       }
+       overhead_entries += 1; /* BIOS popup */
 
-       if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
-           agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) {
+       if (intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
+           intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) {
                switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
                case I830_GMCH_GMS_STOLEN_512:
-                       gtt_entries = KB(512) - KB(size);
+                       stolen_size = KB(512);
                        break;
                case I830_GMCH_GMS_STOLEN_1024:
-                       gtt_entries = MB(1) - KB(size);
+                       stolen_size = MB(1);
                        break;
                case I830_GMCH_GMS_STOLEN_8192:
-                       gtt_entries = MB(8) - KB(size);
+                       stolen_size = MB(8);
                        break;
                case I830_GMCH_GMS_LOCAL:
                        rdct = readb(intel_private.registers+I830_RDRAM_CHANNEL_TYPE);
-                       gtt_entries = (I830_RDRAM_ND(rdct) + 1) *
+                       stolen_size = (I830_RDRAM_ND(rdct) + 1) *
                                        MB(ddt[I830_RDRAM_DDT(rdct)]);
                        local = 1;
                        break;
                default:
-                       gtt_entries = 0;
+                       stolen_size = 0;
                        break;
                }
-       } else if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
-                  agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) {
+       } else if (INTEL_GTT_GEN == 6) {
                /*
                 * SandyBridge has new memory control reg at 0x50.w
                 */
@@ -597,142 +598,255 @@ static void intel_i830_init_gtt_entries(void)
                pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl);
                switch (snb_gmch_ctl & SNB_GMCH_GMS_STOLEN_MASK) {
                case SNB_GMCH_GMS_STOLEN_32M:
-                       gtt_entries = MB(32) - KB(size);
+                       stolen_size = MB(32);
                        break;
                case SNB_GMCH_GMS_STOLEN_64M:
-                       gtt_entries = MB(64) - KB(size);
+                       stolen_size = MB(64);
                        break;
                case SNB_GMCH_GMS_STOLEN_96M:
-                       gtt_entries = MB(96) - KB(size);
+                       stolen_size = MB(96);
                        break;
                case SNB_GMCH_GMS_STOLEN_128M:
-                       gtt_entries = MB(128) - KB(size);
+                       stolen_size = MB(128);
                        break;
                case SNB_GMCH_GMS_STOLEN_160M:
-                       gtt_entries = MB(160) - KB(size);
+                       stolen_size = MB(160);
                        break;
                case SNB_GMCH_GMS_STOLEN_192M:
-                       gtt_entries = MB(192) - KB(size);
+                       stolen_size = MB(192);
                        break;
                case SNB_GMCH_GMS_STOLEN_224M:
-                       gtt_entries = MB(224) - KB(size);
+                       stolen_size = MB(224);
                        break;
                case SNB_GMCH_GMS_STOLEN_256M:
-                       gtt_entries = MB(256) - KB(size);
+                       stolen_size = MB(256);
                        break;
                case SNB_GMCH_GMS_STOLEN_288M:
-                       gtt_entries = MB(288) - KB(size);
+                       stolen_size = MB(288);
                        break;
                case SNB_GMCH_GMS_STOLEN_320M:
-                       gtt_entries = MB(320) - KB(size);
+                       stolen_size = MB(320);
                        break;
                case SNB_GMCH_GMS_STOLEN_352M:
-                       gtt_entries = MB(352) - KB(size);
+                       stolen_size = MB(352);
                        break;
                case SNB_GMCH_GMS_STOLEN_384M:
-                       gtt_entries = MB(384) - KB(size);
+                       stolen_size = MB(384);
                        break;
                case SNB_GMCH_GMS_STOLEN_416M:
-                       gtt_entries = MB(416) - KB(size);
+                       stolen_size = MB(416);
                        break;
                case SNB_GMCH_GMS_STOLEN_448M:
-                       gtt_entries = MB(448) - KB(size);
+                       stolen_size = MB(448);
                        break;
                case SNB_GMCH_GMS_STOLEN_480M:
-                       gtt_entries = MB(480) - KB(size);
+                       stolen_size = MB(480);
                        break;
                case SNB_GMCH_GMS_STOLEN_512M:
-                       gtt_entries = MB(512) - KB(size);
+                       stolen_size = MB(512);
                        break;
                }
        } else {
                switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
                case I855_GMCH_GMS_STOLEN_1M:
-                       gtt_entries = MB(1) - KB(size);
+                       stolen_size = MB(1);
                        break;
                case I855_GMCH_GMS_STOLEN_4M:
-                       gtt_entries = MB(4) - KB(size);
+                       stolen_size = MB(4);
                        break;
                case I855_GMCH_GMS_STOLEN_8M:
-                       gtt_entries = MB(8) - KB(size);
+                       stolen_size = MB(8);
                        break;
                case I855_GMCH_GMS_STOLEN_16M:
-                       gtt_entries = MB(16) - KB(size);
+                       stolen_size = MB(16);
                        break;
                case I855_GMCH_GMS_STOLEN_32M:
-                       gtt_entries = MB(32) - KB(size);
+                       stolen_size = MB(32);
                        break;
                case I915_GMCH_GMS_STOLEN_48M:
-                       /* Check it's really I915G */
-                       if (IS_I915 || IS_I965 || IS_G33 || IS_G4X)
-                               gtt_entries = MB(48) - KB(size);
-                       else
-                               gtt_entries = 0;
+                       stolen_size = MB(48);
                        break;
                case I915_GMCH_GMS_STOLEN_64M:
-                       /* Check it's really I915G */
-                       if (IS_I915 || IS_I965 || IS_G33 || IS_G4X)
-                               gtt_entries = MB(64) - KB(size);
-                       else
-                               gtt_entries = 0;
+                       stolen_size = MB(64);
                        break;
                case G33_GMCH_GMS_STOLEN_128M:
-                       if (IS_G33 || IS_I965 || IS_G4X)
-                               gtt_entries = MB(128) - KB(size);
-                       else
-                               gtt_entries = 0;
+                       stolen_size = MB(128);
                        break;
                case G33_GMCH_GMS_STOLEN_256M:
-                       if (IS_G33 || IS_I965 || IS_G4X)
-                               gtt_entries = MB(256) - KB(size);
-                       else
-                               gtt_entries = 0;
+                       stolen_size = MB(256);
                        break;
                case INTEL_GMCH_GMS_STOLEN_96M:
-                       if (IS_I965 || IS_G4X)
-                               gtt_entries = MB(96) - KB(size);
-                       else
-                               gtt_entries = 0;
+                       stolen_size = MB(96);
                        break;
                case INTEL_GMCH_GMS_STOLEN_160M:
-                       if (IS_I965 || IS_G4X)
-                               gtt_entries = MB(160) - KB(size);
-                       else
-                               gtt_entries = 0;
+                       stolen_size = MB(160);
                        break;
                case INTEL_GMCH_GMS_STOLEN_224M:
-                       if (IS_I965 || IS_G4X)
-                               gtt_entries = MB(224) - KB(size);
-                       else
-                               gtt_entries = 0;
+                       stolen_size = MB(224);
                        break;
                case INTEL_GMCH_GMS_STOLEN_352M:
-                       if (IS_I965 || IS_G4X)
-                               gtt_entries = MB(352) - KB(size);
-                       else
-                               gtt_entries = 0;
+                       stolen_size = MB(352);
                        break;
                default:
-                       gtt_entries = 0;
+                       stolen_size = 0;
                        break;
                }
        }
-       if (!local && gtt_entries > intel_max_stolen) {
-               dev_info(&agp_bridge->dev->dev,
+
+       if (!local && stolen_size > intel_max_stolen) {
+               dev_info(&intel_private.bridge_dev->dev,
                         "detected %dK stolen memory, trimming to %dK\n",
-                        gtt_entries / KB(1), intel_max_stolen / KB(1));
-               gtt_entries = intel_max_stolen / KB(4);
-       } else if (gtt_entries > 0) {
-               dev_info(&agp_bridge->dev->dev, "detected %dK %s memory\n",
-                      gtt_entries / KB(1), local ? "local" : "stolen");
-               gtt_entries /= KB(4);
+                        stolen_size / KB(1), intel_max_stolen / KB(1));
+               stolen_size = intel_max_stolen;
+       } else if (stolen_size > 0) {
+               dev_info(&intel_private.bridge_dev->dev, "detected %dK %s memory\n",
+                      stolen_size / KB(1), local ? "local" : "stolen");
        } else {
-               dev_info(&agp_bridge->dev->dev,
+               dev_info(&intel_private.bridge_dev->dev,
                       "no pre-allocated video memory detected\n");
-               gtt_entries = 0;
+               stolen_size = 0;
        }
 
-       intel_private.gtt_entries = gtt_entries;
+       stolen_entries = stolen_size/KB(4) - overhead_entries;
+
+       return stolen_entries;
+}
+
+static unsigned int intel_gtt_total_entries(void)
+{
+       int size;
+
+       if (IS_G33 || INTEL_GTT_GEN == 4 || INTEL_GTT_GEN == 5) {
+               u32 pgetbl_ctl;
+               pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL);
+
+               switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) {
+               case I965_PGETBL_SIZE_128KB:
+                       size = KB(128);
+                       break;
+               case I965_PGETBL_SIZE_256KB:
+                       size = KB(256);
+                       break;
+               case I965_PGETBL_SIZE_512KB:
+                       size = KB(512);
+                       break;
+               case I965_PGETBL_SIZE_1MB:
+                       size = KB(1024);
+                       break;
+               case I965_PGETBL_SIZE_2MB:
+                       size = KB(2048);
+                       break;
+               case I965_PGETBL_SIZE_1_5MB:
+                       size = KB(1024 + 512);
+                       break;
+               default:
+                       dev_info(&intel_private.pcidev->dev,
+                                "unknown page table size, assuming 512KB\n");
+                       size = KB(512);
+               }
+
+               return size/4;
+       } else if (INTEL_GTT_GEN == 6) {
+               u16 snb_gmch_ctl;
+
+               pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl);
+               switch (snb_gmch_ctl & SNB_GTT_SIZE_MASK) {
+               default:
+               case SNB_GTT_SIZE_0M:
+                       printk(KERN_ERR "Bad GTT size mask: 0x%04x.\n", snb_gmch_ctl);
+                       size = MB(0);
+                       break;
+               case SNB_GTT_SIZE_1M:
+                       size = MB(1);
+                       break;
+               case SNB_GTT_SIZE_2M:
+                       size = MB(2);
+                       break;
+               }
+               return size/4;
+       } else {
+               /* On previous hardware, the GTT size was just what was
+                * required to map the aperture.
+                */
+               return intel_private.base.gtt_mappable_entries;
+       }
+}
+
+static unsigned int intel_gtt_mappable_entries(void)
+{
+       unsigned int aperture_size;
+       u16 gmch_ctrl;
+
+       aperture_size = 1024 * 1024;
+
+       pci_read_config_word(intel_private.bridge_dev,
+                            I830_GMCH_CTRL, &gmch_ctrl);
+
+       switch (intel_private.pcidev->device) {
+       case PCI_DEVICE_ID_INTEL_82830_CGC:
+       case PCI_DEVICE_ID_INTEL_82845G_IG:
+       case PCI_DEVICE_ID_INTEL_82855GM_IG:
+       case PCI_DEVICE_ID_INTEL_82865_IG:
+               if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_64M)
+                       aperture_size *= 64;
+               else
+                       aperture_size *= 128;
+               break;
+       default:
+               /* 9xx supports large sizes, just look at the length */
+               aperture_size = pci_resource_len(intel_private.pcidev, 2);
+               break;
+       }
+
+       return aperture_size >> PAGE_SHIFT;
+}
+
+static int intel_gtt_init(void)
+{
+       u32 gtt_map_size;
+
+       intel_private.base.gtt_mappable_entries = intel_gtt_mappable_entries();
+       intel_private.base.gtt_total_entries = intel_gtt_total_entries();
+
+       gtt_map_size = intel_private.base.gtt_total_entries * 4;
+
+       intel_private.gtt = ioremap(intel_private.gtt_bus_addr,
+                                   gtt_map_size);
+       if (!intel_private.gtt) {
+               iounmap(intel_private.registers);
+               return -ENOMEM;
+       }
+
+       global_cache_flush();   /* FIXME: ? */
+
+       /* we have to call this as early as possible after the MMIO base address is known */
+       intel_private.base.gtt_stolen_entries = intel_gtt_stolen_entries();
+       if (intel_private.base.gtt_stolen_entries == 0) {
+               iounmap(intel_private.registers);
+               iounmap(intel_private.gtt);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static int intel_fake_agp_fetch_size(void)
+{
+       unsigned int aper_size;
+       int i;
+       int num_sizes = ARRAY_SIZE(intel_fake_agp_sizes);
+
+       aper_size = (intel_private.base.gtt_mappable_entries << PAGE_SHIFT)
+                   / MB(1);
+
+       for (i = 0; i < num_sizes; i++) {
+               if (aper_size == intel_fake_agp_sizes[i].size) {
+                       agp_bridge->current_size = intel_fake_agp_sizes + i;
+                       return aper_size;
+               }
+       }
+
+       return 0;
 }
 
 static void intel_i830_fini_flush(void)
@@ -782,120 +896,93 @@ static void intel_i830_chipset_flush(struct agp_bridge_data *bridge)
                printk(KERN_ERR "Timed out waiting for cache flush.\n");
 }
 
-/* The intel i830 automatically initializes the agp aperture during POST.
- * Use the memory already set aside for in the GTT.
- */
-static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge)
+static void intel_enable_gtt(void)
 {
-       int page_order;
-       struct aper_size_info_fixed *size;
-       int num_entries;
-       u32 temp;
+       u32 ptetbl_addr, gma_addr;
+       u16 gmch_ctrl;
 
-       size = agp_bridge->current_size;
-       page_order = size->page_order;
-       num_entries = size->num_entries;
-       agp_bridge->gatt_table_real = NULL;
+       ptetbl_addr = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
 
-       pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp);
-       temp &= 0xfff80000;
+       pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &gma_addr);
+       intel_private.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK);
 
-       intel_private.registers = ioremap(temp, 128 * 4096);
-       if (!intel_private.registers)
-               return -ENOMEM;
+       pci_read_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, &gmch_ctrl);
+       gmch_ctrl |= I830_GMCH_ENABLED;
+       pci_write_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, gmch_ctrl);
 
-       temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
-       global_cache_flush();   /* FIXME: ?? */
+       writel(ptetbl_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
+       readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
+}
 
-       /* we have to call this as early as possible after the MMIO base address is known */
-       intel_i830_init_gtt_entries();
-       if (intel_private.gtt_entries == 0) {
-               iounmap(intel_private.registers);
+static int i830_setup(void)
+{
+       u32 reg_addr;
+
+       pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &reg_addr);
+       reg_addr &= 0xfff80000;
+
+       intel_private.registers = ioremap(reg_addr, KB(64));
+       if (!intel_private.registers)
                return -ENOMEM;
-       }
 
-       agp_bridge->gatt_table = NULL;
+       intel_private.gtt_bus_addr = reg_addr + I810_PTE_BASE;
 
-       agp_bridge->gatt_bus_addr = temp;
+       intel_i830_setup_flush();
 
        return 0;
 }
 
-/* Return the gatt table to a sane state. Use the top of stolen
- * memory for the GTT.
+/* The intel i830 automatically initializes the agp aperture during POST.
+ * Use the memory already set aside for in the GTT.
  */
-static int intel_i830_free_gatt_table(struct agp_bridge_data *bridge)
-{
-       return 0;
-}
-
-static int intel_i830_fetch_size(void)
+static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge)
 {
-       u16 gmch_ctrl;
-       struct aper_size_info_fixed *values;
+       int ret;
 
-       values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
+       ret = intel_private.driver->setup();
+       if (ret != 0)
+               return ret;
 
-       if (agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82830_HB &&
-           agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82845G_HB) {
-               /* 855GM/852GM/865G has 128MB aperture size */
-               agp_bridge->current_size = (void *) values;
-               agp_bridge->aperture_size_idx = 0;
-               return values[0].size;
-       }
+       ret = intel_gtt_init();
+       if (ret != 0)
+               return ret;
 
-       pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
+       agp_bridge->gatt_table_real = NULL;
+       agp_bridge->gatt_table = NULL;
+       agp_bridge->gatt_bus_addr = 0;
 
-       if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) {
-               agp_bridge->current_size = (void *) values;
-               agp_bridge->aperture_size_idx = 0;
-               return values[0].size;
-       } else {
-               agp_bridge->current_size = (void *) (values + 1);
-               agp_bridge->aperture_size_idx = 1;
-               return values[1].size;
-       }
+       return 0;
+}
 
+/* Return the gatt table to a sane state. Use the top of stolen
+ * memory for the GTT.
+ */
+static int intel_fake_agp_free_gatt_table(struct agp_bridge_data *bridge)
+{
        return 0;
 }
 
 static int intel_i830_configure(void)
 {
-       struct aper_size_info_fixed *current_size;
-       u32 temp;
-       u16 gmch_ctrl;
        int i;
 
-       current_size = A_SIZE_FIX(agp_bridge->current_size);
-
-       pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp);
-       agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
-
-       pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
-       gmch_ctrl |= I830_GMCH_ENABLED;
-       pci_write_config_word(agp_bridge->dev, I830_GMCH_CTRL, gmch_ctrl);
+       intel_enable_gtt();
 
-       writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
-       readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
+       agp_bridge->gart_bus_addr = intel_private.gma_bus_addr;
 
        if (agp_bridge->driver->needs_scratch_page) {
-               for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) {
-                       writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
+               for (i = intel_private.base.gtt_stolen_entries;
+                               i < intel_private.base.gtt_total_entries; i++) {
+                       writel(agp_bridge->scratch_page, intel_private.gtt+i);
                }
-               readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI Posting. */
+               readl(intel_private.gtt+i-1);   /* PCI Posting. */
        }
 
        global_cache_flush();
 
-       intel_i830_setup_flush();
        return 0;
 }
 
-static void intel_i830_cleanup(void)
-{
-       iounmap(intel_private.registers);
-}
-
 static int intel_i830_insert_entries(struct agp_memory *mem, off_t pg_start,
                                     int type)
 {
@@ -910,10 +997,10 @@ static int intel_i830_insert_entries(struct agp_memory *mem, off_t pg_start,
        temp = agp_bridge->current_size;
        num_entries = A_SIZE_FIX(temp)->num_entries;
 
-       if (pg_start < intel_private.gtt_entries) {
+       if (pg_start < intel_private.base.gtt_stolen_entries) {
                dev_printk(KERN_DEBUG, &intel_private.pcidev->dev,
-                          "pg_start == 0x%.8lx, intel_private.gtt_entries == 0x%.8x\n",
-                          pg_start, intel_private.gtt_entries);
+                          "pg_start == 0x%.8lx, gtt_stolen_entries == 0x%.8x\n",
+                          pg_start, intel_private.base.gtt_stolen_entries);
 
                dev_info(&intel_private.pcidev->dev,
                         "trying to insert into local/stolen memory\n");
@@ -942,9 +1029,9 @@ static int intel_i830_insert_entries(struct agp_memory *mem, off_t pg_start,
        for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
                writel(agp_bridge->driver->mask_memory(agp_bridge,
                                page_to_phys(mem->pages[i]), mask_type),
-                      intel_private.registers+I810_PTE_BASE+(j*4));
+                      intel_private.gtt+j);
        }
-       readl(intel_private.registers+I810_PTE_BASE+((j-1)*4));
+       readl(intel_private.gtt+j-1);
 
 out:
        ret = 0;
@@ -961,21 +1048,22 @@ static int intel_i830_remove_entries(struct agp_memory *mem, off_t pg_start,
        if (mem->page_count == 0)
                return 0;
 
-       if (pg_start < intel_private.gtt_entries) {
+       if (pg_start < intel_private.base.gtt_stolen_entries) {
                dev_info(&intel_private.pcidev->dev,
                         "trying to disable local/stolen memory\n");
                return -EINVAL;
        }
 
        for (i = pg_start; i < (mem->page_count + pg_start); i++) {
-               writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
+               writel(agp_bridge->scratch_page, intel_private.gtt+i);
        }
-       readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));
+       readl(intel_private.gtt+i-1);
 
        return 0;
 }
 
-static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count, int type)
+static struct agp_memory *intel_fake_agp_alloc_by_type(size_t pg_count,
+                                                      int type)
 {
        if (type == AGP_PHYS_MEMORY)
                return alloc_agpphysmem_i8xx(pg_count, type);
@@ -986,9 +1074,9 @@ static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count, int type)
 static int intel_alloc_chipset_flush_resource(void)
 {
        int ret;
-       ret = pci_bus_alloc_resource(agp_bridge->dev->bus, &intel_private.ifp_resource, PAGE_SIZE,
+       ret = pci_bus_alloc_resource(intel_private.bridge_dev->bus, &intel_private.ifp_resource, PAGE_SIZE,
                                     PAGE_SIZE, PCIBIOS_MIN_MEM, 0,
-                                    pcibios_align_resource, agp_bridge->dev);
+                                    pcibios_align_resource, intel_private.bridge_dev);
 
        return ret;
 }
@@ -998,11 +1086,11 @@ static void intel_i915_setup_chipset_flush(void)
        int ret;
        u32 temp;
 
-       pci_read_config_dword(agp_bridge->dev, I915_IFPADDR, &temp);
+       pci_read_config_dword(intel_private.bridge_dev, I915_IFPADDR, &temp);
        if (!(temp & 0x1)) {
                intel_alloc_chipset_flush_resource();
                intel_private.resource_valid = 1;
-               pci_write_config_dword(agp_bridge->dev, I915_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1);
+               pci_write_config_dword(intel_private.bridge_dev, I915_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1);
        } else {
                temp &= ~1;
 
@@ -1021,17 +1109,17 @@ static void intel_i965_g33_setup_chipset_flush(void)
        u32 temp_hi, temp_lo;
        int ret;
 
-       pci_read_config_dword(agp_bridge->dev, I965_IFPADDR + 4, &temp_hi);
-       pci_read_config_dword(agp_bridge->dev, I965_IFPADDR, &temp_lo);
+       pci_read_config_dword(intel_private.bridge_dev, I965_IFPADDR + 4, &temp_hi);
+       pci_read_config_dword(intel_private.bridge_dev, I965_IFPADDR, &temp_lo);
 
        if (!(temp_lo & 0x1)) {
 
                intel_alloc_chipset_flush_resource();
 
                intel_private.resource_valid = 1;
-               pci_write_config_dword(agp_bridge->dev, I965_IFPADDR + 4,
+               pci_write_config_dword(intel_private.bridge_dev, I965_IFPADDR + 4,
                        upper_32_bits(intel_private.ifp_resource.start));
-               pci_write_config_dword(agp_bridge->dev, I965_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1);
+               pci_write_config_dword(intel_private.bridge_dev, I965_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1);
        } else {
                u64 l64;
 
@@ -1054,7 +1142,7 @@ static void intel_i9xx_setup_flush(void)
        if (intel_private.ifp_resource.start)
                return;
 
-       if (IS_SNB)
+       if (INTEL_GTT_GEN == 6)
                return;
 
        /* setup a resource for this object */
@@ -1062,17 +1150,17 @@ static void intel_i9xx_setup_flush(void)
        intel_private.ifp_resource.flags = IORESOURCE_MEM;
 
        /* Setup chipset flush for 915 */
-       if (IS_I965 || IS_G33 || IS_G4X) {
+       if (IS_G33 || INTEL_GTT_GEN >= 4) {
                intel_i965_g33_setup_chipset_flush();
        } else {
                intel_i915_setup_chipset_flush();
        }
 
-       if (intel_private.ifp_resource.start) {
+       if (intel_private.ifp_resource.start)
                intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE);
-               if (!intel_private.i9xx_flush_page)
-                       dev_info(&intel_private.pcidev->dev, "can't ioremap flush page - no chipset flushing");
-       }
+       if (!intel_private.i9xx_flush_page)
+               dev_err(&intel_private.pcidev->dev,
+                       "can't ioremap flush page - no chipset flushing\n");
 }
 
 static int intel_i9xx_configure(void)
@@ -1088,15 +1176,16 @@ static int intel_i9xx_configure(void)
 
        agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
 
-       pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
+       pci_read_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, &gmch_ctrl);
        gmch_ctrl |= I830_GMCH_ENABLED;
-       pci_write_config_word(agp_bridge->dev, I830_GMCH_CTRL, gmch_ctrl);
+       pci_write_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, gmch_ctrl);
 
        writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
        readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
 
        if (agp_bridge->driver->needs_scratch_page) {
-               for (i = intel_private.gtt_entries; i < intel_private.gtt_total_size; i++) {
+               for (i = intel_private.base.gtt_stolen_entries; i <
+                               intel_private.base.gtt_total_entries; i++) {
                        writel(agp_bridge->scratch_page, intel_private.gtt+i);
                }
                readl(intel_private.gtt+i-1);   /* PCI Posting. */
@@ -1109,7 +1198,7 @@ static int intel_i9xx_configure(void)
        return 0;
 }
 
-static void intel_i915_cleanup(void)
+static void intel_gtt_cleanup(void)
 {
        if (intel_private.i9xx_flush_page)
                iounmap(intel_private.i9xx_flush_page);
@@ -1141,10 +1230,10 @@ static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start,
        temp = agp_bridge->current_size;
        num_entries = A_SIZE_FIX(temp)->num_entries;
 
-       if (pg_start < intel_private.gtt_entries) {
+       if (pg_start < intel_private.base.gtt_stolen_entries) {
                dev_printk(KERN_DEBUG, &intel_private.pcidev->dev,
-                          "pg_start == 0x%.8lx, intel_private.gtt_entries == 0x%.8x\n",
-                          pg_start, intel_private.gtt_entries);
+                          "pg_start == 0x%.8lx, gtt_stolen_entries == 0x%.8x\n",
+                          pg_start, intel_private.base.gtt_stolen_entries);
 
                dev_info(&intel_private.pcidev->dev,
                         "trying to insert into local/stolen memory\n");
@@ -1163,7 +1252,8 @@ static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start,
 
        mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
 
-       if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
+       if (INTEL_GTT_GEN != 6 && mask_type != 0 &&
+           mask_type != AGP_PHYS_MEMORY &&
            mask_type != INTEL_AGP_CACHED_MEMORY)
                goto out_err;
 
@@ -1187,7 +1277,7 @@ static int intel_i915_remove_entries(struct agp_memory *mem, off_t pg_start,
        if (mem->page_count == 0)
                return 0;
 
-       if (pg_start < intel_private.gtt_entries) {
+       if (pg_start < intel_private.base.gtt_stolen_entries) {
                dev_info(&intel_private.pcidev->dev,
                         "trying to disable local/stolen memory\n");
                return -EINVAL;
@@ -1201,73 +1291,15 @@ static int intel_i915_remove_entries(struct agp_memory *mem, off_t pg_start,
        return 0;
 }
 
-/* Return the aperture size by just checking the resource length.  The effect
- * described in the spec of the MSAC registers is just changing of the
- * resource size.
- */
-static int intel_i9xx_fetch_size(void)
-{
-       int num_sizes = ARRAY_SIZE(intel_i830_sizes);
-       int aper_size; /* size in megabytes */
-       int i;
-
-       aper_size = pci_resource_len(intel_private.pcidev, 2) / MB(1);
-
-       for (i = 0; i < num_sizes; i++) {
-               if (aper_size == intel_i830_sizes[i].size) {
-                       agp_bridge->current_size = intel_i830_sizes + i;
-                       return aper_size;
-               }
-       }
-
-       return 0;
-}
-
-static int intel_i915_get_gtt_size(void)
-{
-       int size;
-
-       if (IS_G33) {
-               u16 gmch_ctrl;
-
-               /* G33's GTT size defined in gmch_ctrl */
-               pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
-               switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
-               case I830_GMCH_GMS_STOLEN_512:
-                       size = 512;
-                       break;
-               case I830_GMCH_GMS_STOLEN_1024:
-                       size = 1024;
-                       break;
-               case I830_GMCH_GMS_STOLEN_8192:
-                       size = 8*1024;
-                       break;
-               default:
-                       dev_info(&agp_bridge->dev->dev,
-                                "unknown page table size 0x%x, assuming 512KB\n",
-                               (gmch_ctrl & I830_GMCH_GMS_MASK));
-                       size = 512;
-               }
-       } else {
-               /* On previous hardware, the GTT size was just what was
-                * required to map the aperture.
-                */
-               size = agp_bridge->driver->fetch_size();
-       }
-
-       return KB(size);
-}
-
 /* The intel i915 automatically initializes the agp aperture during POST.
  * Use the memory already set aside for in the GTT.
  */
 static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
 {
-       int page_order;
+       int page_order, ret;
        struct aper_size_info_fixed *size;
        int num_entries;
        u32 temp, temp2;
-       int gtt_map_size;
 
        size = agp_bridge->current_size;
        page_order = size->page_order;
@@ -1277,32 +1309,18 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
        pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp);
        pci_read_config_dword(intel_private.pcidev, I915_PTEADDR, &temp2);
 
-       gtt_map_size = intel_i915_get_gtt_size();
-
-       intel_private.gtt = ioremap(temp2, gtt_map_size);
-       if (!intel_private.gtt)
-               return -ENOMEM;
-
-       intel_private.gtt_total_size = gtt_map_size / 4;
-
        temp &= 0xfff80000;
 
        intel_private.registers = ioremap(temp, 128 * 4096);
-       if (!intel_private.registers) {
-               iounmap(intel_private.gtt);
+       if (!intel_private.registers)
                return -ENOMEM;
-       }
 
+       intel_private.gtt_bus_addr = temp2;
        temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
-       global_cache_flush();   /* FIXME: ? */
 
-       /* we have to call this as early as possible after the MMIO base address is known */
-       intel_i830_init_gtt_entries();
-       if (intel_private.gtt_entries == 0) {
-               iounmap(intel_private.gtt);
-               iounmap(intel_private.registers);
-               return -ENOMEM;
-       }
+       ret = intel_gtt_init();
+       if (ret != 0)
+               return ret;
 
        agp_bridge->gatt_table = NULL;
 
@@ -1333,51 +1351,24 @@ static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge,
 static unsigned long intel_gen6_mask_memory(struct agp_bridge_data *bridge,
                                            dma_addr_t addr, int type)
 {
-       /* Shift high bits down */
-       addr |= (addr >> 28) & 0xff;
+       /* gen6 has bit11-4 for physical addr bit39-32 */
+       addr |= (addr >> 28) & 0xff0;
 
        /* Type checking must be done elsewhere */
        return addr | bridge->driver->masks[type].mask;
 }
 
-static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
+static void intel_i965_get_gtt_range(int *gtt_offset)
 {
-       u16 snb_gmch_ctl;
-
-       switch (agp_bridge->dev->device) {
-       case PCI_DEVICE_ID_INTEL_GM45_HB:
-       case PCI_DEVICE_ID_INTEL_EAGLELAKE_HB:
-       case PCI_DEVICE_ID_INTEL_Q45_HB:
-       case PCI_DEVICE_ID_INTEL_G45_HB:
-       case PCI_DEVICE_ID_INTEL_G41_HB:
-       case PCI_DEVICE_ID_INTEL_B43_HB:
-       case PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB:
-       case PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB:
-       case PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB:
-       case PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB:
-               *gtt_offset = *gtt_size = MB(2);
-               break;
-       case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB:
-       case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB:
+       switch (INTEL_GTT_GEN) {
+       case 5:
+       case 6:
                *gtt_offset = MB(2);
-
-               pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl);
-               switch (snb_gmch_ctl & SNB_GTT_SIZE_MASK) {
-               default:
-               case SNB_GTT_SIZE_0M:
-                       printk(KERN_ERR "Bad GTT size mask: 0x%04x.\n", snb_gmch_ctl);
-                       *gtt_size = MB(0);
-                       break;
-               case SNB_GTT_SIZE_1M:
-                       *gtt_size = MB(1);
-                       break;
-               case SNB_GTT_SIZE_2M:
-                       *gtt_size = MB(2);
-                       break;
-               }
                break;
+       case 4:
        default:
-               *gtt_offset = *gtt_size = KB(512);
+               *gtt_offset =  KB(512);
+               break;
        }
 }
 
@@ -1386,11 +1377,11 @@ static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
  */
 static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
 {
-       int page_order;
+       int page_order, ret;
        struct aper_size_info_fixed *size;
        int num_entries;
        u32 temp;
-       int gtt_offset, gtt_size;
+       int gtt_offset;
 
        size = agp_bridge->current_size;
        page_order = size->page_order;
@@ -1401,31 +1392,17 @@ static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
 
        temp &= 0xfff00000;
 
-       intel_i965_get_gtt_range(&gtt_offset, &gtt_size);
-
-       intel_private.gtt = ioremap((temp + gtt_offset) , gtt_size);
-
-       if (!intel_private.gtt)
-               return -ENOMEM;
-
-       intel_private.gtt_total_size = gtt_size / 4;
-
        intel_private.registers = ioremap(temp, 128 * 4096);
-       if (!intel_private.registers) {
-               iounmap(intel_private.gtt);
+       if (!intel_private.registers) 
                return -ENOMEM;
-       }
 
+       intel_i965_get_gtt_range(&gtt_offset);
+       intel_private.gtt_bus_addr = temp + gtt_offset;
        temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
-       global_cache_flush();   /* FIXME: ? */
 
-       /* we have to call this as early as possible after the MMIO base address is known */
-       intel_i830_init_gtt_entries();
-       if (intel_private.gtt_entries == 0) {
-               iounmap(intel_private.gtt);
-               iounmap(intel_private.registers);
-               return -ENOMEM;
-       }
+       ret = intel_gtt_init();
+       if (ret != 0)
+               return ret;
 
        agp_bridge->gatt_table = NULL;
 
@@ -1445,7 +1422,7 @@ static const struct agp_bridge_driver intel_810_driver = {
        .cleanup                = intel_i810_cleanup,
        .mask_memory            = intel_i810_mask_memory,
        .masks                  = intel_i810_masks,
-       .agp_enable             = intel_i810_agp_enable,
+       .agp_enable             = intel_fake_agp_enable,
        .cache_flush            = global_cache_flush,
        .create_gatt_table      = agp_generic_create_gatt_table,
        .free_gatt_table        = agp_generic_free_gatt_table,
@@ -1462,22 +1439,22 @@ static const struct agp_bridge_driver intel_810_driver = {
 
 static const struct agp_bridge_driver intel_830_driver = {
        .owner                  = THIS_MODULE,
-       .aperture_sizes         = intel_i830_sizes,
+       .aperture_sizes         = intel_fake_agp_sizes,
        .size_type              = FIXED_APER_SIZE,
        .num_aperture_sizes     = 4,
        .needs_scratch_page     = true,
        .configure              = intel_i830_configure,
-       .fetch_size             = intel_i830_fetch_size,
-       .cleanup                = intel_i830_cleanup,
+       .fetch_size             = intel_fake_agp_fetch_size,
+       .cleanup                = intel_gtt_cleanup,
        .mask_memory            = intel_i810_mask_memory,
        .masks                  = intel_i810_masks,
-       .agp_enable             = intel_i810_agp_enable,
+       .agp_enable             = intel_fake_agp_enable,
        .cache_flush            = global_cache_flush,
        .create_gatt_table      = intel_i830_create_gatt_table,
-       .free_gatt_table        = intel_i830_free_gatt_table,
+       .free_gatt_table        = intel_fake_agp_free_gatt_table,
        .insert_memory          = intel_i830_insert_entries,
        .remove_memory          = intel_i830_remove_entries,
-       .alloc_by_type          = intel_i830_alloc_by_type,
+       .alloc_by_type          = intel_fake_agp_alloc_by_type,
        .free_by_type           = intel_i810_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_alloc_pages        = agp_generic_alloc_pages,
@@ -1489,22 +1466,22 @@ static const struct agp_bridge_driver intel_830_driver = {
 
 static const struct agp_bridge_driver intel_915_driver = {
        .owner                  = THIS_MODULE,
-       .aperture_sizes         = intel_i830_sizes,
+       .aperture_sizes         = intel_fake_agp_sizes,
        .size_type              = FIXED_APER_SIZE,
        .num_aperture_sizes     = 4,
        .needs_scratch_page     = true,
        .configure              = intel_i9xx_configure,
-       .fetch_size             = intel_i9xx_fetch_size,
-       .cleanup                = intel_i915_cleanup,
+       .fetch_size             = intel_fake_agp_fetch_size,
+       .cleanup                = intel_gtt_cleanup,
        .mask_memory            = intel_i810_mask_memory,
        .masks                  = intel_i810_masks,
-       .agp_enable             = intel_i810_agp_enable,
+       .agp_enable             = intel_fake_agp_enable,
        .cache_flush            = global_cache_flush,
        .create_gatt_table      = intel_i915_create_gatt_table,
-       .free_gatt_table        = intel_i830_free_gatt_table,
+       .free_gatt_table        = intel_fake_agp_free_gatt_table,
        .insert_memory          = intel_i915_insert_entries,
        .remove_memory          = intel_i915_remove_entries,
-       .alloc_by_type          = intel_i830_alloc_by_type,
+       .alloc_by_type          = intel_fake_agp_alloc_by_type,
        .free_by_type           = intel_i810_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_alloc_pages        = agp_generic_alloc_pages,
@@ -1522,22 +1499,22 @@ static const struct agp_bridge_driver intel_915_driver = {
 
 static const struct agp_bridge_driver intel_i965_driver = {
        .owner                  = THIS_MODULE,
-       .aperture_sizes         = intel_i830_sizes,
+       .aperture_sizes         = intel_fake_agp_sizes,
        .size_type              = FIXED_APER_SIZE,
        .num_aperture_sizes     = 4,
        .needs_scratch_page     = true,
        .configure              = intel_i9xx_configure,
-       .fetch_size             = intel_i9xx_fetch_size,
-       .cleanup                = intel_i915_cleanup,
+       .fetch_size             = intel_fake_agp_fetch_size,
+       .cleanup                = intel_gtt_cleanup,
        .mask_memory            = intel_i965_mask_memory,
        .masks                  = intel_i810_masks,
-       .agp_enable             = intel_i810_agp_enable,
+       .agp_enable             = intel_fake_agp_enable,
        .cache_flush            = global_cache_flush,
        .create_gatt_table      = intel_i965_create_gatt_table,
-       .free_gatt_table        = intel_i830_free_gatt_table,
+       .free_gatt_table        = intel_fake_agp_free_gatt_table,
        .insert_memory          = intel_i915_insert_entries,
        .remove_memory          = intel_i915_remove_entries,
-       .alloc_by_type          = intel_i830_alloc_by_type,
+       .alloc_by_type          = intel_fake_agp_alloc_by_type,
        .free_by_type           = intel_i810_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_alloc_pages        = agp_generic_alloc_pages,
@@ -1555,28 +1532,28 @@ static const struct agp_bridge_driver intel_i965_driver = {
 
 static const struct agp_bridge_driver intel_gen6_driver = {
        .owner                  = THIS_MODULE,
-       .aperture_sizes         = intel_i830_sizes,
+       .aperture_sizes         = intel_fake_agp_sizes,
        .size_type              = FIXED_APER_SIZE,
        .num_aperture_sizes     = 4,
        .needs_scratch_page     = true,
        .configure              = intel_i9xx_configure,
-       .fetch_size             = intel_i9xx_fetch_size,
-       .cleanup                = intel_i915_cleanup,
+       .fetch_size             = intel_fake_agp_fetch_size,
+       .cleanup                = intel_gtt_cleanup,
        .mask_memory            = intel_gen6_mask_memory,
-       .masks                  = intel_i810_masks,
-       .agp_enable             = intel_i810_agp_enable,
+       .masks                  = intel_gen6_masks,
+       .agp_enable             = intel_fake_agp_enable,
        .cache_flush            = global_cache_flush,
        .create_gatt_table      = intel_i965_create_gatt_table,
-       .free_gatt_table        = intel_i830_free_gatt_table,
+       .free_gatt_table        = intel_fake_agp_free_gatt_table,
        .insert_memory          = intel_i915_insert_entries,
        .remove_memory          = intel_i915_remove_entries,
-       .alloc_by_type          = intel_i830_alloc_by_type,
+       .alloc_by_type          = intel_fake_agp_alloc_by_type,
        .free_by_type           = intel_i810_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_alloc_pages        = agp_generic_alloc_pages,
        .agp_destroy_page       = agp_generic_destroy_page,
        .agp_destroy_pages      = agp_generic_destroy_pages,
-       .agp_type_to_mask_type  = intel_i830_type_to_mask_type,
+       .agp_type_to_mask_type  = intel_gen6_type_to_mask_type,
        .chipset_flush          = intel_i915_chipset_flush,
 #ifdef USE_PCI_DMA_API
        .agp_map_page           = intel_agp_map_page,
@@ -1588,22 +1565,22 @@ static const struct agp_bridge_driver intel_gen6_driver = {
 
 static const struct agp_bridge_driver intel_g33_driver = {
        .owner                  = THIS_MODULE,
-       .aperture_sizes         = intel_i830_sizes,
+       .aperture_sizes         = intel_fake_agp_sizes,
        .size_type              = FIXED_APER_SIZE,
        .num_aperture_sizes     = 4,
        .needs_scratch_page     = true,
        .configure              = intel_i9xx_configure,
-       .fetch_size             = intel_i9xx_fetch_size,
-       .cleanup                = intel_i915_cleanup,
+       .fetch_size             = intel_fake_agp_fetch_size,
+       .cleanup                = intel_gtt_cleanup,
        .mask_memory            = intel_i965_mask_memory,
        .masks                  = intel_i810_masks,
-       .agp_enable             = intel_i810_agp_enable,
+       .agp_enable             = intel_fake_agp_enable,
        .cache_flush            = global_cache_flush,
        .create_gatt_table      = intel_i915_create_gatt_table,
-       .free_gatt_table        = intel_i830_free_gatt_table,
+       .free_gatt_table        = intel_fake_agp_free_gatt_table,
        .insert_memory          = intel_i915_insert_entries,
        .remove_memory          = intel_i915_remove_entries,
-       .alloc_by_type          = intel_i830_alloc_by_type,
+       .alloc_by_type          = intel_fake_agp_alloc_by_type,
        .free_by_type           = intel_i810_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_alloc_pages        = agp_generic_alloc_pages,
@@ -1618,3 +1595,201 @@ static const struct agp_bridge_driver intel_g33_driver = {
        .agp_unmap_memory       = intel_agp_unmap_memory,
 #endif
 };
+
+static const struct intel_gtt_driver i8xx_gtt_driver = {
+       .gen = 2,
+       .setup = i830_setup,
+};
+static const struct intel_gtt_driver i915_gtt_driver = {
+       .gen = 3,
+};
+static const struct intel_gtt_driver g33_gtt_driver = {
+       .gen = 3,
+       .is_g33 = 1,
+};
+static const struct intel_gtt_driver pineview_gtt_driver = {
+       .gen = 3,
+       .is_pineview = 1, .is_g33 = 1,
+};
+static const struct intel_gtt_driver i965_gtt_driver = {
+       .gen = 4,
+};
+static const struct intel_gtt_driver g4x_gtt_driver = {
+       .gen = 5,
+};
+static const struct intel_gtt_driver ironlake_gtt_driver = {
+       .gen = 5,
+       .is_ironlake = 1,
+};
+static const struct intel_gtt_driver sandybridge_gtt_driver = {
+       .gen = 6,
+};
+
+/* Table to describe Intel GMCH and AGP/PCIE GART drivers.  At least one of
+ * driver and gmch_driver must be non-null, and find_gmch will determine
+ * which one should be used if a gmch_chip_id is present.
+ */
+static const struct intel_gtt_driver_description {
+       unsigned int gmch_chip_id;
+       char *name;
+       const struct agp_bridge_driver *gmch_driver;
+       const struct intel_gtt_driver *gtt_driver;
+} intel_gtt_chipsets[] = {
+       { PCI_DEVICE_ID_INTEL_82810_IG1, "i810", &intel_810_driver , NULL},
+       { PCI_DEVICE_ID_INTEL_82810_IG3, "i810", &intel_810_driver , NULL},
+       { PCI_DEVICE_ID_INTEL_82810E_IG, "i810", &intel_810_driver , NULL},
+       { PCI_DEVICE_ID_INTEL_82815_CGC, "i815", &intel_810_driver , NULL},
+       { PCI_DEVICE_ID_INTEL_82830_CGC, "830M",
+               &intel_830_driver , &i8xx_gtt_driver},
+       { PCI_DEVICE_ID_INTEL_82845G_IG, "830M",
+               &intel_830_driver , &i8xx_gtt_driver},
+       { PCI_DEVICE_ID_INTEL_82854_IG, "854",
+               &intel_830_driver , &i8xx_gtt_driver},
+       { PCI_DEVICE_ID_INTEL_82855GM_IG, "855GM",
+               &intel_830_driver , &i8xx_gtt_driver},
+       { PCI_DEVICE_ID_INTEL_82865_IG, "865",
+               &intel_830_driver , &i8xx_gtt_driver},
+       { PCI_DEVICE_ID_INTEL_E7221_IG, "E7221 (i915)",
+               &intel_915_driver , &i915_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_82915G_IG, "915G",
+               &intel_915_driver , &i915_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_82915GM_IG, "915GM",
+               &intel_915_driver , &i915_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_82945G_IG, "945G",
+               &intel_915_driver , &i915_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_82945GM_IG, "945GM",
+               &intel_915_driver , &i915_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_82945GME_IG, "945GME",
+               &intel_915_driver , &i915_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_82946GZ_IG, "946GZ",
+               &intel_i965_driver , &i965_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_82G35_IG, "G35",
+               &intel_i965_driver , &i965_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_82965Q_IG, "965Q",
+               &intel_i965_driver , &i965_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_82965G_IG, "965G",
+               &intel_i965_driver , &i965_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_82965GM_IG, "965GM",
+               &intel_i965_driver , &i965_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_82965GME_IG, "965GME/GLE",
+               &intel_i965_driver , &i965_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_G33_IG, "G33",
+               &intel_g33_driver , &g33_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_Q35_IG, "Q35",
+               &intel_g33_driver , &g33_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_Q33_IG, "Q33",
+               &intel_g33_driver , &g33_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, "GMA3150",
+               &intel_g33_driver , &pineview_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_PINEVIEW_IG, "GMA3150",
+               &intel_g33_driver , &pineview_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_GM45_IG, "GM45",
+               &intel_i965_driver , &g4x_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_EAGLELAKE_IG, "Eaglelake",
+               &intel_i965_driver , &g4x_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_Q45_IG, "Q45/Q43",
+               &intel_i965_driver , &g4x_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_G45_IG, "G45/G43",
+               &intel_i965_driver , &g4x_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_B43_IG, "B43",
+               &intel_i965_driver , &g4x_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_G41_IG, "G41",
+               &intel_i965_driver , &g4x_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG,
+           "HD Graphics", &intel_i965_driver , &ironlake_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG,
+           "HD Graphics", &intel_i965_driver , &ironlake_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG,
+           "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG,
+           "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG,
+           "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG,
+           "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG,
+           "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG,
+           "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG,
+           "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver },
+       { 0, NULL, NULL }
+};
+
+static int find_gmch(u16 device)
+{
+       struct pci_dev *gmch_device;
+
+       gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
+       if (gmch_device && PCI_FUNC(gmch_device->devfn) != 0) {
+               gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL,
+                                            device, gmch_device);
+       }
+
+       if (!gmch_device)
+               return 0;
+
+       intel_private.pcidev = gmch_device;
+       return 1;
+}
+
+int intel_gmch_probe(struct pci_dev *pdev,
+                                     struct agp_bridge_data *bridge)
+{
+       int i, mask;
+       bridge->driver = NULL;
+
+       for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) {
+               if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) {
+                       bridge->driver =
+                               intel_gtt_chipsets[i].gmch_driver;
+                       intel_private.driver = 
+                               intel_gtt_chipsets[i].gtt_driver;
+                       break;
+               }
+       }
+
+       if (!bridge->driver)
+               return 0;
+
+       bridge->dev_private_data = &intel_private;
+       bridge->dev = pdev;
+
+       intel_private.bridge_dev = pci_dev_get(pdev);
+
+       dev_info(&pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name);
+
+       if (bridge->driver->mask_memory == intel_gen6_mask_memory)
+               mask = 40;
+       else if (bridge->driver->mask_memory == intel_i965_mask_memory)
+               mask = 36;
+       else
+               mask = 32;
+
+       if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask)))
+               dev_err(&intel_private.pcidev->dev,
+                       "set gfx device dma mask %d-bit failed!\n", mask);
+       else
+               pci_set_consistent_dma_mask(intel_private.pcidev,
+                                           DMA_BIT_MASK(mask));
+
+       if (bridge->driver == &intel_810_driver)
+               return 1;
+
+       intel_private.base.gtt_mappable_entries = intel_gtt_mappable_entries();
+
+       return 1;
+}
+EXPORT_SYMBOL(intel_gmch_probe);
+
+void intel_gmch_remove(struct pci_dev *pdev)
+{
+       if (intel_private.pcidev)
+               pci_dev_put(intel_private.pcidev);
+       if (intel_private.bridge_dev)
+               pci_dev_put(intel_private.bridge_dev);
+}
+EXPORT_SYMBOL(intel_gmch_remove);
+
+MODULE_AUTHOR("Dave Jones <davej@redhat.com>");
+MODULE_LICENSE("GPL and additional rights");