bk://linux-dj.bkbits.net/agpgart
davej@delerium.kernelslacker.org|ChangeSet|20050203214041|58980 davej

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2005/02/02 20:24:51-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-agpgart
# 
# include/linux/pci_ids.h
#   2005/02/02 20:24:44-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/01/26 01:53:54-05:00 davej@redhat.com 
#   [AGPGART] Make agp=off boot param work for Intel AGP drivers.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/intel-mch-agp.c
#   2005/01/26 01:53:45-05:00 davej@redhat.com +2 -0
#   [AGPGART] Make agp=off boot param work for Intel AGP drivers.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/intel-agp.c
#   2005/01/26 01:53:45-05:00 davej@redhat.com +2 -0
#   [AGPGART] Make agp=off boot param work for Intel AGP drivers.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/01/25 22:52:58-05:00 davej@redhat.com 
#   [AGPGART] Make sure we don't give up searching for gfx cards.
#   
#   We need to clear the previously found cap_ptr, or we exit after
#   finding the first one, even if its not the one plugged into the
#   bridge we're looking at.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/01/25 22:52:49-05:00 davej@redhat.com +1 -0
#   [AGPGART] Make sure we don't give up searching for gfx cards.
#   
#   We need to clear the previously found cap_ptr, or we exit after
#   finding the first one, even if its not the one plugged into the
#   bridge we're looking at.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/01/25 22:48:16-05:00 davej@redhat.com 
#   [AGPGART] Map the graphic card to the bridge its connected to.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/01/25 22:48:07-05:00 davej@redhat.com +5 -0
#   [AGPGART] Map the graphic card to the bridge its connected to.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/01/25 14:27:39-05:00 davej@redhat.com 
#   [AGPGART] Silly thinko in reserve bit masking.
#   
#   Stupid inversion meant we passed '0' to userspace, and madness
#   ensued resulting in very funky visuals.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/01/25 14:27:29-05:00 davej@redhat.com +2 -2
#   [AGPGART] Silly thinko in reserve bit masking.
#   
#   Stupid inversion meant we passed '0' to userspace, and madness
#   ensued resulting in very funky visuals.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/01/24 15:45:32-05:00 davej@redhat.com 
#   [AGPGART] Fix the same pci_get_class bug in the amd-k7 driver.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/amd-k7-agp.c
#   2005/01/24 15:45:23-05:00 davej@redhat.com +1 -1
#   [AGPGART] Fix the same pci_get_class bug in the amd-k7 driver.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/01/24 15:37:57-05:00 davej@redhat.com 
#   [AGPGART] Fix stupid thinko in device discovery.
#   
#   Should fix the 'cant find AGP VGA controller' warnings.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/01/24 15:37:48-05:00 davej@redhat.com +1 -1
#   [AGPGART] Fix stupid thinko in device discovery.
#   
#   Should fix the 'cant find AGP VGA controller' warnings.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/01/23 21:12:57-05:00 davej@redhat.com 
#   [AGPGART] In AGP2.0 mode, if we're in 1X mode, disable fast writes.
#   
#   In this mode, fast writes are just ignored, and treated as regular PCI
#   writes, but disabling them explicitly doesn't hurt.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/01/23 21:12:48-05:00 davej@redhat.com +4 -0
#   [AGPGART] In AGP2.0 mode, if we're in 1X mode, disable fast writes.
#   
#   In this mode, fast writes are just ignored, and treated as regular PCI
#   writes, but disabling them explicitly doesn't hurt.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/01/23 20:39:41-05:00 davej@redhat.com 
#   [AGPGART] Mask out the reserved bits of the agp mode register before handing them to userspace.
#   
#   X munges what we hand to it, so with luck, this will lower the possibility
#   of it handing us something with reserved bits set.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/01/23 20:39:32-05:00 davej@redhat.com +17 -14
#   [AGPGART] Mask out the reserved bits of the agp mode register before handing them to userspace.
#   
#   X munges what we hand to it, so with luck, this will lower the possibility
#   of it handing us something with reserved bits set.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/01/23 20:32:04-05:00 davej@redhat.com 
#   [AGPGART] Introduce routine to check current operating mode of agp bridge.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/01/23 20:31:55-05:00 davej@redhat.com +17 -11
#   [AGPGART] Introduce routine to check current operating mode of agp bridge.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/01/23 18:20:47-05:00 davej@redhat.com 
#   [AGPGART] Remove pointless tests for bridge vendor from amd-k7-agp driver.
#   
#   If we got far enough to run this code, we *must* have an AMD bridge.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/amd-k7-agp.c
#   2005/01/23 18:20:38-05:00 davej@redhat.com +2 -4
#   [AGPGART] Remove pointless tests for bridge vendor from amd-k7-agp driver.
#   
#   If we got far enough to run this code, we *must* have an AMD bridge.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/01/23 18:15:23-05:00 davej@redhat.com 
#   [AGPGART] AMD 751 errata workaround.
#   Some combinations of NVidia GeForce cards and this AGP chipset cause lockups
#   when operated in AGP x2 mode. Force them to x1 mode for safety.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/amd-k7-agp.c
#   2005/01/23 18:15:15-05:00 davej@redhat.com +31 -0
#   [AGPGART] AMD 751 errata workaround.
#   Some combinations of NVidia GeForce cards and this AGP chipset cause lockups
#   when operated in AGP x2 mode. Force them to x1 mode for safety.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/01/23 17:54:23-05:00 davej@redhat.com 
#   [AGPGART] AMD 761 errata workaround.
#   B0/B1 steppings of this chipset were horribly broken,
#   and couldn't do fast writes, or side band addressing.
#   Looking through the errata on this one reads like a horror story, it's
#   a miracle it could get AGP x1 working.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/amd-k7-agp.c
#   2005/01/23 17:54:15-05:00 davej@redhat.com +18 -0
#   [AGPGART] AMD 761 errata workaround.
#   B0/B1 steppings of this chipset were horribly broken,
#   and couldn't do fast writes, or side band addressing, or x2.
#   Looking through the errata on this one reads like a horror story, it's
#   a miracle it could get AGP x1 working.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/01/23 15:48:47-05:00 davej@redhat.com 
#   [AGPGART] Add mechanism for chipset specific errata.
#   
#   Allow chipset drivers to tell the generic routines not to enable
#   certain features if they have errata when those features are used. 
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/01/23 15:48:38-05:00 davej@redhat.com +29 -3
#   [AGPGART] Add mechanism for chipset specific errata.
#   
#   Allow chipset drivers to tell the generic routines not to enable
#   certain features if they have errata when those features are used. 
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/agp.h
#   2005/01/23 15:48:38-05:00 davej@redhat.com +5 -0
#   [AGPGART] Add mechanism for chipset specific errata.
#   
#   Allow chipset drivers to tell the generic routines not to enable
#   certain features if they have errata when those features are used. 
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/01/23 03:03:58-05:00 davej@redhat.com 
#   [AGPGART] Name & Shame the apps passing bad flags.
#   (Basically a distinction between XFree and Xorg)
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/01/23 03:03:49-05:00 davej@redhat.com +6 -6
#   [AGPGART] Name & Shame the apps passing bad flags.
#   (Basically a distinction between XFree and Xorg)
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/01/23 03:01:22-05:00 davej@redhat.com 
#   [AGPGART] Do some sanity checks on the rates that userspace passes.
#   
#   The AGP specifications define the following...
#   
#         agp2 agp3
#   000   BAD  BAD
#   001   x1   x4
#   010   x2   x8
#   011   BAD  x8
#   100   x4   BAD
#   101   BAD  BAD
#   110   BAD  BAD
#   111   BAD  BAD
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/01/23 03:01:13-05:00 davej@redhat.com +33 -0
#   [AGPGART] Do some sanity checks on the rates that userspace passes.
#   
#   The AGP specifications define the following...
#   
#         agp2 agp3
#   000   BAD  BAD
#   001   x1   x4
#   010   x2   x8
#   011   BAD  x8
#   100   x4   BAD
#   101   BAD  BAD
#   110   BAD  BAD
#   111   BAD  BAD
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/01/23 02:59:57-05:00 davej@redhat.com 
#   [AGPGART] Fix up the reserved bits.
#   The previous checks were against AGP_STAT values, but userspace passes us
#   an agp command register.
# 
# drivers/char/agp/agp.h
#   2005/01/23 02:59:48-05:00 davej@redhat.com +2 -2
#   [AGPGART] Fix up the reserved bits.
#   The previous checks were against AGP_STAT values, but userspace passes us
#   an agp command register.
# 
# ChangeSet
#   2005/01/23 01:58:34-05:00 davej@redhat.com 
#   [AGPGART] Warn and fix up mode if userspace passes nonsense.
#   Check the reserved bits in the agp mode register.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/01/23 01:58:26-05:00 davej@redhat.com +11 -1
#   [AGPGART] Warn and fix up mode if userspace passes nonsense.
#   Check the reserved bits in the agp mode register.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/agp.h
#   2005/01/23 01:58:26-05:00 davej@redhat.com +3 -0
#   [AGPGART] Warn and fix up mode if userspace passes nonsense.
#   Check the reserved bits in the agp mode register.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/01/23 01:35:11-05:00 davej@redhat.com 
#   [AGPGART] Check the bridge is in 3.0 mode, not the graphic card.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/01/23 01:35:03-05:00 davej@redhat.com +4 -3
#   [AGPGART] Check the bridge is in 3.0 mode, not the graphic card.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/agp.h
#   2005/01/23 01:35:03-05:00 davej@redhat.com +1 -1
#   [AGPGART] Check the bridge is in 3.0 mode, not the graphic card.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/01/23 01:27:05-05:00 davej@redhat.com 
#   [AGPGART] Fix refcount bug in mode parsing code.
#   
#   The pci_get_class conversion leaked this refcount.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/01/23 01:26:57-05:00 davej@redhat.com +4 -3
#   [AGPGART] Fix refcount bug in mode parsing code.
#   
#   The pci_get_class conversion leaked this refcount.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/01/23 01:21:56-05:00 davej@redhat.com 
#   [AGPGART] Rename a bunch of ambiguous variables.
#   mode = What X wants us to set the mode to (As set by AGPMode in X config)
#   cmd = PCI_AGP_STATUS from the AGP bridge.
#   tmp = PCI_AGP_STATUS from the graphic card.
#   
#   mode -> requested_mode
#   cmd -> bridge_agpstat
#   tmp -> vga_agpstat
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/01/23 01:21:47-05:00 davej@redhat.com +74 -72
#   [AGPGART] Rename a bunch of ambiguous variables.
#   mode = What X wants us to set the mode to (As set by AGPMode in X config)
#   cmd = PCI_AGP_STATUS from the AGP bridge.
#   tmp = PCI_AGP_STATUS from the graphic card.
#   
#   mode -> requested_mode
#   cmd -> bridge_agpstat
#   tmp -> vga_agpstat
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/01/23 01:02:33-05:00 davej@redhat.com 
#   [AGPGART] Don't scan whole bus for a VGA card.
#   Use the handy pci_get_class() function instead of implementing our own
#   pci bus walking loop.  Also makes it skip non-VGA devices fixing up a
#   long-standing FIXME. Previously, it may have been tripping up on AGP
#   bridges, which could have caused all sorts of sillyness.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/01/23 01:02:24-05:00 davej@redhat.com +45 -29
#   [AGPGART] Don't scan whole bus for a VGA card.
#   Use the handy pci_get_class() function instead of implementing our own
#   pci bus walking loop.  Also makes it skip non-VGA devices fixing up a
#   long-standing FIXME. Previously, it may have been tripping up on AGP
#   bridges, which could have caused all sorts of sillyness.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/01/20 15:26:37-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-agpgart
# 
# include/linux/pci_ids.h
#   2005/01/20 15:26:32-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/01/19 13:50:39-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-agpgart
# 
# include/linux/pci_ids.h
#   2005/01/19 13:50:35-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/01/15 17:52:11-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-agpgart
# 
# include/linux/pci_ids.h
#   2005/01/15 17:52:06-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/01/12 12:07:51-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-agpgart
# 
# include/linux/pci_ids.h
#   2005/01/12 12:07:45-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/01/11 11:40:41-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-agpgart
# 
# include/linux/pci_ids.h
#   2005/01/11 11:40:37-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/01/10 14:26:42-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-agpgart
# 
# include/linux/pci_ids.h
#   2005/01/10 14:26:36-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/01/08 20:55:21-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-agpgart
# 
# include/linux/pci_ids.h
#   2005/01/08 20:55:14-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/12/30 22:57:33-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-agpgart
# 
# include/linux/pci_ids.h
#   2004/12/30 22:57:28-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/12/29 17:46:46-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-agpgart
# 
# include/linux/pci_ids.h
#   2004/12/29 17:46:41-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/12/27 00:11:51-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-agpgart
# 
# include/linux/pci_ids.h
#   2004/12/27 00:11:47-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/12/25 08:19:35-08:00 akpm@bix.(none) 
#   Merge bk://linux-dj.bkbits.net/agpgart
#   into bix.(none):/usr/src/bk-agpgart
# 
# include/linux/pci_ids.h
#   2004/12/25 08:19:30-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/12/25 08:17:55-08:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-agpgart
# 
# include/linux/pci_ids.h
#   2004/12/25 08:17:50-08:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
diff -Nru a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
--- a/drivers/char/agp/agp.h	2005-02-03 18:04:22 -08:00
+++ b/drivers/char/agp/agp.h	2005-02-03 18:04:22 -08:00
@@ -137,6 +137,7 @@
 	int max_memory_agp;	/* in number of pages */
 	int aperture_size_idx;
 	int capndx;
