Merge to Fedora kernel-2.6.18-1.2255_FC5-vs2.0.2.2-rc9 patched with stable patch...
[linux-2.6.git] / drivers / char / agp / intel-agp.c
index f9acaa9..7475eae 100644 (file)
@@ -2,14 +2,6 @@
  * Intel AGPGART routines.
  */
 
-/*
- * Intel(R) 855GM/852GM and 865G support added by David Dawes
- * <dawes@tungstengraphics.com>.
- *
- * Intel(R) 915G support added by Alan Hourihane
- * <alanh@tungstengraphics.com>.
- */
-
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/init.h>
@@ -17,6 +9,21 @@
 #include <linux/agp_backend.h>
 #include "agp.h"
 
+#define PCI_DEVICE_ID_INTEL_82946GZ_HB      0x2970
+#define PCI_DEVICE_ID_INTEL_82946GZ_IG      0x2972
+#define PCI_DEVICE_ID_INTEL_82965G_1_HB     0x2980
+#define PCI_DEVICE_ID_INTEL_82965G_1_IG     0x2982
+#define PCI_DEVICE_ID_INTEL_82965Q_HB       0x2990
+#define PCI_DEVICE_ID_INTEL_82965Q_IG       0x2992
+#define PCI_DEVICE_ID_INTEL_82965G_HB       0x29A0
+#define PCI_DEVICE_ID_INTEL_82965G_IG       0x29A2
+
+#define IS_I965 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82946GZ_HB || \
+                 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_1_HB || \
+                 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \
+                 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB)
+
+
 /* Intel 815 register */
 #define INTEL_815_APCONT       0x51
 #define INTEL_815_ATTBASE_MASK ~0x1FFFFFFF
@@ -40,6 +47,8 @@
 #define I915_GMCH_GMS_STOLEN_48M       (0x6 << 4)
 #define I915_GMCH_GMS_STOLEN_64M       (0x7 << 4)
 
+/* Intel 965G registers */
+#define I965_MSAC 0x62
 
 /* Intel 7505 registers */
 #define INTEL_I7505_APSIZE     0x74
@@ -150,7 +159,7 @@ static void intel_i810_tlbflush(struct agp_memory *mem)
        return;
 }
 
-static void intel_i810_agp_enable(u32 mode)
+static void intel_i810_agp_enable(struct agp_bridge_data *bridge, u32 mode)
 {
        return;
 }
@@ -160,7 +169,7 @@ static void *i8xx_alloc_pages(void)
 {
        struct page * page;
 
-       page = alloc_pages(GFP_KERNEL, 2);
+       page = alloc_pages(GFP_KERNEL | GFP_DMA32, 2);
        if (page == NULL)
                return NULL;
 
@@ -201,9 +210,9 @@ static int intel_i810_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 + mem->page_count) > num_entries) {
+       if ((pg_start + mem->page_count) > num_entries)
                return -EINVAL;
-       }
+
        for (j = pg_start; j < (pg_start + mem->page_count); j++) {
                if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j)))
                        return -EBUSY;
@@ -221,7 +230,7 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
                        agp_bridge->driver->tlb_flush(mem);
                        return 0;
                }
-               if((type == AGP_PHYS_MEMORY) && (mem->type == AGP_PHYS_MEMORY))
+               if ((type == AGP_PHYS_MEMORY) && (mem->type == AGP_PHYS_MEMORY))
                        goto insert;
                return -EINVAL;
        }
@@ -229,8 +238,9 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
 insert:
        global_cache_flush();
        for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-               writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type),
-                               intel_i810_private.registers+I810_PTE_BASE+(j*4));
+               writel(agp_bridge->driver->mask_memory(agp_bridge,
+                       mem->memory[i], mem->type),
+                       intel_i810_private.registers+I810_PTE_BASE+(j*4));
                readl(intel_i810_private.registers+I810_PTE_BASE+(j*4));        /* PCI Posting. */
        }
        global_cache_flush();
