bk://linux-dj.bkbits.net/agpgart
davej@redhat.com|ChangeSet|20040319203046|33001 davej

diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	Sun Mar 21 00:24:09 2004
+++ b/MAINTAINERS	Sun Mar 21 00:24:09 2004
@@ -201,7 +201,7 @@
 AGPGART DRIVER
 P:	Dave Jones
 M:	davej@codemonkey.org.uk
-W:	http://www.codemonkey.org.uk/agp/
+W:	http://www.codemonkey.org.uk/projects/agp/
 S:	Maintained
 
 AHA152X SCSI DRIVER
diff -Nru a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
--- a/drivers/char/agp/Kconfig	Sun Mar 21 00:24:09 2004
+++ b/drivers/char/agp/Kconfig	Sun Mar 21 00:24:09 2004
@@ -75,9 +75,20 @@
 	  You should say Y here if you use XFree86 3.3.6 or 4.x and want to
 	  use GLX or DRI.  If unsure, say Y
 
+config AGP_IA32E
+	tristate "Intel IA32E chipset support"
+	depends on AGP && X86
+	help
+	  This option gives you AGP support for the GLX component of XFree86 4.x
+	  on Intel chipsets that support the IA32E processor.
+
+	  You should say Y here if you use XFree86 3.3.6 or 4.x and want to
+	  use GLX or DRI, or if you have any Intel integrated graphics
+	  chipsets.  If unsure, say Y.
+
 config AGP_INTEL
 	tristate "Intel 440LX/BX/GX, I8xx and E7x05 chipset support"
-	depends on AGP && X86
+	depends on AGP && X86 && !X86_64
 	help
 	  This option gives you AGP support for the GLX component of XFree86 4.x
 	  on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, 860, 875,
diff -Nru a/drivers/char/agp/Makefile b/drivers/char/agp/Makefile
--- a/drivers/char/agp/Makefile	Sun Mar 21 00:24:09 2004
+++ b/drivers/char/agp/Makefile	Sun Mar 21 00:24:09 2004
@@ -9,6 +9,7 @@
 obj-$(CONFIG_AGP_EFFICEON)	+= efficeon-agp.o
 obj-$(CONFIG_AGP_HP_ZX1)	+= hp-agp.o
 obj-$(CONFIG_AGP_I460)		+= i460-agp.o
+obj-$(CONFIG_AGP_IA32E)		+= ia32e-agp.o
 obj-$(CONFIG_AGP_INTEL)		+= intel-agp.o
 obj-$(CONFIG_AGP_NVIDIA)	+= nvidia-agp.o
 obj-$(CONFIG_AGP_SIS)		+= sis-agp.o
diff -Nru a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
--- a/drivers/char/agp/agp.h	Sun Mar 21 00:24:09 2004
+++ b/drivers/char/agp/agp.h	Sun Mar 21 00:24:09 2004
@@ -1,6 +1,6 @@
 /*
  * AGPGART
- * Copyright (C) 2002-2003 Dave Jones
+ * Copyright (C) 2002-2004 Dave Jones
  * Copyright (C) 1999 Jeff Hartmann
  * Copyright (C) 1999 Precision Insight, Inc.
  * Copyright (C) 1999 Xi Graphics, Inc.
@@ -167,8 +167,6 @@
 
 #define PGE_EMPTY(b, p)	(!(p) || (p) == (unsigned long) (b)->scratch_page)
 
-/* Chipset independant registers (from AGP Spec) */
-#define AGP_APBASE	0x10
 
 /* Intel registers */
 #define INTEL_APSIZE	0xb4
@@ -177,14 +175,6 @@
 #define INTEL_NBXCFG	0x50
 #define INTEL_ERRSTS	0x91
 
-/* Intel 460GX Registers */
-#define INTEL_I460_BAPBASE		0x98
-#define INTEL_I460_GXBCTL		0xa0
-#define INTEL_I460_AGPSIZ		0xa2
-#define INTEL_I460_ATTBASE		0xfe200000
-#define INTEL_I460_GATT_VALID		(1UL << 24)
-#define INTEL_I460_GATT_COHERENT	(1UL << 25)
-
 /* Intel i830 registers */
 #define I830_GMCH_CTRL			0x52
 #define I830_GMCH_ENABLED		0x4
@@ -219,26 +209,10 @@
 #define I852_GME			0x2
 #define I852_GM				0x5
 
-/* Intel 815 register */
-#define INTEL_815_APCONT	0x51
-#define INTEL_815_ATTBASE_MASK	~0x1FFFFFFF
-
-/* Intel i820 registers */
-#define INTEL_I820_RDCR		0x51
-#define INTEL_I820_ERRSTS	0xc8
-
-/* Intel i840 registers */
-#define INTEL_I840_MCHCFG	0x50
-#define INTEL_I840_ERRSTS	0xc8
- 
 /* Intel i845 registers */
 #define INTEL_I845_AGPM		0x51
 #define INTEL_I845_ERRSTS	0xc8
 
-/* Intel i850 registers */
-#define INTEL_I850_MCHCFG	0x50
-#define INTEL_I850_ERRSTS	0xc8
-
 /* Intel i860 registers */
 #define INTEL_I860_MCHCFG	0x50
 #define INTEL_I860_ERRSTS	0xc8
@@ -261,110 +235,6 @@
 #define I810_DRAM_ROW_0		0x00000001
 #define I810_DRAM_ROW_0_SDRAM	0x00000001
 