+	int flags;
 	char major_version;
 	char minor_version;
 };
@@ -255,7 +256,7 @@
 void agp_generic_destroy_page(void *addr);
 void agp_free_key(int key);
 int agp_num_entries(void);
-u32 agp_collect_device_status(u32 mode, u32 command);
+u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 mode, u32 command);
 void agp_device_command(u32 command, int agp_v3);
 int agp_3_5_enable(struct agp_bridge_data *bridge);
 void global_cache_flush(void);
@@ -314,5 +315,12 @@
 
 #define AGPCTRL_APERENB		(1<<8)
 #define AGPCTRL_GTLBEN		(1<<7)
+
+#define AGP2_RESERVED_MASK 0x00fffcc8
+#define AGP3_RESERVED_MASK 0x00ff00cc
+
+#define AGP_ERRATA_FASTWRITES 1<<0
+#define AGP_ERRATA_SBA	 1<<1
+#define AGP_ERRATA_1X 1<<2
 
 #endif	/* _AGP_BACKEND_PRIV_H */
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	2005-02-03 18:04:22 -08:00
+++ b/drivers/char/agp/amd-k7-agp.c	2005-02-03 18:04:22 -08:00
@@ -421,6 +421,53 @@
 	bridge->dev = pdev;
 	bridge->capndx = cap_ptr;
 