@@ -268,7 +278,8 @@ static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
                return NULL;
 
        switch (pg_count) {
-       case 1: addr = agp_bridge->driver->agp_alloc_page();
+       case 1: addr = agp_bridge->driver->agp_alloc_page(agp_bridge);
+               global_flush_tlb();
                break;
        case 4:
                /* kludge to get 4 physical pages for ARGB cursor */
@@ -285,7 +296,7 @@ static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
        if (new == NULL)
                return NULL;
 
-       new->memory[0] = virt_to_phys(addr);
+       new->memory[0] = virt_to_gart(addr);
        if (pg_count == 4) {
                /* kludge to get 4 physical pages for ARGB cursor */
                new->memory[1] = new->memory[0] + PAGE_SIZE;
@@ -318,7 +329,7 @@ static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
                return new;
        }
        if (type == AGP_PHYS_MEMORY)
-               return(alloc_agpphysmem_i8xx(pg_count, type));
+               return alloc_agpphysmem_i8xx(pg_count, type);
 
        return NULL;
 }
@@ -326,21 +337,24 @@ static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
 static void intel_i810_free_by_type(struct agp_memory *curr)
 {
        agp_free_key(curr->key);
-       if(curr->type == AGP_PHYS_MEMORY) {
+       if (curr->type == AGP_PHYS_MEMORY) {
                if (curr->page_count == 4)
-                       i8xx_destroy_pages(phys_to_virt(curr->memory[0]));
-               else
+                       i8xx_destroy_pages(gart_to_virt(curr->memory[0]));
+               else {
                        agp_bridge->driver->agp_destroy_page(
-                                phys_to_virt(curr->memory[0]));
+                                gart_to_virt(curr->memory[0]));
+                       global_flush_tlb();
+               }
                vfree(curr->memory);
        }
        kfree(curr);
 }
 
-static unsigned long intel_i810_mask_memory(unsigned long addr, int type)
+static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge,
+       unsigned long addr, int type)
 {
        /* Type checking must be done elsewhere */
-       return addr | agp_bridge->driver->masks[type].mask;
+       return addr | bridge->driver->masks[type].mask;
 }
 
 static struct aper_size_info_fixed intel_i830_sizes[] =
@@ -349,6 +363,7 @@ static struct aper_size_info_fixed intel_i830_sizes[] =
        /* The 64M mode still requires a 128k gatt */
        {64, 16384, 5},
        {256, 65536, 6},
+       {512, 131072, 7},
 };
 
 static struct _intel_i830_private {
@@ -372,7 +387,11 @@ static void intel_i830_init_gtt_entries(void)
        /* We obtain the size of the GTT, which is also stored (for some
         * reason) at the top of stolen memory. Then we add 4KB to that
         * for the video BIOS popup, which is also stored in there. */
-       size = agp_bridge->driver->fetch_size() + 4;
+
+       if (IS_I965)
+               size = 512 + 4;
+       else
+               size = agp_bridge->driver->fetch_size() + 4;
 
        if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
            agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) {
@@ -415,14 +434,20 @@ static void intel_i830_init_gtt_entries(void)
                        break;
                case I915_GMCH_GMS_STOLEN_48M:
                        /* Check it's really I915G */
-                       if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB)
+                       if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
+                           agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
+                           agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
+                           agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || IS_I965 )
                                gtt_entries = MB(48) - KB(size);
                        else
                                gtt_entries = 0;
                        break;
                case I915_GMCH_GMS_STOLEN_64M:
                        /* Check it's really I915G */
-                       if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB)
+                       if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
+                           agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
+                           agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
+                           agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || IS_I965)
                                gtt_entries = MB(64) - KB(size);
                        else
                                gtt_entries = 0;
@@ -445,7 +470,7 @@ static void intel_i830_init_gtt_entries(void)
 /* 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(void)
+static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge)
 {
        int page_order;
        struct aper_size_info_fixed *size;
@@ -462,7 +487,7 @@ static int intel_i830_create_gatt_table(void)
 
        intel_i830_private.registers = ioremap(temp,128 * 4096);
        if (!intel_i830_private.registers)
-               return (-ENOMEM);
+               return -ENOMEM;
 
        temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
        global_cache_flush();   /* FIXME: ?? */