-/* Intel 7505 registers */
-#define INTEL_I7505_APSIZE	0x74
-#define INTEL_I7505_NCAPID	0x60
-#define INTEL_I7505_NISTAT	0x6c
-#define INTEL_I7505_ATTBASE	0x78
-#define INTEL_I7505_ERRSTS	0x42
-#define INTEL_I7505_AGPCTRL	0x70
-#define INTEL_I7505_MCHCFG	0x50
-
-/* VIA register */
-#define VIA_GARTCTRL	0x80
-#define VIA_APSIZE	0x84
-#define VIA_ATTBASE	0x88
-
-/* VIA KT400 */
-#define VIA_AGP3_GARTCTRL	0x90
-#define VIA_AGP3_APSIZE		0x94
-#define VIA_AGP3_ATTBASE	0x98
-#define VIA_AGPSEL		0xfd
-
-/* SiS registers */
-#define SIS_ATTBASE	0x90
-#define SIS_APSIZE	0x94
-#define SIS_TLBCNTRL	0x97
-#define SIS_TLBFLUSH	0x98
-
-/* AMD registers */
-#define AMD_MMBASE	0x14
-#define AMD_APSIZE	0xac
-#define AMD_MODECNTL	0xb0
-#define AMD_MODECNTL2	0xb2
-#define AMD_GARTENABLE	0x02	/* In mmio region (16-bit register) */
-#define AMD_ATTBASE	0x04	/* In mmio region (32-bit register) */
-#define AMD_TLBFLUSH	0x0c	/* In mmio region (32-bit register) */
-#define AMD_CACHEENTRY	0x10	/* In mmio region (32-bit register) */
-
-/* AMD64 registers */
-#define AMD64_GARTAPERTURECTL	0x90
-#define AMD64_GARTAPERTUREBASE	0x94
-#define AMD64_GARTTABLEBASE	0x98
-#define AMD64_GARTCACHECTL		0x9c
-#define AMD64_GARTEN		(1<<0)
-
-/* ALi registers */
-#define ALI_AGPCTRL			0xb8
-#define ALI_ATTBASE			0xbc
-#define ALI_TLBCTRL			0xc0
-#define ALI_TAGCTRL			0xc4
-#define ALI_CACHE_FLUSH_CTRL		0xD0
-#define ALI_CACHE_FLUSH_ADDR_MASK	0xFFFFF000
-#define ALI_CACHE_FLUSH_EN		0x100
-
-/* ATI register */
-#define ATI_GART_MMBASE_ADDR	0x14
-#define ATI_RS100_APSIZE	0xac
-#define ATI_RS300_APSIZE	0xf8
-#define ATI_RS100_IG_AGPMODE	0xb0
-#define ATI_RS300_IG_AGPMODE	0xfc
-
-#define ATI_GART_FEATURE_ID		0x00
-#define ATI_GART_BASE			0x04
-#define ATI_GART_CACHE_SZBASE		0x08
-#define ATI_GART_CACHE_CNTRL		0x0c
-#define ATI_GART_CACHE_ENTRY_CNTRL	0x10
-
-/* Serverworks Registers */
-#define SVWRKS_APSIZE		0x10
-#define SVWRKS_SIZE_MASK	0xfe000000
-
-#define SVWRKS_MMBASE		0x14
-#define SVWRKS_CACHING		0x4b
-#define SVWRKS_FEATURE		0x68
-
-/* func 1 registers */
-#define SVWRKS_AGP_ENABLE	0x60
-#define SVWRKS_COMMAND		0x04
-
-/* Memory mapped registers */
-#define SVWRKS_GART_CACHE	0x02
-#define SVWRKS_GATTBASE		0x04
-#define SVWRKS_TLBFLUSH		0x10
-#define SVWRKS_POSTFLUSH	0x14
-#define SVWRKS_DIRFLUSH		0x0c
-
-/* HP ZX1 SBA registers */
-#define HP_ZX1_CTRL		0x200
-#define HP_ZX1_IBASE		0x300
-#define HP_ZX1_IMASK		0x308
-#define HP_ZX1_PCOM		0x310
-#define HP_ZX1_TCNFG		0x318
-#define HP_ZX1_PDIR_BASE	0x320
-#define HP_ZX1_CACHE_FLUSH	0x428
-
-/* NVIDIA registers */
-#define NVIDIA_0_APSIZE		0x80
-#define NVIDIA_1_WBC		0xf0
-#define NVIDIA_2_GARTCTRL	0xd0
-#define NVIDIA_2_APBASE		0xd8
-#define NVIDIA_2_APLIMIT	0xdc
-#define NVIDIA_2_ATTBASE(i)	(0xe0 + (i) * 4)
-#define NVIDIA_3_APBASE		0x50
-#define NVIDIA_3_APLIMIT	0x54
-
-
 struct agp_device_ids {
 	unsigned short device_id; /* first, to make table easier to read */
 	enum chipset_type chipset;
@@ -402,21 +272,38 @@
 void get_agp_version(struct agp_bridge_data *bridge);
 unsigned long agp_generic_mask_memory(unsigned long addr, int type);
 
+/* generic routines for agp>=3 */
+int agp3_generic_fetch_size(void);
+void agp3_generic_tlbflush(struct agp_memory *mem);
+int agp3_generic_configure(void);
+void agp3_generic_cleanup(void);
+
+/* aperture sizes have been standardised since v3 */
+#define AGP_GENERIC_SIZES_ENTRIES 11
+extern struct aper_size_info_16 agp3_generic_sizes[];
+
+
 extern int agp_off;
 extern int agp_try_unsupported_boot;
 
-/* Standard agp registers */
-#define AGPSTAT			0x4
-#define AGPCMD			0x8
-#define AGPNISTAT		0xc
-#define AGPCTRL                 0x10
-#define AGPNEPG			0x16
-#define AGPNICMD		0x20
+/* Chipset independant registers (from AGP Spec) */
+#define AGP_APBASE	0x10
+
+#define AGPSTAT		0x4
+#define AGPCMD		0x8
+#define AGPNISTAT	0xc
+#define AGPCTRL		0x10
+#define AGPAPSIZE	0x14
+#define AGPNEPG		0x16
+#define AGPGARTLO	0x18
+#define AGPGARTHI	0x1c
+#define AGPNICMD	0x20
 
 #define AGP_MAJOR_VERSION_SHIFT	(20)
 #define AGP_MINOR_VERSION_SHIFT	(16)
 
 #define AGPSTAT_RQ_DEPTH	(0xff000000)
+#define AGPSTAT_RQ_DEPTH_SHIFT	24
 
 #define AGPSTAT_CAL_MASK	(1<<12|1<<11|1<<10)
 #define AGPSTAT_ARQSZ		(1<<15|1<<14|1<<13)
@@ -435,4 +322,7 @@
 #define AGPSTAT3_8X		(1<<1)
 #define AGPSTAT3_4X		(1)
 
-#endif				/* _AGP_BACKEND_PRIV_H */
+#define AGPCTRL_APERENB		(1<<8)
+#define AGPCTRL_GTLBEN		(1<<7)
+
+#endif	/* _AGP_BACKEND_PRIV_H */
diff -Nru a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
--- a/drivers/char/agp/ali-agp.c	Sun Mar 21 00:24:09 2004
+++ b/drivers/char/agp/ali-agp.c	Sun Mar 21 00:24:09 2004
@@ -9,6 +9,14 @@
 #include <linux/agp_backend.h>
 #include "agp.h"
 
+#define ALI_AGPCTRL	0xb8
+#define ALI_ATTBASE	0xbc
+#define ALI_TLBCTRL	0xc0
+#define ALI_TAGCTRL	0xc4
+#define ALI_CACHE_FLUSH_CTRL	0xD0
+#define ALI_CACHE_FLUSH_ADDR_MASK	0xFFFFF000
+#define ALI_CACHE_FLUSH_EN	0x100
+
 static int ali_fetch_size(void)
 {
 	int i;
diff -Nru a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
--- a/drivers/char/agp/amd-k7-agp.c	Sun Mar 21 00:24:09 2004
+++ b/drivers/char/agp/amd-k7-agp.c	Sun Mar 21 00:24:09 2004
@@ -11,6 +11,15 @@
 #include <linux/mm.h>
 #include "agp.h"
 
+#define AMD_MMBASE	0x14
+#define AMD_APSIZE	0xac
+#define AMD_MODECNTL	0xb0
+#define AMD_MODECNTL2	0xb2
+#define AMD_GARTENABLE	0x02	/* In mmio region (16-bit register) */
+#define AMD_ATTBASE	0x04	/* In mmio region (32-bit register) */
+#define AMD_TLBFLUSH	0x0c	/* In mmio region (32-bit register) */
+#define AMD_CACHEENTRY	0x10	/* In mmio region (32-bit register) */
+
 struct amd_page_map {
 	unsigned long *real;
 	unsigned long *remapped;
diff -Nru a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
--- a/drivers/char/agp/amd64-agp.c	Sun Mar 21 00:24:09 2004
+++ b/drivers/char/agp/amd64-agp.c	Sun Mar 21 00:24:09 2004
@@ -31,6 +31,13 @@
 #define INVGART		(1<<0)
 #define GARTPTEERR	(1<<1)
 
+/* K8 On-cpu GART registers */
+#define AMD64_GARTAPERTURECTL	0x90
+#define AMD64_GARTAPERTUREBASE	0x94
+#define AMD64_GARTTABLEBASE	0x98
+#define AMD64_GARTCACHECTL	0x9c
+#define AMD64_GARTEN		(1<<0)
+
 /* NVIDIA K8 registers */
 #define NVIDIA_X86_64_0_APBASE		0x10
 #define NVIDIA_X86_64_1_APBASE1		0x50
@@ -382,8 +389,9 @@
 	case 0x11: revstring="B0"; break;
 	case 0x12: revstring="B1"; break;
 	case 0x13: revstring="B2"; break;
+	case 0x14: revstring="B3"; break;
 	default:   revstring="??"; break;
-		}
+	}
 
 	printk (KERN_INFO PFX "Detected AMD 8151 AGP Bridge rev %s\n", revstring);
 
diff -Nru a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
--- a/drivers/char/agp/ati-agp.c	Sun Mar 21 00:24:09 2004
+++ b/drivers/char/agp/ati-agp.c	Sun Mar 21 00:24:09 2004
@@ -10,6 +10,18 @@
 #include <asm/agp.h>
 #include "agp.h"
 
+#define ATI_GART_MMBASE_ADDR	0x14
+#define ATI_RS100_APSIZE	0xac
+#define ATI_RS100_IG_AGPMODE	0xb0
+#define ATI_RS300_APSIZE	0xf8
+#define ATI_RS300_IG_AGPMODE	0xfc
+#define ATI_GART_FEATURE_ID		0x00
+#define ATI_GART_BASE			0x04
+#define ATI_GART_CACHE_SZBASE		0x08
+#define ATI_GART_CACHE_CNTRL		0x0c
+#define ATI_GART_CACHE_ENTRY_CNTRL	0x10
+
+
 static struct aper_size_info_lvl2 ati_generic_sizes[7] =
 {
 	{2048, 524288, 0x0000000c},
diff -Nru a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
--- a/drivers/char/agp/generic.c	Sun Mar 21 00:24:09 2004
+++ b/drivers/char/agp/generic.c	Sun Mar 21 00:24:09 2004
@@ -956,3 +956,85 @@
 }
 EXPORT_SYMBOL(agp_generic_mask_memory);
 
+/*
+ * These functions are implemented according to the AGPv3 spec,
+ * which covers implementation details that had previously been
+ * left open.
+ */
+
+int agp3_generic_fetch_size(void)
+{
+	u16 temp_size;
+	int i;
+	struct aper_size_info_16 *values;
+
+	pci_read_config_word(agp_bridge->dev, agp_bridge->capndx+AGPAPSIZE, &temp_size);
+	values = A_SIZE_16(agp_bridge->driver->aperture_sizes);
+
+	for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
+		if (temp_size == values[i].size_value) {
+			agp_bridge->previous_size =
+				agp_bridge->current_size = (void *) (values + i);
+
+			agp_bridge->aperture_size_idx = i;
+			return values[i].size;
+		}
+	}
+	return 0;
+}
+EXPORT_SYMBOL(agp3_generic_fetch_size);
+
+void agp3_generic_tlbflush(struct agp_memory *mem)
+{
+	u32 ctrl;
+	pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, &ctrl);
+	pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, ctrl & ~AGPCTRL_GTLBEN);
+	pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, ctrl);
+}
+EXPORT_SYMBOL(agp3_generic_tlbflush);
+
+int agp3_generic_configure(void)
+{
+	u32 temp;
+	struct aper_size_info_16 *current_size;
+
+	current_size = A_SIZE_16(agp_bridge->current_size);
+
+	pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
+	agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+
+	// set aperture size
+	pci_write_config_word(agp_bridge->dev, agp_bridge->capndx+AGPAPSIZE, current_size->size_value);
+    // set gart pointer
+	pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPGARTLO, agp_bridge->gatt_bus_addr);
+	// enable aperture and GTLB
+	pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, &temp);
+	pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, temp | AGPCTRL_APERENB | AGPCTRL_GTLBEN);
+	return 0;
+}
+EXPORT_SYMBOL(agp3_generic_configure);
+
+void agp3_generic_cleanup(void)
+{
+	u32 ctrl;
+	pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, &ctrl);
+	pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, ctrl & ~AGPCTRL_APERENB);
+}
+EXPORT_SYMBOL(agp3_generic_cleanup);
+
+struct aper_size_info_16 agp3_generic_sizes[AGP_GENERIC_SIZES_ENTRIES] =
+{
+	{4096, 1048576, 10,0x000},
+	{2048,  524288, 9, 0x800},
+	{1024,  262144, 8, 0xc00},
+	{ 512,  131072, 7, 0xe00},
+	{ 256,   65536, 6, 0xf00},
+	{ 128,   32768, 5, 0xf20},
+	{  64,   16384, 4, 0xf30},
+	{  32,    8192, 3, 0xf38},
+	{  16,    4096, 2, 0xf3c},
+	{   8,    2048, 1, 0xf3e},
+	{   4,    1024, 0, 0xf3f}
+};
+EXPORT_SYMBOL(agp3_generic_sizes);
+
diff -Nru a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
--- a/drivers/char/agp/i460-agp.c	Sun Mar 21 00:24:09 2004
+++ b/drivers/char/agp/i460-agp.c	Sun Mar 21 00:24:09 2004
@@ -14,6 +14,13 @@
 
 #include "agp.h"
 