+	/* 751 Errata (22564_B-1.PDF)
+	   erratum 20: strobe glitch with Nvidia NV10 GeForce cards.
+	   system controller may experience noise due to strong drive strengths
+	 */
+	if (agp_bridge->dev->device == PCI_DEVICE_ID_AMD_FE_GATE_7006) {
+		u8 cap_ptr=0;
+		struct pci_dev *gfxcard=NULL;
+		while (!cap_ptr) {
+			gfxcard = pci_get_class(PCI_CLASS_DISPLAY_VGA<<8, gfxcard);
+			if (!gfxcard) {
+				printk (KERN_INFO PFX "Couldn't find an AGP VGA controller.\n");
+				return -ENODEV;
+			}
+			cap_ptr = pci_find_capability(gfxcard, PCI_CAP_ID_AGP);
+			if (!cap_ptr) {
+				pci_dev_put(gfxcard);
+				continue;
+			}
+		}
+
+		/* With so many variants of NVidia cards, it's simpler just
+		   to blacklist them all, and then whitelist them as needed
+		   (if necessary at all). */
+		if (gfxcard->vendor == PCI_VENDOR_ID_NVIDIA) {
+			agp_bridge->flags |= AGP_ERRATA_1X;
+			printk (KERN_INFO PFX "AMD 751 chipset with NVidia GeForce detected. Forcing to 1X due to errata.\n");
+		}
+		pci_dev_put(gfxcard);
+	}
+
+	/* 761 Errata (23613_F.pdf)
+	 * Revisions B0/B1 were a disaster.
+	 * erratum 44: SYSCLK/AGPCLK skew causes 2X failures -- Force mode to 1X
+	 * erratum 45: Timing problem prevents fast writes -- Disable fast write.
+	 * erratum 46: Setup violation on AGP SBA pins - Disable side band addressing.
+	 * With this lot disabled, we should prevent lockups. */
+	if (agp_bridge->dev->device == PCI_DEVICE_ID_AMD_FE_GATE_700E) {
+		u8 revision=0;
+		pci_read_config_byte(pdev, PCI_REVISION_ID, &revision);
+		if (revision == 0x10 || revision == 0x11) {
+			agp_bridge->flags = AGP_ERRATA_FASTWRITES;
+			agp_bridge->flags |= AGP_ERRATA_SBA;
+			agp_bridge->flags |= AGP_ERRATA_1X;
+			printk (KERN_INFO PFX "AMD 761 chipset with errata detected - disabling AGP fast writes & SBA and forcing to 1X.\n");
+		}
+	}
+
 	/* Fill in the mode register */
 	pci_read_config_dword(pdev,
 			bridge->capndx+PCI_AGP_STATUS,
diff -Nru a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
--- a/drivers/char/agp/generic.c	2005-02-03 18:04:22 -08:00
+++ b/drivers/char/agp/generic.c	2005-02-03 18:04:22 -08:00
@@ -1,6 +1,6 @@
 /*
  * AGPGART driver.
- * Copyright (C) 2002-2004 Dave Jones.
+ * Copyright (C) 2002-2005 Dave Jones.
  * Copyright (C) 1999 Jeff Hartmann.
  * Copyright (C) 1999 Precision Insight, Inc.
  * Copyright (C) 1999 Xi Graphics, Inc.
@@ -289,6 +289,19 @@
 EXPORT_SYMBOL_GPL(agp_num_entries);
 
 
+static int check_bridge_mode(struct pci_dev *dev)
+{
+	u32 agp3;
+	u8 cap_ptr;
+
+	cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP);
+	pci_read_config_dword(dev, cap_ptr+AGPSTAT, &agp3);
+	if (agp3 & AGPSTAT_MODE_3_0)
+		return 1;
+	return 0;
+}
+
+
 /**
  *	agp_copy_info  -  copy bridge state information
  *
@@ -310,7 +323,10 @@
 	info->version.minor = agp_bridge->version->minor;
 	info->chipset = agp_bridge->type;
 	info->device = agp_bridge->dev;
-	info->mode = agp_bridge->mode;
+	if (check_bridge_mode(agp_bridge->dev))
+		info->mode = agp_bridge->mode & ~AGP3_RESERVED_MASK;
+	else
+		info->mode = agp_bridge->mode & ~AGP2_RESERVED_MASK;
 	info->aper_base = agp_bridge->gart_bus_addr;
 	info->aper_size = agp_return_size();
 	info->max_memory = agp_bridge->max_memory_agp;
@@ -403,71 +419,130 @@
 
 
 /* Generic Agp routines - Start */
-static void agp_v2_parse_one(u32 *mode, u32 *cmd, u32 *tmp)
+static void agp_v2_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_agpstat)
 {
+	u32 tmp;
+
+	if (*requested_mode & AGP2_RESERVED_MASK) {
+		printk (KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode);
+		*requested_mode &= ~AGP2_RESERVED_MASK;
+	}
+
+	/* Check the speed bits make sense. Only one should be set. */
+	tmp = *requested_mode & 7;
+	if (tmp == 0) {
+		printk (KERN_INFO PFX "%s tried to set rate=x0. Setting to x1 mode.\n", current->comm);
+		*requested_mode |= AGPSTAT2_1X;
+	}
+	if (tmp == 3) {
+		printk (KERN_INFO PFX "%s tried to set rate=x3. Setting to x2 mode.\n", current->comm);
+		*requested_mode |= AGPSTAT2_2X;
+	}
+	if (tmp >4) {
+		printk (KERN_INFO PFX "%s tried to set rate=x%d. Setting to x4 mode.\n", current->comm, tmp);
+		*requested_mode |= AGPSTAT2_4X;
+	}
+
 	/* disable SBA if it's not supported */
-	if (!((*cmd & AGPSTAT_SBA) && (*tmp & AGPSTAT_SBA) && (*mode & AGPSTAT_SBA)))
-		*cmd &= ~AGPSTAT_SBA;
+	if (!((*bridge_agpstat & AGPSTAT_SBA) && (*vga_agpstat & AGPSTAT_SBA) && (*requested_mode & AGPSTAT_SBA)))
+		*bridge_agpstat &= ~AGPSTAT_SBA;
 
-	/* Set speed */
-	if (!((*cmd & AGPSTAT2_4X) && (*tmp & AGPSTAT2_4X) && (*mode & AGPSTAT2_4X)))
-		*cmd &= ~AGPSTAT2_4X;
+	/* Set rate */
+	if (!((*bridge_agpstat & AGPSTAT2_4X) && (*vga_agpstat & AGPSTAT2_4X) && (*requested_mode & AGPSTAT2_4X)))
+		*bridge_agpstat &= ~AGPSTAT2_4X;
 
-	if (!((*cmd & AGPSTAT2_2X) && (*tmp & AGPSTAT2_2X) && (*mode & AGPSTAT2_2X)))
-		*cmd &= ~AGPSTAT2_2X;
+	if (!((*bridge_agpstat & AGPSTAT2_2X) && (*vga_agpstat & AGPSTAT2_2X) && (*requested_mode & AGPSTAT2_2X)))
+		*bridge_agpstat &= ~AGPSTAT2_2X;
 
-	if (!((*cmd & AGPSTAT2_1X) && (*tmp & AGPSTAT2_1X) && (*mode & AGPSTAT2_1X)))
-		*cmd &= ~AGPSTAT2_1X;
+	if (!((*bridge_agpstat & AGPSTAT2_1X) && (*vga_agpstat & AGPSTAT2_1X) && (*requested_mode & AGPSTAT2_1X)))
+		*bridge_agpstat &= ~AGPSTAT2_1X;
 
 	/* Now we know what mode it should be, clear out the unwanted bits. */
-	if (*cmd & AGPSTAT2_4X)
-		*cmd &= ~(AGPSTAT2_1X | AGPSTAT2_2X);	/* 4X */
+	if (*bridge_agpstat & AGPSTAT2_4X)
+		*bridge_agpstat &= ~(AGPSTAT2_1X | AGPSTAT2_2X);	/* 4X */
+
+	if (*bridge_agpstat & AGPSTAT2_2X)
+		*bridge_agpstat &= ~(AGPSTAT2_1X | AGPSTAT2_4X);	/* 2X */
 
-	if (*cmd & AGPSTAT2_2X)
-		*cmd &= ~(AGPSTAT2_1X | AGPSTAT2_4X);	/* 2X */
+	if (*bridge_agpstat & AGPSTAT2_1X)
+		*bridge_agpstat &= ~(AGPSTAT2_2X | AGPSTAT2_4X);	/* 1X */
 
-	if (*cmd & AGPSTAT2_1X)
-		*cmd &= ~(AGPSTAT2_2X | AGPSTAT2_4X);	/* 1X */
+	/* Apply any errata. */
+	if (agp_bridge->flags & AGP_ERRATA_FASTWRITES)
+		*bridge_agpstat &= ~AGPSTAT_FW;
+
+	if (agp_bridge->flags & AGP_ERRATA_SBA)
+		*bridge_agpstat &= ~AGPSTAT_SBA;
+
+	if (agp_bridge->flags & AGP_ERRATA_1X) {
+		*bridge_agpstat &= ~(AGPSTAT2_2X | AGPSTAT2_4X);
+		*bridge_agpstat |= AGPSTAT2_1X;
+	}
+
+	/* If we've dropped down to 1X, disable fast writes. */
+	if (*bridge_agpstat & AGPSTAT2_1X)
+		*bridge_agpstat &= ~AGPSTAT_FW;
 }
 
 /*
- * mode = requested mode.
- * cmd = PCI_AGP_STATUS from agp bridge.
- * tmp = PCI_AGP_STATUS from graphic card.
+ * requested_mode = Mode requested by (typically) X.
+ * bridge_agpstat = PCI_AGP_STATUS from agp bridge.
+ * vga_agpstat = PCI_AGP_STATUS from graphic card.
  */