@@ -474,15 +499,15 @@ static int intel_i830_create_gatt_table(void)
 
        agp_bridge->gatt_bus_addr = temp;
 
-       return(0);
+       return 0;
 }
 
 /* Return the gatt table to a sane state. Use the top of stolen
  * memory for the GTT.
  */
-static int intel_i830_free_gatt_table(void)
+static int intel_i830_free_gatt_table(struct agp_bridge_data *bridge)
 {
-       return(0);
+       return 0;
 }
 
 static int intel_i830_fetch_size(void)
@@ -497,7 +522,7 @@ static int intel_i830_fetch_size(void)
                /* 855GM/852GM/865G has 128MB aperture size */
                agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
                agp_bridge->aperture_size_idx = 0;
-               return(values[0].size);
+               return values[0].size;
        }
 
        pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
@@ -505,14 +530,14 @@ static int intel_i830_fetch_size(void)
        if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) {
                agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
                agp_bridge->aperture_size_idx = 0;
-               return(values[0].size);
+               return values[0].size;
        } else {
                agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + 1);
                agp_bridge->aperture_size_idx = 1;
-               return(values[1].size);
+               return values[1].size;
        }
 
-       return(0);
+       return 0;
 }
 
 static int intel_i830_configure(void)
@@ -542,7 +567,7 @@ static int intel_i830_configure(void)
        }
 
        global_cache_flush();
-       return (0);
+       return 0;
 }
 
 static void intel_i830_cleanup(void)
@@ -563,11 +588,11 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
                                pg_start,intel_i830_private.gtt_entries);
 
                printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
-               return (-EINVAL);
+               return -EINVAL;
        }
 
        if ((pg_start + mem->page_count) > num_entries)
-               return (-EINVAL);
+               return -EINVAL;
 
        /* The i830 can't check the GTT for entries since its read only,
         * depend on the caller to make the correct offset decisions.
@@ -575,19 +600,20 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
 
        if ((type != 0 && type != AGP_PHYS_MEMORY) ||
                (mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
-               return (-EINVAL);
+               return -EINVAL;
 
        global_cache_flush();   /* FIXME: Necessary ?*/
 
        for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-               writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type),
-                               intel_i830_private.registers+I810_PTE_BASE+(j*4));
+               writel(agp_bridge->driver->mask_memory(agp_bridge,
+                       mem->memory[i], mem->type),
+                       intel_i830_private.registers+I810_PTE_BASE+(j*4));
                readl(intel_i830_private.registers+I810_PTE_BASE+(j*4));        /* PCI Posting. */
        }
 
        global_cache_flush();
        agp_bridge->driver->tlb_flush(mem);
-       return(0);
+       return 0;
 }
 
 static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
@@ -599,7 +625,7 @@ static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
 
        if (pg_start < intel_i830_private.gtt_entries) {
                printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
-               return (-EINVAL);
+               return -EINVAL;
        }
 
        for (i = pg_start; i < (mem->page_count + pg_start); i++) {
@@ -609,16 +635,16 @@ static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
 
        global_cache_flush();
        agp_bridge->driver->tlb_flush(mem);
-       return (0);
+       return 0;
 }
 
 static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type)
 {
        if (type == AGP_PHYS_MEMORY)
-               return(alloc_agpphysmem_i8xx(pg_count, type));
+               return alloc_agpphysmem_i8xx(pg_count, type);
 
        /* always return NULL for other allocation types for now */
-       return(NULL);
+       return NULL;
 }
 
 static int intel_i915_configure(void)
@@ -649,7 +675,7 @@ static int intel_i915_configure(void)
        }
 
        global_cache_flush();
-       return (0);
+       return 0;
 }
 
 static void intel_i915_cleanup(void)
@@ -672,11 +698,11 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
                                pg_start,intel_i830_private.gtt_entries);
 
                printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
-               return (-EINVAL);
+               return -EINVAL;
        }
 
        if ((pg_start + mem->page_count) > num_entries)