+#define INTEL_I460_BAPBASE		0x98
+#define INTEL_I460_GXBCTL		0xa0
+#define INTEL_I460_AGPSIZ		0xa2
+#define INTEL_I460_ATTBASE		0xfe200000
+#define INTEL_I460_GATT_VALID		(1UL << 24)
+#define INTEL_I460_GATT_COHERENT	(1UL << 25)
+
 /*
  * The i460 can operate with large (4MB) pages, but there is no sane way to support this
  * within the current kernel/DRM environment, so we disable the relevant code for now.
diff -Nru a/drivers/char/agp/ia32e-agp.c b/drivers/char/agp/ia32e-agp.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/char/agp/ia32e-agp.c	Sun Mar 21 00:24:09 2004
@@ -0,0 +1,683 @@
+/*
+ * Intel ia32e AGPGART routines.
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/agp_backend.h>
+#include "agp.h"
+
+
+#define AGP_DCACHE_MEMORY	1
+#define AGP_PHYS_MEMORY		2
+
+static struct gatt_mask intel_i810_masks[] =
+{
+	{.mask = I810_PTE_VALID, .type = 0},
+	{.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY},
+	{.mask = I810_PTE_VALID, .type = 0}
+};
+
+static void intel_i810_tlbflush(struct agp_memory *mem)
+{
+	return;
+}
+
+static void intel_i810_agp_enable(u32 mode)
+{
+	return;
+}
+
+
+/*
+ * The i810/i830 requires a physical address to program its mouse
+ * pointer into hardware.
+ * However the Xserver still writes to it through the agp aperture.
+ */
+static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
+{
+	struct agp_memory *new;
+	void *addr;
+
+	if (pg_count != 1)
+		return NULL;
+
+	addr = agp_bridge->driver->agp_alloc_page();
+	if (addr == NULL)
+		return NULL;
+
+	new = agp_create_memory(1);
+	if (new == NULL)
+		return NULL;
+
+	new->memory[0] = agp_bridge->driver->mask_memory(virt_to_phys(addr), type);
+	new->page_count = 1;
+	new->num_scratch_pages = 1;
+	new->type = AGP_PHYS_MEMORY;
+	new->physical = new->memory[0];
+	return new;
+}
+
+static void intel_i810_free_by_type(struct agp_memory *curr)
+{
+	agp_free_key(curr->key);
+	if(curr->type == AGP_PHYS_MEMORY) {
+		agp_bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[0]));
+		vfree(curr->memory);
+	}
+	kfree(curr);
+}
+
+static unsigned long intel_i810_mask_memory(unsigned long addr, int type)
+{
+	/* Type checking must be done elsewhere */
+	return addr | agp_bridge->driver->masks[type].mask;
+}
+
+static struct aper_size_info_fixed intel_i830_sizes[] =
+{
+	{128, 32768, 5},
+	/* The 64M mode still requires a 128k gatt */
+	{64, 16384, 5}
+};
+
+static struct _intel_i830_private {
+	struct pci_dev *i830_dev;		/* device one */
+	volatile u8 *registers;
+	int gtt_entries;
+} intel_i830_private;
+
+static void intel_i830_init_gtt_entries(void)
+{
+	u16 gmch_ctrl;
+	int gtt_entries;
+	u8 rdct;
+	int local = 0;
+	static const int ddt[4] = { 0, 16, 32, 64 };
+
+	pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
+
+	if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
+	    agp_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(132);
+			break;
+		case I830_GMCH_GMS_STOLEN_1024:
+			gtt_entries = MB(1) - KB(132);
+			break;
+		case I830_GMCH_GMS_STOLEN_8192:
+			gtt_entries = MB(8) - KB(132);
+			break;
+		case I830_GMCH_GMS_LOCAL:
+			rdct = INREG8(intel_i830_private.registers,
+				      I830_RDRAM_CHANNEL_TYPE);
+			gtt_entries = (I830_RDRAM_ND(rdct) + 1) *
+					MB(ddt[I830_RDRAM_DDT(rdct)]);
+			local = 1;
+			break;
+		default:
+			gtt_entries = 0;
+			break;
+		}
+	} else {
+		switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
+		case I855_GMCH_GMS_STOLEN_1M:
+			gtt_entries = MB(1) - KB(132);
+			break;
+		case I855_GMCH_GMS_STOLEN_4M:
+			gtt_entries = MB(4) - KB(132);
+			break;
+		case I855_GMCH_GMS_STOLEN_8M:
+			gtt_entries = MB(8) - KB(132);
+			break;
+		case I855_GMCH_GMS_STOLEN_16M:
+			gtt_entries = MB(16) - KB(132);
+			break;
+		case I855_GMCH_GMS_STOLEN_32M:
+			gtt_entries = MB(32) - KB(132);
+			break;
+		default:
+			gtt_entries = 0;
+			break;
+		}
+	}
+	if (gtt_entries > 0)
+		printk(KERN_INFO PFX "Detected %dK %s memory.\n",
+		       gtt_entries / KB(1), local ? "local" : "stolen");
+	else
+		printk(KERN_INFO PFX
+		       "No pre-allocated video memory detected.\n");
+	gtt_entries /= KB(4);
+
+	intel_i830_private.gtt_entries = gtt_entries;
+}
+
+/* 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)
+{
+	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 = 0;
+
+	pci_read_config_dword(intel_i830_private.i830_dev,I810_MMADDR,&temp);
+	temp &= 0xfff80000;
+
+	intel_i830_private.registers = (volatile u8 *) ioremap(temp,128 * 4096);
+	if (!intel_i830_private.registers)
+		return (-ENOMEM);
+
+	temp = INREG32(intel_i830_private.registers,I810_PGETBL_CTL) & 0xfffff000;
+	global_cache_flush();
+
+	/* 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);
+}
+
+/* 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)
+{
+	return(0);
+}
+
+static int intel_i830_fetch_size(void)
+{
+	u16 gmch_ctrl;
+	struct aper_size_info_fixed *values;
+
+	values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
+
+	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->previous_size = agp_bridge->current_size = (void *) values;
+		agp_bridge->aperture_size_idx = 0;
+		return(values[0].size);
+	}
+
+	pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
+
+	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);
+	} else {
+		agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
+		agp_bridge->aperture_size_idx = 1;
+		return(values[1].size);
+	}
+
+	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_i830_private.i830_dev,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);
+
+	OUTREG32(intel_i830_private.registers,I810_PGETBL_CTL,agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED);
+	global_cache_flush();
+
+	if (agp_bridge->driver->needs_scratch_page)
+		for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++)
+			OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (i * 4),agp_bridge->scratch_page);
+
+	return (0);
+}
+
+static void intel_i830_cleanup(void)
+{
+	iounmap((void *) intel_i830_private.registers);
+}
+
+static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start,
+				int type)
+{
+	int i,j,num_entries;
+	void *temp;
+
+	temp = agp_bridge->current_size;
+	num_entries = A_SIZE_FIX(temp)->num_entries;
+
+	if (pg_start < intel_i830_private.gtt_entries) {
+		printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n",
+				pg_start,intel_i830_private.gtt_entries);
+
+		printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
+		return (-EINVAL);
+	}
+
+	if ((pg_start + mem->page_count) > num_entries)
+		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.
+	 */
+
+	if ((type != 0 && type != AGP_PHYS_MEMORY) ||
+		(mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
+		return (-EINVAL);
+
+	global_cache_flush();
+
+	for (i = 0, j = pg_start; i < mem->page_count; i++, j++)
+		OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (j * 4),
+			agp_bridge->driver->mask_memory(mem->memory[i], mem->type));
+
+	global_cache_flush();
+
+	agp_bridge->driver->tlb_flush(mem);
+
+	return(0);
+}
+
+static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
+				int type)
+{
+	int i;
+
+	global_cache_flush();
+
+	if (pg_start < intel_i830_private.gtt_entries) {
+		printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
+		return (-EINVAL);
+	}
+
+	for (i = pg_start; i < (mem->page_count + pg_start); i++)
+		OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (i * 4),agp_bridge->scratch_page);
+
+	global_cache_flush();
+
+	agp_bridge->driver->tlb_flush(mem);
+
+	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));
+
+	/* always return NULL for other allocation types for now */
+	return(NULL);
+}
+
+static int intel_8xx_fetch_size(void)
+{
+	u8 temp;
+	int i;
+	struct aper_size_info_8 *values;
+
+	pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp);
+
+	values = A_SIZE_8(agp_bridge->driver->aperture_sizes);
+
+	for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
+		if (temp == values[i].size_value) {
+			agp_bridge->previous_size =
+				agp_bridge->current_size = (void *) (values + i);
+			agp_bridge->aperture_size_idx = i;
+			return values[i].size;
+		}
+	}
+	return 0;
+}
+
+static void intel_8xx_tlbflush(struct agp_memory *mem)
+{
+	u32 temp;
+	pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp);
+	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp & ~(1 << 7));
+	pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp);
+	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp | (1 << 7));
+}
+
+static void intel_8xx_cleanup(void)
+{
+	u16 temp;
+	struct aper_size_info_8 *previous_size;
+
+	previous_size = A_SIZE_8(agp_bridge->previous_size);
+	pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp);
+	pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9));
+	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, previous_size->size_value);
+}
+
+static int intel_845_configure(void)
+{
+	u32 temp;
+	u8 temp2;
+	struct aper_size_info_8 *current_size;
+
+	current_size = A_SIZE_8(agp_bridge->current_size);
+
+	/* 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);
+
+	/* attbase - aperture base */
+	pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr); 
+
+	/* agpctrl */
+	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); 
+
+	/* agpm */
+	pci_read_config_byte(agp_bridge->dev, INTEL_I845_AGPM, &temp2);
+	pci_write_config_byte(agp_bridge->dev, INTEL_I845_AGPM, temp2 | (1 << 1));
+	/* clear any possible error conditions */
+	pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c); 
+	return 0;
+}
+
+
+static int intel_860_configure(void)
+{
+	u32 temp;
+	u16 temp2;
+	struct aper_size_info_8 *current_size;
+
+	current_size = A_SIZE_8(agp_bridge->current_size);
+
+	/* 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);
+
+	/* attbase - aperture base */
+	pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
+
+	/* agpctrl */
+	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
+
+	/* mcgcfg */
+	pci_read_config_word(agp_bridge->dev, INTEL_I860_MCHCFG, &temp2);
+	pci_write_config_word(agp_bridge->dev, INTEL_I860_MCHCFG, temp2 | (1 << 9));
+	/* clear any possible AGP-related error conditions */
+	pci_write_config_word(agp_bridge->dev, INTEL_I860_ERRSTS, 0xf700);
+	return 0;
+}
+
+/* Setup function */
+static struct gatt_mask intel_generic_masks[] =
+{
+	{.mask = 0x00000017, .type = 0}
+};
+
+static struct aper_size_info_8 intel_8xx_sizes[7] =
+{
+	{256, 65536, 6, 0},
+	{128, 32768, 5, 32},
+	{64, 16384, 4, 48},
+	{32, 8192, 3, 56},
+	{16, 4096, 2, 60},
+	{8, 2048, 1, 62},
+	{4, 1024, 0, 63}
+};
+
+struct agp_bridge_driver intel_830_driver = {
+	.owner			= THIS_MODULE,
+	.aperture_sizes		= intel_i830_sizes,
+	.size_type		= FIXED_APER_SIZE,
+	.num_aperture_sizes 	= 2,
+	.needs_scratch_page	= TRUE,
+	.configure		= intel_i830_configure,
+	.fetch_size		= intel_i830_fetch_size,
+	.cleanup		= intel_i830_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_i830_create_gatt_table,
+	.free_gatt_table	= intel_i830_free_gatt_table,
+	.insert_memory		= intel_i830_insert_entries,
+	.remove_memory		= intel_i830_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,
+};
+
+struct agp_bridge_driver intel_845_driver = {
+	.owner			= THIS_MODULE,
+	.aperture_sizes		= intel_8xx_sizes,
+	.size_type		= U8_APER_SIZE,
+	.num_aperture_sizes	= 7,
+	.configure		= intel_845_configure,
+	.fetch_size		= intel_8xx_fetch_size,
+	.cleanup		= intel_8xx_cleanup,
+	.tlb_flush		= intel_8xx_tlbflush,
+	.mask_memory		= agp_generic_mask_memory,
+	.masks			= intel_generic_masks,
+	.agp_enable		= agp_generic_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= agp_generic_create_gatt_table,
+	.free_gatt_table	= agp_generic_free_gatt_table,
+	.insert_memory		= agp_generic_insert_memory,
+	.remove_memory		= agp_generic_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+};
+
+
+struct agp_bridge_driver intel_860_driver = {
+	.owner			= THIS_MODULE,
+	.aperture_sizes		= intel_8xx_sizes,
+	.size_type		= U8_APER_SIZE,
+	.num_aperture_sizes	= 7,
+	.configure		= intel_860_configure,
+	.fetch_size		= intel_8xx_fetch_size,
+	.cleanup		= intel_8xx_cleanup,
+	.tlb_flush		= intel_8xx_tlbflush,
+	.mask_memory		= agp_generic_mask_memory,
+	.masks			= intel_generic_masks,
+	.agp_enable		= agp_generic_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= agp_generic_create_gatt_table,
+	.free_gatt_table	= agp_generic_free_gatt_table,
+	.insert_memory		= agp_generic_insert_memory,
+	.remove_memory		= agp_generic_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+};
+
+static int find_i830(u16 device)
+{
+	struct pci_dev *i830_dev;
+
+	i830_dev = pci_find_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,
+				device, i830_dev);
+	}
+
+	if (!i830_dev)
+		return 0;
+
+	intel_i830_private.i830_dev = i830_dev;
+	return 1;
+}
+
+static int __devinit agp_ia32e_probe(struct pci_dev *pdev,
+				     const struct pci_device_id *ent)
+{
+	struct agp_bridge_data *bridge;
+	char *name = "(unknown)";
+	u8 cap_ptr = 0;
+	struct resource *r;
+
+	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
+
+	bridge = agp_alloc_bridge();
+	if (!bridge)
+		return -ENOMEM;
+
+	switch (pdev->device) {
+	case PCI_DEVICE_ID_INTEL_82865_HB:
+		if (find_i830(PCI_DEVICE_ID_INTEL_82865_IG)) {
+			bridge->driver = &intel_830_driver;
+		} else {
+			bridge->driver = &intel_845_driver;
+		}
+		name = "865";
+		break;
+	case PCI_DEVICE_ID_INTEL_82875_HB:
+		bridge->driver = &intel_845_driver;
+		name = "i875";
+		break;
+
+	default:
+		printk(KERN_ERR PFX "Unsupported Intel chipset (device id: %04x)\n",
+			    pdev->device);
+		return -ENODEV;
+	};
+
+	bridge->dev = pdev;
+	bridge->capndx = cap_ptr;
+
+	if (bridge->driver == &intel_830_driver)
+		bridge->dev_private_data = &intel_i830_private;
+
+	printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n", name);
+
+	/*
+	* The following fixes the case where the BIOS has "forgotten" to
+	* provide an address range for the GART.
+	* 20030610 - hamish@zot.org
+	*/
+	r = &pdev->resource[0];
+	if (!r->start && r->end) {
+		if(pci_assign_resource(pdev, 0)) {
+			printk(KERN_ERR PFX "could not assign resource 0\n");
+			return (-ENODEV);
+		}
+	}
+
+	/*
+	* If the device has not been properly setup, the following will catch
+	* the problem and should stop the system from crashing.
+	* 20030610 - hamish@zot.org
+	*/
+	if (pci_enable_device(pdev)) {
+		printk(KERN_ERR PFX "Unable to Enable PCI device\n");
+		return (-ENODEV);
+	}
+
+	/* Fill in the mode register */
+	if (cap_ptr) {
+		pci_read_config_dword(pdev,
+				bridge->capndx+PCI_AGP_STATUS,
+				&bridge->mode);
+	}
+
+	pci_set_drvdata(pdev, bridge);
+	return agp_add_bridge(bridge);
+}
+
+static void __devexit agp_ia32e_remove(struct pci_dev *pdev)
+{
+	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+
+	agp_remove_bridge(bridge);
+	agp_put_bridge(bridge);
+}
+
+static int agp_ia32e_suspend(struct pci_dev *dev, u32 state)
+{
+	return 0;
+}
+
+static int agp_ia32e_resume(struct pci_dev *pdev)
+{
+	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+
+	if (bridge->driver == &intel_845_driver)
+		intel_845_configure();
+
+	return 0;
+}
+
+static struct pci_device_id agp_ia32e_pci_table[] = {
+	{
+	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
+	.class_mask	= ~0,
+	.vendor		= PCI_VENDOR_ID_INTEL,
+	.device		= PCI_ANY_ID,
+	.subvendor	= PCI_ANY_ID,
+	.subdevice	= PCI_ANY_ID,
+	},
+	{ }
+};
+
+MODULE_DEVICE_TABLE(pci, agp_ia32e_pci_table);
+
+static struct pci_driver agp_ia32e_pci_driver = {
+	.name		= "agpgart-ia32e",
+	.id_table	= agp_ia32e_pci_table,
+	.probe		= agp_ia32e_probe,
+	.remove		= agp_ia32e_remove,
+	.suspend	= agp_ia32e_suspend,
+	.resume		= agp_ia32e_resume,
+};
+
+/* intel_agp_init() must not be declared static for explicit
+   early initialization to work (ie i810fb) */
+int __init agp_ia32e_init(void)
+{
+	static int agp_initialised=0;
+
+	if (agp_initialised == 1)
+		return 0;
+	agp_initialised=1;
+
+	return pci_module_init(&agp_ia32e_pci_driver);
+}
+
+static void __exit agp_ia32e_cleanup(void)
+{
+	pci_unregister_driver(&agp_ia32e_pci_driver);
+}
+
+module_init(agp_ia32e_init);
+module_exit(agp_ia32e_cleanup);
+
+MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
+MODULE_LICENSE("GPL and additional rights");
+
diff -Nru a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
--- a/drivers/char/agp/intel-agp.c	Sun Mar 21 00:24:09 2004
+++ b/drivers/char/agp/intel-agp.c	Sun Mar 21 00:24:09 2004
@@ -13,6 +13,31 @@
 #include <linux/agp_backend.h>
 #include "agp.h"
 