-static void agp_v3_parse_one(u32 *mode, u32 *cmd, u32 *tmp)
+static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_agpstat)
 {
-	u32 origcmd=*cmd, origtmp=*tmp;
+	u32 origbridge=*bridge_agpstat, origvga=*vga_agpstat;
+	u32 tmp;
+
+	if (*requested_mode & AGP3_RESERVED_MASK) {
+		printk (KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode);
+		*requested_mode &= ~AGP3_RESERVED_MASK;
+	}
+
+	/* Check the speed bits make sense. */
+	tmp = *requested_mode & 7;
+	if (tmp == 0) {
+		printk (KERN_INFO PFX "%s tried to set rate=x0. Setting to AGP3 x4 mode.\n", current->comm);
+		*requested_mode |= AGPSTAT3_4X;
+	}
+	if (tmp == 3) {
+		printk (KERN_INFO PFX "%s tried to set rate=x3. Setting to AGP3 x4 mode.\n", current->comm);
+		*requested_mode |= AGPSTAT3_4X;
+	}
+	if (tmp >3) {
+		printk (KERN_INFO PFX "%s tried to set rate=x%d. Setting to AGP3 x8 mode.\n", current->comm, tmp);
+		*requested_mode |= AGPSTAT3_8X;
+	}
 
 	/* ARQSZ - Set the value to the maximum one.
 	 * Don't allow the mode register to override values. */
-	*cmd = ((*cmd & ~AGPSTAT_ARQSZ) |
-		max_t(u32,(*cmd & AGPSTAT_ARQSZ),(*tmp & AGPSTAT_ARQSZ)));
+	*bridge_agpstat = ((*bridge_agpstat & ~AGPSTAT_ARQSZ) |
+		max_t(u32,(*bridge_agpstat & AGPSTAT_ARQSZ),(*vga_agpstat & AGPSTAT_ARQSZ)));
 
 	/* Calibration cycle.
 	 * Don't allow the mode register to override values. */
-	*cmd = ((*cmd & ~AGPSTAT_CAL_MASK) |
-		min_t(u32,(*cmd & AGPSTAT_CAL_MASK),(*tmp & AGPSTAT_CAL_MASK)));
+	*bridge_agpstat = ((*bridge_agpstat & ~AGPSTAT_CAL_MASK) |
+		min_t(u32,(*bridge_agpstat & AGPSTAT_CAL_MASK),(*vga_agpstat & AGPSTAT_CAL_MASK)));
 
 	/* SBA *must* be supported for AGP v3 */
-	*cmd |= AGPSTAT_SBA;
+	*bridge_agpstat |= AGPSTAT_SBA;
 
 	/*
 	 * Set speed.
 	 * Check for invalid speeds. This can happen when applications
 	 * written before the AGP 3.0 standard pass AGP2.x modes to AGP3 hardware
 	 */
-	if (*mode & AGPSTAT_MODE_3_0) {
+	if (*requested_mode & AGPSTAT_MODE_3_0) {
 		/*
-		 * Caller hasn't a clue what its doing. We are in 3.0 mode,
+		 * Caller hasn't a clue what it is doing. Bridge is in 3.0 mode,
 		 * have been passed a 3.0 mode, but with 2.x speed bits set.
 		 * AGP2.x 4x -> AGP3.0 4x.
 		 */
-		if (*mode & AGPSTAT2_4X) {
+		if (*requested_mode & AGPSTAT2_4X) {
 			printk (KERN_INFO PFX "%s passes broken AGP3 flags (%x). Fixed.\n",
-						current->comm, *mode);
-			*mode &= ~AGPSTAT2_4X;
-			*mode |= AGPSTAT3_4X;
+						current->comm, *requested_mode);
+			*requested_mode &= ~AGPSTAT2_4X;
+			*requested_mode |= AGPSTAT3_4X;
 		}
 	} else {
 		/*
@@ -476,27 +551,27 @@
 		 * Convert AGP 1x,2x,4x -> AGP 3.0 4x.
 		 */
 		printk (KERN_INFO PFX "%s passes broken AGP2 flags (%x) in AGP3 mode. Fixed.\n",
-					current->comm, *mode);
-		*mode &= ~(AGPSTAT2_4X | AGPSTAT2_2X | AGPSTAT2_1X);
-		*mode |= AGPSTAT3_4X;
+					current->comm, *requested_mode);
+		*requested_mode &= ~(AGPSTAT2_4X | AGPSTAT2_2X | AGPSTAT2_1X);
+		*requested_mode |= AGPSTAT3_4X;
 	}
 
-	if (*mode & AGPSTAT3_8X) {
-		if (!(*cmd & AGPSTAT3_8X)) {
-			*cmd &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
-			*cmd |= AGPSTAT3_4X;
+	if (*requested_mode & AGPSTAT3_8X) {
+		if (!(*bridge_agpstat & AGPSTAT3_8X)) {
+			*bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
+			*bridge_agpstat |= AGPSTAT3_4X;
 			printk ("%s requested AGPx8 but bridge not capable.\n", current->comm);
 			return;
 		}
-		if (!(*tmp & AGPSTAT3_8X)) {
-			*cmd &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
-			*cmd |= AGPSTAT3_4X;
+		if (!(*vga_agpstat & AGPSTAT3_8X)) {
+			*bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
+			*bridge_agpstat |= AGPSTAT3_4X;
 			printk ("%s requested AGPx8 but graphic card not capable.\n", current->comm);
 			return;
 		}
 		/* All set, bridge & device can do AGP x8*/
-		*cmd &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD);
-		return;
+		*bridge_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD);
+		goto done;
 
 	} else {
 
@@ -505,71 +580,105 @@
 		 * If the hardware can't do x4, we're up shit creek, and never
 		 *  should have got this far.
 		 */
-		*cmd &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
-		if ((*cmd & AGPSTAT3_4X) && (*tmp & AGPSTAT3_4X))
-			*cmd |= AGPSTAT3_4X;
+		*bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
+		if ((*bridge_agpstat & AGPSTAT3_4X) && (*vga_agpstat & AGPSTAT3_4X))
+			*bridge_agpstat |= AGPSTAT3_4X;
 		else {
 			printk (KERN_INFO PFX "Badness. Don't know which AGP mode to set. "
-							"[cmd:%x tmp:%x fell back to:- cmd:%x tmp:%x]\n",
-							origcmd, origtmp, *cmd, *tmp);
-			if (!(*cmd & AGPSTAT3_4X))
+							"[bridge_agpstat:%x vga_agpstat:%x fell back to:- bridge_agpstat:%x vga_agpstat:%x]\n",
+							origbridge, origvga, *bridge_agpstat, *vga_agpstat);
+			if (!(*bridge_agpstat & AGPSTAT3_4X))
 				printk (KERN_INFO PFX "Bridge couldn't do AGP x4.\n");
-			if (!(*tmp & AGPSTAT3_4X))
+			if (!(*vga_agpstat & AGPSTAT3_4X))
 				printk (KERN_INFO PFX "Graphic card couldn't do AGP x4.\n");
+			return;
 		}
 	}
+
+done:
+	/* Apply any errata. */
+	if (agp_bridge->flags & AGP_ERRATA_FASTWRITES)
+		*bridge_agpstat &= ~AGPSTAT_FW;
+
+	if (agp_bridge->flags & AGP_ERRATA_SBA)
+		*bridge_agpstat &= ~AGPSTAT_SBA;
+
+	if (agp_bridge->flags & AGP_ERRATA_1X) {
+		*bridge_agpstat &= ~(AGPSTAT2_2X | AGPSTAT2_4X);
+		*bridge_agpstat |= AGPSTAT2_1X;
+	}
 }
 