-               return (-EINVAL);
+               return -EINVAL;
 
        /* The i830 can't check the GTT for entries since its read only,
         * depend on the caller to make the correct offset decisions.
@@ -684,18 +710,19 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
 
        if ((type != 0 && type != AGP_PHYS_MEMORY) ||
                (mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
-               return (-EINVAL);
+               return -EINVAL;
 
        global_cache_flush();
 
        for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-               writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), intel_i830_private.gtt+j);
+               writel(agp_bridge->driver->mask_memory(agp_bridge,
+                       mem->memory[i], mem->type), intel_i830_private.gtt+j);
                readl(intel_i830_private.gtt+j);        /* PCI Posting. */
        }
 
        global_cache_flush();
        agp_bridge->driver->tlb_flush(mem);
-       return(0);
+       return 0;
 }
 
 static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
@@ -707,7 +734,7 @@ static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
 
        if (pg_start < intel_i830_private.gtt_entries) {
                printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
-               return (-EINVAL);
+               return -EINVAL;
        }
 
        for (i = pg_start; i < (mem->page_count + pg_start); i++) {
@@ -717,13 +744,13 @@ static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
 
        global_cache_flush();
        agp_bridge->driver->tlb_flush(mem);
-       return (0);
+       return 0;
 }
 
 static int intel_i915_fetch_size(void)
 {
        struct aper_size_info_fixed *values;
-       u32 temp, offset = 0;
+       u32 temp, offset;
 
 #define I915_256MB_ADDRESS_MASK (1<<27)
 
@@ -735,13 +762,13 @@ static int intel_i915_fetch_size(void)
        else
                offset = 2;     /* 256MB aperture */
        agp_bridge->previous_size = agp_bridge->current_size = (void *)(values + offset);
-       return(values[offset].size);
+       return values[offset].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(void)
+static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
 {
        int page_order;
        struct aper_size_info_fixed *size;
@@ -758,13 +785,13 @@ static int intel_i915_create_gatt_table(void)
 
        intel_i830_private.gtt = ioremap(temp2, 256 * 1024);
        if (!intel_i830_private.gtt)
-               return (-ENOMEM);
+               return -ENOMEM;
 
        temp &= 0xfff80000;
 
        intel_i830_private.registers = ioremap(temp,128 * 4096);
        if (!intel_i830_private.registers)
-               return (-ENOMEM);
+               return -ENOMEM;
 
        temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
        global_cache_flush();   /* FIXME: ? */
@@ -776,9 +803,80 @@ static int intel_i915_create_gatt_table(void)
 
        agp_bridge->gatt_bus_addr = temp;
 
-       return(0);
+       return 0;
+}
+static int intel_i965_fetch_size(void)
+{
+       struct aper_size_info_fixed *values;
+       u32 offset = 0;
+       u8 temp;
+
+#define I965_512MB_ADDRESS_MASK (3<<1)
+
+       values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
+
+       pci_read_config_byte(intel_i830_private.i830_dev, I965_MSAC, &temp);
+       temp &= I965_512MB_ADDRESS_MASK;
+       switch (temp) {
+       case 0x00:
+               offset = 0; /* 128MB */
+               break;
+       case 0x06:
+               offset = 3; /* 512MB */
+               break;
+       default:
+       case 0x02:
+               offset = 2; /* 256MB */
+               break;
+       }
+
+       agp_bridge->previous_size = agp_bridge->current_size = (void *)(values + offset);
+
+       return values[offset].size;
+}
+
+/* The intel i965 automatically initializes the agp aperture during POST.
++ * Use the memory already set aside for in the GTT.
++ */
+static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
+{
+       int page_order;
+       struct aper_size_info_fixed *size;
+       int num_entries;
+       u32 temp;
+
+       size = agp_bridge->current_size;
+       page_order = size->page_order;
+       num_entries = size->num_entries;
+       agp_bridge->gatt_table_real = NULL;
+
+       pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADDR, &temp);
+
+       temp &= 0xfff00000;
+       intel_i830_private.gtt = ioremap((temp + (512 * 1024)) , 512 * 1024);
+
+       if (!intel_i830_private.gtt)
+               return -ENOMEM;
+
+
+       intel_i830_private.registers = ioremap(temp,128 * 4096);
+       if (!intel_i830_private.registers)
+               return -ENOMEM;
+
+       temp = readl(intel_i830_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();
+
+       agp_bridge->gatt_table = NULL;
+
+       agp_bridge->gatt_bus_addr = temp;
+
+       return 0;
 }
 
+
 static int intel_fetch_size(void)
 {
        int i;
@@ -1039,9 +1137,15 @@ static int intel_845_configure(void)
        /* aperture size */
        pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
 
-       /* address to map to */
-       pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
-       agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+       if (agp_bridge->apbase_config != 0) {
+               pci_write_config_dword(agp_bridge->dev, AGP_APBASE,
+                                      agp_bridge->apbase_config);
+       } else {
+               /* address to map to */
+               pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
+               agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+               agp_bridge->apbase_config = temp;
+       }
 
        /* attbase - aperture base */
        pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
@@ -1288,7 +1392,7 @@ static struct agp_bridge_driver intel_830_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = intel_i830_sizes,
        .size_type              = FIXED_APER_SIZE,
-       .num_aperture_sizes     = 3,
+       .num_aperture_sizes     = 4,
        .needs_scratch_page     = TRUE,
        .configure              = intel_i830_configure,
        .fetch_size             = intel_i830_fetch_size,
@@ -1450,7 +1554,7 @@ static struct agp_bridge_driver intel_915_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = intel_i830_sizes,
        .size_type              = FIXED_APER_SIZE,
-       .num_aperture_sizes     = 3,
+       .num_aperture_sizes     = 4,
        .needs_scratch_page     = TRUE,
        .configure              = intel_i915_configure,
        .fetch_size             = intel_i915_fetch_size,
@@ -1470,6 +1574,29 @@ static struct agp_bridge_driver intel_915_driver = {
        .agp_destroy_page       = agp_generic_destroy_page,
 };
 
+static struct agp_bridge_driver intel_i965_driver = {
+       .owner                  = THIS_MODULE,
+       .aperture_sizes         = intel_i830_sizes,
+       .size_type              = FIXED_APER_SIZE,
+       .num_aperture_sizes     = 4,
+       .needs_scratch_page     = TRUE,
+       .configure              = intel_i915_configure,
+       .fetch_size             = intel_i965_fetch_size,
+       .cleanup                = intel_i915_cleanup,
+       .tlb_flush              = intel_i810_tlbflush,
+       .mask_memory            = intel_i810_mask_memory,
+       .masks                  = intel_i810_masks,
+       .agp_enable             = intel_i810_agp_enable,
+       .cache_flush            = global_cache_flush,
+       .create_gatt_table      = intel_i965_create_gatt_table,
+       .free_gatt_table        = intel_i830_free_gatt_table,
+       .insert_memory          = intel_i915_insert_entries,
+       .remove_memory          = intel_i915_remove_entries,
+       .alloc_by_type          = intel_i830_alloc_by_type,
+       .free_by_type           = intel_i810_free_by_type,
+       .agp_alloc_page         = agp_generic_alloc_page,
+       .agp_destroy_page       = agp_generic_destroy_page,
+};
 
 static struct agp_bridge_driver intel_7505_driver = {
        .owner                  = THIS_MODULE,
@@ -1498,7 +1625,7 @@ static int find_i810(u16 device)
 {
        struct pci_dev *i810_dev;
 
-       i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, device, NULL);
+       i810_dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
        if (!i810_dev)
                return 0;
        intel_i810_private.i810_dev = i810_dev;
@@ -1509,9 +1636,9 @@ static int find_i830(u16 device)
 {
        struct pci_dev *i830_dev;
 
-       i830_dev = pci_find_device(PCI_VENDOR_ID_INTEL, device, NULL);
+       i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
        if (i830_dev && PCI_FUNC(i830_dev->devfn) != 0) {
-               i830_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
+               i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
                                device, i830_dev);
        }
 
@@ -1584,11 +1711,10 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
                name = "i820";
                break;
        case PCI_DEVICE_ID_INTEL_82830_HB:
-               if (find_i830(PCI_DEVICE_ID_INTEL_82830_CGC)) {
+               if (find_i830(PCI_DEVICE_ID_INTEL_82830_CGC))
                        bridge->driver = &intel_830_driver;
-               } else {
+               else
                        bridge->driver = &intel_830mp_driver;
-               }
                name = "830M";
                break;
        case PCI_DEVICE_ID_INTEL_82840_HB:
@@ -1600,11 +1726,10 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
                name = "i845";
                break;
        case PCI_DEVICE_ID_INTEL_82845G_HB:
-               if (find_i830(PCI_DEVICE_ID_INTEL_82845G_IG)) {
+               if (find_i830(PCI_DEVICE_ID_INTEL_82845G_IG))
                        bridge->driver = &intel_830_driver;
-               } else {
+               else
                        bridge->driver = &intel_845_driver;
-               }
                name = "845G";
                break;
        case PCI_DEVICE_ID_INTEL_82850_HB:
@@ -1629,11 +1754,10 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
                name = "i860";
                break;
        case PCI_DEVICE_ID_INTEL_82865_HB:
-               if (find_i830(PCI_DEVICE_ID_INTEL_82865_IG)) {
+               if (find_i830(PCI_DEVICE_ID_INTEL_82865_IG))
                        bridge->driver = &intel_830_driver;
-               } else {
+               else
                        bridge->driver = &intel_845_driver;
-               }
                name = "865";
                break;
        case PCI_DEVICE_ID_INTEL_82875_HB:
@@ -1641,13 +1765,62 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
                name = "i875";
                break;
        case PCI_DEVICE_ID_INTEL_82915G_HB:
-               if (find_i830(PCI_DEVICE_ID_INTEL_82915G_IG)) {
+               if (find_i830(PCI_DEVICE_ID_INTEL_82915G_IG))
                        bridge->driver = &intel_915_driver;
-               } else {
+               else
                        bridge->driver = &intel_845_driver;
-               }
                name = "915G";
                break;
+       case PCI_DEVICE_ID_INTEL_82915GM_HB:
+               if (find_i830(PCI_DEVICE_ID_INTEL_82915GM_IG))
+                       bridge->driver = &intel_915_driver;
+               else
+                       bridge->driver = &intel_845_driver;
+               name = "915GM";
+               break;
+       case PCI_DEVICE_ID_INTEL_82945G_HB:
+               if (find_i830(PCI_DEVICE_ID_INTEL_82945G_IG))
+                       bridge->driver = &intel_915_driver;
+               else
+                       bridge->driver = &intel_845_driver;
+               name = "945G";
+               break;
+       case PCI_DEVICE_ID_INTEL_82945GM_HB:
+               if (find_i830(PCI_DEVICE_ID_INTEL_82945GM_IG))
+                       bridge->driver = &intel_915_driver;
+               else
+                       bridge->driver = &intel_845_driver;
+               name = "945GM";
+               break;
+       case PCI_DEVICE_ID_INTEL_82946GZ_HB:
+               if (find_i830(PCI_DEVICE_ID_INTEL_82946GZ_IG))
+                       bridge->driver = &intel_i965_driver;
+               else
+                       bridge->driver = &intel_845_driver;
+               name = "946GZ";
+               break;
+       case PCI_DEVICE_ID_INTEL_82965G_1_HB:
+               if (find_i830(PCI_DEVICE_ID_INTEL_82965G_1_IG))
+                       bridge->driver = &intel_i965_driver;
+               else
+                       bridge->driver = &intel_845_driver;
+               name = "965G";
+               break;
+       case PCI_DEVICE_ID_INTEL_82965Q_HB:
+               if (find_i830(PCI_DEVICE_ID_INTEL_82965Q_IG))
+                       bridge->driver = &intel_i965_driver;
+               else
+                       bridge->driver = &intel_845_driver;
+               name = "965Q";
+               break;
+       case PCI_DEVICE_ID_INTEL_82965G_HB:
+               if (find_i830(PCI_DEVICE_ID_INTEL_82965G_IG))
+                       bridge->driver = &intel_i965_driver;
+               else
+                       bridge->driver = &intel_845_driver;
+               name = "965G";
+               break;
+
        case PCI_DEVICE_ID_INTEL_7505_0:
                bridge->driver = &intel_7505_driver;
                name = "E7505";
@@ -1681,7 +1854,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
        */
        r = &pdev->resource[0];
        if (!r->start && r->end) {
-               if(pci_assign_resource(pdev, 0)) {
+               if (pci_assign_resource(pdev, 0)) {
                        printk(KERN_ERR PFX "could not assign resource 0\n");
                        agp_put_bridge(bridge);
                        return -ENODEV;
@@ -1721,26 +1894,42 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev)
        struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
        agp_remove_bridge(bridge);
+
+       if (intel_i810_private.i810_dev)
+               pci_dev_put(intel_i810_private.i810_dev);
+       if (intel_i830_private.i830_dev)
+               pci_dev_put(intel_i830_private.i830_dev);
+
        agp_put_bridge(bridge);
 }
 
+#ifdef CONFIG_PM
 static int agp_intel_resume(struct pci_dev *pdev)
 {
        struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
-       pci_restore_state(pdev, pdev->saved_config_space);
+       pci_restore_state(pdev);
 
        if (bridge->driver == &intel_generic_driver)
                intel_configure();
+       else if (bridge->driver == &intel_850_driver)
+               intel_850_configure();
        else if (bridge->driver == &intel_845_driver)
                intel_845_configure();
        else if (bridge->driver == &intel_830mp_driver)
                intel_830mp_configure();
        else if (bridge->driver == &intel_915_driver)
                intel_i915_configure();
+       else if (bridge->driver == &intel_830_driver)
+               intel_i830_configure();
+       else if (bridge->driver == &intel_810_driver)
+               intel_i810_configure();
+       else if (bridge->driver == &intel_i965_driver)
+               intel_i915_configure();
 
        return 0;
 }
+#endif
 
 static struct pci_device_id agp_intel_pci_table[] = {
 #define ID(x)                                          \
@@ -1774,6 +1963,13 @@ static struct pci_device_id agp_intel_pci_table[] = {
        ID(PCI_DEVICE_ID_INTEL_7505_0),
        ID(PCI_DEVICE_ID_INTEL_7205_0),
        ID(PCI_DEVICE_ID_INTEL_82915G_HB),
+       ID(PCI_DEVICE_ID_INTEL_82915GM_HB),
+       ID(PCI_DEVICE_ID_INTEL_82945G_HB),
+       ID(PCI_DEVICE_ID_INTEL_82945GM_HB),
+       ID(PCI_DEVICE_ID_INTEL_82946GZ_HB),
+       ID(PCI_DEVICE_ID_INTEL_82965G_1_HB),
+       ID(PCI_DEVICE_ID_INTEL_82965Q_HB),
+       ID(PCI_DEVICE_ID_INTEL_82965G_HB),
        { }
 };
 
@@ -1784,20 +1980,16 @@ static struct pci_driver agp_intel_pci_driver = {
        .id_table       = agp_intel_pci_table,
        .probe          = agp_intel_probe,
        .remove         = __devexit_p(agp_intel_remove),
+#ifdef CONFIG_PM
        .resume         = agp_intel_resume,
+#endif
 };
 
-/* intel_agp_init() must not be declared static for explicit
-   early initialization to work (ie i810fb) */
-int __init agp_intel_init(void)
+static int __init agp_intel_init(void)
 {
-       static int agp_initialised=0;
-
-       if (agp_initialised == 1)
-               return 0;
-       agp_initialised=1;
-
-       return pci_module_init(&agp_intel_pci_driver);
+       if (agp_off)
+               return -EINVAL;
+       return pci_register_driver(&agp_intel_pci_driver);
 }
 
 static void __exit agp_intel_cleanup(void)