+/* Intel 815 register */
+#define INTEL_815_APCONT	0x51
+#define INTEL_815_ATTBASE_MASK	~0x1FFFFFFF
+
+/* Intel i820 registers */
+#define INTEL_I820_RDCR		0x51
+#define INTEL_I820_ERRSTS	0xc8
+
+/* Intel i840 registers */
+#define INTEL_I840_MCHCFG	0x50
+#define INTEL_I840_ERRSTS	0xc8
+
+/* Intel i850 registers */
+#define INTEL_I850_MCHCFG	0x50
+#define INTEL_I850_ERRSTS	0xc8
+
+/* Intel 7505 registers */
+#define INTEL_I7505_APSIZE	0x74
+#define INTEL_I7505_NCAPID	0x60
+#define INTEL_I7505_NISTAT	0x6c
+#define INTEL_I7505_ATTBASE	0x78
+#define INTEL_I7505_ERRSTS	0x42
+#define INTEL_I7505_AGPCTRL	0x70
+#define INTEL_I7505_MCHCFG	0x50
+
 static struct aper_size_info_fixed intel_i810_sizes[] =
 {
 	{64, 16384, 4},
diff -Nru a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
--- a/drivers/char/agp/nvidia-agp.c	Sun Mar 21 00:24:09 2004
+++ b/drivers/char/agp/nvidia-agp.c	Sun Mar 21 00:24:09 2004
@@ -13,6 +13,17 @@
 #include <linux/mm.h>
 #include "agp.h"
 
+/* NVIDIA registers */
+#define NVIDIA_0_APSIZE		0x80
+#define NVIDIA_1_WBC		0xf0
+#define NVIDIA_2_GARTCTRL	0xd0
+#define NVIDIA_2_APBASE		0xd8
+#define NVIDIA_2_APLIMIT	0xdc
+#define NVIDIA_2_ATTBASE(i)	(0xe0 + (i) * 4)
+#define NVIDIA_3_APBASE		0x50
+#define NVIDIA_3_APLIMIT	0x54
+
+
 static struct _nvidia_private {
 	struct pci_dev *dev_1;
 	struct pci_dev *dev_2;
diff -Nru a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
--- a/drivers/char/agp/sis-agp.c	Sun Mar 21 00:24:09 2004
+++ b/drivers/char/agp/sis-agp.c	Sun Mar 21 00:24:09 2004
@@ -8,6 +8,12 @@
 #include <linux/agp_backend.h>
 #include "agp.h"
 
+#define SIS_ATTBASE	0x90
+#define SIS_APSIZE	0x94
+#define SIS_TLBCNTRL	0x97
+#define SIS_TLBFLUSH	0x98
+
+
 static int sis_fetch_size(void)
 {
 	u8 temp_size;
@@ -61,6 +67,42 @@
 			      (previous_size->size_value & ~(0x03)));
 }
 
+static void sis_648_enable(u32 mode)
+{
+	struct pci_dev *device = NULL;
+	u32 command;
+	int rate;
+
+	printk(KERN_INFO PFX "Found an AGP %d.%d compliant device at %s.\n",
+		agp_bridge->major_version,
+		agp_bridge->minor_version,
+		agp_bridge->dev->slot_name);
+
+	pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + PCI_AGP_STATUS, &command);
+	command = agp_collect_device_status(mode, command);
+	command |= AGPSTAT_AGP_ENABLE;
+	rate = (command & 0x7) << 2;
+
+	while ((device = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, device)) != NULL) {
+		u8 agp = pci_find_capability(device, PCI_CAP_ID_AGP);
+		if (!agp)
+			continue;
+
+		printk(KERN_INFO PFX "Putting AGP V3 device at %s into %dx mode\n",
+			pci_name(device), rate);
+
+		pci_write_config_dword(device, agp + PCI_AGP_COMMAND, command);
+
+		if(device->device == PCI_DEVICE_ID_SI_648) {
+			// weird: on 648 and 648fx chipsets any rate change in the target command register
+			// triggers a 5ms screwup during which the master cannot be configured
+			printk(KERN_INFO PFX "sis 648 agp fix - giving bridge time to recover\n");
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout (1+(HZ*10)/1000);
+		}
+	}
+}
+
 static struct aper_size_info_8 sis_generic_sizes[7] =
 {
 	{256, 65536, 6, 99},
@@ -176,6 +218,26 @@
 	{ }, /* dummy final entry, always present */
 };
 