-//FIXME: This doesn't smell right.
-//We need a function we pass an agp_device to.
-u32 agp_collect_device_status(u32 mode, u32 cmd)
+
+/**
+ * agp_collect_device_status - determine correct agp_cmd from various agp_stat's
+ * @bridge: an agp_bridge_data struct allocated for the AGP host bridge.
+ * @requested_mode: requested agp_stat from userspace (Typically from X)
+ * @bridge_agpstat: current agp_stat from AGP bridge.
+ *
+ * This function will hunt for an AGP graphics card, and try to match
+ * the requested mode to the capabilities of both the bridge and the card.
+ */
+u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 requested_mode, u32 bridge_agpstat)
 {
 	struct pci_dev *device = NULL;
-	u8 cap_ptr;
-	u32 tmp;
-	u32 agp3;
+	u8 cap_ptr = 0;
+	u32 vga_agpstat;
 
-	for_each_pci_dev(device) {
+	while (!cap_ptr) {
+		device = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, device);
+		if (!device) {
+			printk (KERN_INFO PFX "Couldn't find an AGP VGA controller.\n");
+			return 0;
+		}
 		cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP);
-		if (!cap_ptr)
+		if (!cap_ptr) {
+			pci_dev_put(device);
+			continue;
+		}
+		if ((device->bus->self->vendor != bridge->dev->vendor) &&
+			(device->bus->self->device != bridge->dev->device)) {
+			pci_dev_put(device);
+			cap_ptr = 0;
 			continue;
-
-		//FIXME: We should probably skip anything here that
-		// isn't an AGP graphic card.
-		/*
-		 * Ok, here we have a AGP device. Disable impossible
-		 * settings, and adjust the readqueue to the minimum.
-		 */
-		pci_read_config_dword(device, cap_ptr+PCI_AGP_STATUS, &tmp);
-
-		/* adjust RQ depth */
-		cmd = ((cmd & ~AGPSTAT_RQ_DEPTH) |
-		     min_t(u32, (mode & AGPSTAT_RQ_DEPTH),
-			 min_t(u32, (cmd & AGPSTAT_RQ_DEPTH), (tmp & AGPSTAT_RQ_DEPTH))));
-
-		/* disable FW if it's not supported */
-		if (!((cmd & AGPSTAT_FW) && (tmp & AGPSTAT_FW) && (mode & AGPSTAT_FW)))
-			cmd &= ~AGPSTAT_FW;
-
-		/* Check to see if we are operating in 3.0 mode */
-		pci_read_config_dword(device, cap_ptr+AGPSTAT, &agp3);
-		if (agp3 & AGPSTAT_MODE_3_0) {
-			agp_v3_parse_one(&mode, &cmd, &tmp);
-		} else {
-			agp_v2_parse_one(&mode, &cmd, &tmp);
 		}
 	}
-	return cmd;
+
+	/*
+	 * Ok, here we have a AGP device. Disable impossible
+	 * settings, and adjust the readqueue to the minimum.
+	 */
+	pci_read_config_dword(device, cap_ptr+PCI_AGP_STATUS, &vga_agpstat);
+
+	/* adjust RQ depth */
+	bridge_agpstat = ((bridge_agpstat & ~AGPSTAT_RQ_DEPTH) |
+	     min_t(u32, (requested_mode & AGPSTAT_RQ_DEPTH),
+		 min_t(u32, (bridge_agpstat & AGPSTAT_RQ_DEPTH), (vga_agpstat & AGPSTAT_RQ_DEPTH))));
+
+	/* disable FW if it's not supported */
+	if (!((bridge_agpstat & AGPSTAT_FW) &&
+		 (vga_agpstat & AGPSTAT_FW) &&
+		 (requested_mode & AGPSTAT_FW)))
+		bridge_agpstat &= ~AGPSTAT_FW;
+
+	/* Check to see if we are operating in 3.0 mode */
+	if (check_bridge_mode(agp_bridge->dev))
+		agp_v3_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat);
+	else
+		agp_v2_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat);
+
+	pci_dev_put(device);
+	return bridge_agpstat;
 }
 EXPORT_SYMBOL(agp_collect_device_status);
 
 
-void agp_device_command(u32 command, int agp_v3)
+void agp_device_command(u32 bridge_agpstat, int agp_v3)
 {
 	struct pci_dev *device = NULL;
 	int mode;
 
-	mode = command & 0x7;
+	mode = bridge_agpstat & 0x7;
 	if (agp_v3)
 		mode *= 4;
 
@@ -580,7 +689,7 @@
 
 		printk(KERN_INFO PFX "Putting AGP V%d device at %s into %dx mode\n",
 				agp_v3 ? 3 : 2, pci_name(device), mode);
-		pci_write_config_dword(device, agp + PCI_AGP_COMMAND, command);
+		pci_write_config_dword(device, agp + PCI_AGP_COMMAND, bridge_agpstat);
 	}
 }
 EXPORT_SYMBOL(agp_device_command);
@@ -601,10 +710,9 @@
 EXPORT_SYMBOL(get_agp_version);
 
 
-void agp_generic_enable(u32 mode)
+void agp_generic_enable(u32 requested_mode)
 {
-	u32 command, temp;
-	u32 agp3;
+	u32 bridge_agpstat, temp;
 
 	get_agp_version(agp_bridge);
 
@@ -614,26 +722,26 @@
 				agp_bridge->dev->slot_name);
 
 	pci_read_config_dword(agp_bridge->dev,
-		      agp_bridge->capndx + PCI_AGP_STATUS, &command);
+		      agp_bridge->capndx + PCI_AGP_STATUS, &bridge_agpstat);
 