+
+static void __devinit sis_get_driver(struct agp_bridge_data *bridge)
+{
+	if (bridge->dev->device == PCI_DEVICE_ID_SI_648) {
+		if (agp_bridge->major_version == 3 && agp_bridge->minor_version < 5) {
+			sis_driver.agp_enable=sis_648_enable;
+		} else {
+			sis_driver.agp_enable			= sis_648_enable;
+			sis_driver.aperture_sizes		= agp3_generic_sizes;
+			sis_driver.size_type			= U16_APER_SIZE;
+			sis_driver.num_aperture_sizes	= AGP_GENERIC_SIZES_ENTRIES;
+			sis_driver.configure			= agp3_generic_configure;
+			sis_driver.fetch_size			= agp3_generic_fetch_size;
+			sis_driver.cleanup				= agp3_generic_cleanup;
+			sis_driver.tlb_flush			= agp3_generic_tlbflush;
+		}
+	}
+}
+
+
 static int __devinit agp_sis_probe(struct pci_dev *pdev,
 				   const struct pci_device_id *ent)
 {
@@ -210,10 +272,11 @@
 	bridge->dev = pdev;
 	bridge->capndx = cap_ptr;
 
+	get_agp_version(bridge);
+
 	/* Fill in the mode register */
-	pci_read_config_dword(pdev,
-			bridge->capndx+PCI_AGP_STATUS,
-			&bridge->mode);
+	pci_read_config_dword(pdev, bridge->capndx+PCI_AGP_STATUS, &bridge->mode);
+	sis_get_driver(bridge);
 
 	pci_set_drvdata(pdev, bridge);
 	return agp_add_bridge(bridge);
diff -Nru a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
--- a/drivers/char/agp/sworks-agp.c	Sun Mar 21 00:24:09 2004
+++ b/drivers/char/agp/sworks-agp.c	Sun Mar 21 00:24:09 2004
@@ -8,6 +8,23 @@
 #include <linux/agp_backend.h>
 #include "agp.h"
 
+#define SVWRKS_COMMAND		0x04
+#define SVWRKS_APSIZE		0x10
+#define SVWRKS_MMBASE		0x14
+#define SVWRKS_CACHING		0x4b
+#define SVWRKS_AGP_ENABLE	0x60
+#define SVWRKS_FEATURE		0x68
+
+#define SVWRKS_SIZE_MASK	0xfe000000
+
+/* Memory mapped registers */
+#define SVWRKS_GART_CACHE	0x02
+#define SVWRKS_GATTBASE		0x04
+#define SVWRKS_TLBFLUSH		0x10
+#define SVWRKS_POSTFLUSH	0x14
+#define SVWRKS_DIRFLUSH		0x0c
+
+
 struct serverworks_page_map {
 	unsigned long *real;
 	unsigned long *remapped;
@@ -454,10 +471,17 @@
 	}
 
 	switch (pdev->device) {
+	case 0x0006:
+		/* ServerWorks CNB20HE
+		Fail silently.*/
+		printk (KERN_ERR PFX "Detected ServerWorks CNB20HE chipset: No AGP present.\n");
+		return -ENODEV;
+
 	case PCI_DEVICE_ID_SERVERWORKS_HE:
 	case PCI_DEVICE_ID_SERVERWORKS_LE:
 	case 0x0007:
 		break;
+
 	default:
 		printk(KERN_ERR PFX "Unsupported Serverworks chipset "
 				"(device id: %04x)\n", pdev->device);
diff -Nru a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
--- a/drivers/char/agp/via-agp.c	Sun Mar 21 00:24:09 2004
+++ b/drivers/char/agp/via-agp.c	Sun Mar 21 00:24:09 2004
@@ -9,6 +9,15 @@
 #include <linux/agp_backend.h>
 #include "agp.h"
 
+#define VIA_GARTCTRL	0x80
+#define VIA_APSIZE	0x84
+#define VIA_ATTBASE	0x88
+
+#define VIA_AGP3_GARTCTRL	0x90
+#define VIA_AGP3_APSIZE		0x94
+#define VIA_AGP3_ATTBASE	0x98
+#define VIA_AGPSEL		0xfd
+
 static int via_fetch_size(void)
 {
 	int i;