-	command = agp_collect_device_status(mode, command);
-	command |= AGPSTAT_AGP_ENABLE;
+	bridge_agpstat = agp_collect_device_status(agp_bridge, requested_mode, bridge_agpstat);
+	if (bridge_agpstat == 0)
+		/* Something bad happened. FIXME: Return error code? */
+		return;
+
+	bridge_agpstat |= AGPSTAT_AGP_ENABLE;
 
 	/* Do AGP version specific frobbing. */
 	if(agp_bridge->major_version >= 3) {
-		pci_read_config_dword(agp_bridge->dev,
-			agp_bridge->capndx+AGPSTAT, &agp3);
-
-		/* Check to see if we are operating in 3.0 mode */
-		if (agp3 & AGPSTAT_MODE_3_0) {
+		if (check_bridge_mode(agp_bridge->dev)) {
 			/* If we have 3.5, we can do the isoch stuff. */
 			if (agp_bridge->minor_version >= 5)
 				agp_3_5_enable(agp_bridge);
-			agp_device_command(command, TRUE);
+			agp_device_command(bridge_agpstat, TRUE);
 			return;
 		} else {
 		    /* Disable calibration cycle in RX91<1> when not in AGP3.0 mode of operation.*/
-		    command &= ~(7<<10) ;
+		    bridge_agpstat &= ~(7<<10) ;
 		    pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, &temp);
 		    temp |= (1<<9);
 		    pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, temp);
@@ -644,7 +752,7 @@
 	}
 
 	/* AGP v<3 */
-	agp_device_command(command, FALSE);
+	agp_device_command(bridge_agpstat, FALSE);
 }
 EXPORT_SYMBOL(agp_generic_enable);
 
diff -Nru a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
--- a/drivers/char/agp/intel-agp.c	2005-02-03 18:04:22 -08:00
+++ b/drivers/char/agp/intel-agp.c	2005-02-03 18:04:22 -08:00
@@ -1806,6 +1806,8 @@
 
 static int __init agp_intel_init(void)
 {
+	if (agp_off)
+		return -EINVAL;
 	return pci_module_init(&agp_intel_pci_driver);
 }
 
diff -Nru a/drivers/char/agp/intel-mch-agp.c b/drivers/char/agp/intel-mch-agp.c
--- a/drivers/char/agp/intel-mch-agp.c	2005-02-03 18:04:22 -08:00
+++ b/drivers/char/agp/intel-mch-agp.c	2005-02-03 18:04:22 -08:00
@@ -622,6 +622,8 @@
 int __init agp_intelmch_init(void)
 {
 	static int agp_initialised=0;
+	if (agp_off)
+		return -EINVAL;
 
 	if (agp_initialised == 1)
 		return 0;