[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[patch] AGP 3.0 support, from FreeBSD



Hi all,

Here's a patch to port over the AGP 3.0 support from FreeBSD.  Since I
haven't got any spare AGP 2 or 3 hardware around to test with, it would
be nice to get some feedback.

For now, there's a debug printf that should tell you in dmesg which AGP
version (v2 or v3) and mode (1, 2, 4 or 8x) was used.  Of course,
you'll only get this when you start X.

Also, please note that this doesn't work (yet) for i810, since that
driver doesn't use agp_generic_enable().  It should work for the other
AGP chipsets, though.

Cheers,
Dimitry

Index: sys/dev/pci/agpvar.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/agpvar.h,v
retrieving revision 1.3
diff -u -d -p -r1.3 agpvar.h
--- sys/dev/pci/agpvar.h	25 Jul 2002 23:31:04 -0000	1.3
+++ sys/dev/pci/agpvar.h	27 Feb 2006 19:31:21 -0000
@@ -56,10 +56,7 @@ struct agp_memory_info {
 
 /* #define	AGP_DEBUG */
 #ifdef AGP_DEBUG
-#define AGP_DPF(x...) do {			\
-    printf("agp: ");				\
-    printf(##x);				\
-} while (0)
+#define AGP_DPF(fmt, arg...) printf("agp: " fmt ,##arg)
 #else
 #define AGP_DPF(x...) do {} while (0)
 #endif
Index: sys/dev/pci/vga_pci.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/vga_pci.c,v
retrieving revision 1.20
diff -u -d -p -r1.20 vga_pci.c
--- sys/dev/pci/vga_pci.c	19 Nov 2005 02:18:00 -0000	1.20
+++ sys/dev/pci/vga_pci.c	27 Feb 2006 19:31:21 -0000
@@ -551,23 +551,82 @@ agp_generic_detach(struct vga_pci_softc 
 	return 0;
 }
 
-int
-agp_generic_enable(struct vga_pci_softc *sc, u_int32_t mode)
+/*
+ * This does the enable logic for v3, with the same topology
+ * restrictions as in place for v2 -- one bus, one device on the bus.
+ */
+static int
+agp_v3_enable(struct vga_pci_softc *sc, u_int32_t mode, int capoff,
+   pcireg_t tstatus, pcireg_t mstatus)
 {
-	pcireg_t tstatus, mstatus;
-	pcireg_t command;
-	int rq, sba, fw, rate, capoff;
+	u_int32_t command;
+	int rq, sba, fw, rate, arqsz, cal;
+
+	/* Set RQ to the min of mode, tstatus and mstatus */
+	rq = AGP_MODE_GET_RQ(mode);
+	if (AGP_MODE_GET_RQ(tstatus) < rq)
+		rq = AGP_MODE_GET_RQ(tstatus);
+	if (AGP_MODE_GET_RQ(mstatus) < rq)
+		rq = AGP_MODE_GET_RQ(mstatus);
+
+	/*
+	 * ARQSZ - Set the value to the maximum one.
+	 * Don't allow the mode register to override values.
+	 */
+	arqsz = AGP_MODE_GET_ARQSZ(mode);
+	if (AGP_MODE_GET_ARQSZ(tstatus) > rq)
+		rq = AGP_MODE_GET_ARQSZ(tstatus);
+	if (AGP_MODE_GET_ARQSZ(mstatus) > rq)
+		rq = AGP_MODE_GET_ARQSZ(mstatus);
+
+	/* Calibration cycle - don't allow override by mode register */
+	cal = AGP_MODE_GET_CAL(tstatus);
+	if (AGP_MODE_GET_CAL(mstatus) < cal)
+		cal = AGP_MODE_GET_CAL(mstatus);
+
+	/* SBA must be supported for AGP v3. */
+	sba = 1;
+
+	/* Set FW if all three support it. */
+	fw = (AGP_MODE_GET_FW(tstatus)
+	    & AGP_MODE_GET_FW(mstatus)
+	    & AGP_MODE_GET_FW(mode));
 	
-	if (pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_AGP,
-	     &capoff, NULL) == 0) {
-		printf("agp_generic_enable: not an AGP capable device\n");
-		return -1;
-	}
+	/* Figure out the max rate */
+	rate = (AGP_MODE_GET_RATE(tstatus)
+	    & AGP_MODE_GET_RATE(mstatus)
+	    & AGP_MODE_GET_RATE(mode));
+	if (rate & AGP_MODE_V3_RATE_8x)
+		rate = AGP_MODE_V3_RATE_8x;
+	else
+		rate = AGP_MODE_V3_RATE_4x;
+	printf("Setting AGP v3 mode %d\n", rate * 4);
 
-	tstatus = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
-	    sc->sc_capoff + AGP_STATUS);
-	mstatus = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
-	    capoff + AGP_STATUS);
+	/* XXX: Not sure what this is good for? */
+	pci_conf_write(sc->sc_pc, sc->sc_pcitag,
+	    sc->sc_capoff + AGP_COMMAND, 0);
+
+	/* Construct the new mode word and tell the hardware */
+	command = AGP_MODE_SET_RQ(0, rq);
+	command = AGP_MODE_SET_ARQSZ(command, arqsz);
+	command = AGP_MODE_SET_CAL(command, cal);
+	command = AGP_MODE_SET_SBA(command, sba);
+	command = AGP_MODE_SET_FW(command, fw);
+	command = AGP_MODE_SET_RATE(command, rate);
+	command = AGP_MODE_SET_AGP(command, 1);
+	pci_conf_write(sc->sc_pc, sc->sc_pcitag,
+	    sc->sc_capoff + AGP_COMMAND, command);
+	pci_conf_write(sc->sc_pc, sc->sc_pcitag, capoff + AGP_COMMAND, command);
+
+	return (0);
+}
+
+static int
+agp_v2_enable(struct vga_pci_softc *sc, u_int32_t mode, int capoff,
+    pcireg_t tstatus, pcireg_t mstatus)
+{
+	u_int32_t command;
+	int rq, sba, fw, rate;
 
 	/* Set RQ to the min of mode, tstatus and mstatus */
 	rq = AGP_MODE_GET_RQ(mode);
@@ -578,26 +637,27 @@ agp_generic_enable(struct vga_pci_softc 
 
 	/* Set SBA if all three can deal with SBA */
 	sba = (AGP_MODE_GET_SBA(tstatus)
-	       & AGP_MODE_GET_SBA(mstatus)
-	       & AGP_MODE_GET_SBA(mode));
+	    & AGP_MODE_GET_SBA(mstatus)
+	    & AGP_MODE_GET_SBA(mode));
 
 	/* Similar for FW */
 	fw = (AGP_MODE_GET_FW(tstatus)
-	       & AGP_MODE_GET_FW(mstatus)
-	       & AGP_MODE_GET_FW(mode));
+	    & AGP_MODE_GET_FW(mstatus)
+	    & AGP_MODE_GET_FW(mode));
 
 	/* Figure out the max rate */
 	rate = (AGP_MODE_GET_RATE(tstatus)
-		& AGP_MODE_GET_RATE(mstatus)
-		& AGP_MODE_GET_RATE(mode));
-	if (rate & AGP_MODE_RATE_4x)
-		rate = AGP_MODE_RATE_4x;
-	else if (rate & AGP_MODE_RATE_2x)
-		rate = AGP_MODE_RATE_2x;
+	    & AGP_MODE_GET_RATE(mstatus)
+	    & AGP_MODE_GET_RATE(mode));
+	if (rate & AGP_MODE_V2_RATE_4x)
+		rate = AGP_MODE_V2_RATE_4x;
+	else if (rate & AGP_MODE_V2_RATE_2x)
+		rate = AGP_MODE_V2_RATE_2x;
 	else
-		rate = AGP_MODE_RATE_1x;
+		rate = AGP_MODE_V2_RATE_1x;
+	printf("Setting AGP v2 mode %d\n", rate);
 
-	/* Construct the new mode word and tell the hardware  */
+	/* Construct the new mode word and tell the hardware */
 	command = AGP_MODE_SET_RQ(0, rq);
 	command = AGP_MODE_SET_SBA(command, sba);
 	command = AGP_MODE_SET_FW(command, fw);
@@ -606,7 +666,39 @@ agp_generic_enable(struct vga_pci_softc 
 	pci_conf_write(sc->sc_pc, sc->sc_pcitag,
 	    sc->sc_capoff + AGP_COMMAND, command);
 	pci_conf_write(sc->sc_pc, sc->sc_pcitag, capoff + AGP_COMMAND, command);
-	return 0;
+
+	return (0);
+}
+
+int
+agp_generic_enable(struct vga_pci_softc *sc, u_int32_t mode)
+{
+	pcireg_t tstatus, mstatus;
+	int capoff;
+
+	if (pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_AGP,
+	    &capoff, NULL) == 0) {
+		printf("agp_generic_enable: not an AGP capable device\n");
+		return -1;
+	}
+
+	tstatus = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
+	    sc->sc_capoff + AGP_STATUS);
+	mstatus = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
+	    capoff + AGP_STATUS);
+
+	/*
+	 * Check display and bridge for AGP v3 support.  AGP v3 allows
+	 * more variety in topology than v2, e.g. multiple AGP devices
+	 * attached to one bridge, or multiple AGP bridges in one
+	 * system.  This doesn't attempt to address those situations,
+	 * but should work fine for a classic single AGP slot system
+	 * with AGP v3.
+	 */
+	if (AGP_MODE_GET_MODE_3(tstatus) && AGP_MODE_GET_MODE_3(mstatus))
+		return (agp_v3_enable(sc, mode, capoff, tstatus, mstatus));
+	else
+		return (agp_v2_enable(sc, mode, capoff, tstatus, mstatus));
 }
 
 struct agp_memory *
Index: sys/sys/agpio.h
===================================================================
RCS file: /cvs/src/sys/sys/agpio.h,v
retrieving revision 1.1
diff -u -d -p -r1.1 agpio.h
--- sys/sys/agpio.h	12 Jul 2002 20:17:03 -0000	1.1
+++ sys/sys/agpio.h	27 Feb 2006 19:31:24 -0000
@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$FreeBSD: src/sys/sys/agpio.h,v 1.1 2000/06/09 16:04:30 dfr Exp $
+ *	$FreeBSD: src/sys/sys/agpio.h,v 1.4 2003/10/23 18:08:56 jhb Exp $
  */
 
 #ifndef _SYS_AGPIO_H_
@@ -41,22 +41,43 @@
 
 /*
  * Macros to manipulate AGP mode words.
+ *
+ * SBA = Sideband Address Port
+ * FW  = Fast Writes
  */
 #define AGP_MODE_GET_RQ(x)		(((x) & 0xff000000U) >> 24)
+#define AGP_MODE_GET_ARQSZ(x)		(((x) & 0x0000e000U) >> 13)
+#define AGP_MODE_GET_CAL(x)		(((x) & 0x00001c00U) >> 10)
 #define AGP_MODE_GET_SBA(x)		(((x) & 0x00000200U) >> 9)
 #define AGP_MODE_GET_AGP(x)		(((x) & 0x00000100U) >> 8)
-#define AGP_MODE_GET_4G(x)		(((x) & 0x00000020U) >> 5)
+#define AGP_MODE_GET_GART_64(x)		(((x) & 0x00000080U) >> 7)
+#define AGP_MODE_GET_OVER_4G(x)		(((x) & 0x00000020U) >> 5)
 #define AGP_MODE_GET_FW(x)		(((x) & 0x00000010U) >> 4)
-#define AGP_MODE_GET_RATE(x)		((x) & 0x00000003U)
+#define AGP_MODE_GET_MODE_3(x)		(((x) & 0x00000008U) >> 3)
+#define AGP_MODE_GET_RATE(x)		((x) & 0x00000007U)
 #define AGP_MODE_SET_RQ(x,v)		(((x) & ~0xff000000U) | ((v) << 24))
+#define AGP_MODE_SET_ARQSZ(x,v)		(((x) & ~0x0000e000U) | ((v) << 13))
+#define AGP_MODE_SET_CAL(x,v)		(((x) & ~0x00001c00U) | ((v) << 10))
 #define AGP_MODE_SET_SBA(x,v)		(((x) & ~0x00000200U) | ((v) << 9))
 #define AGP_MODE_SET_AGP(x,v)		(((x) & ~0x00000100U) | ((v) << 8))
-#define AGP_MODE_SET_4G(x,v)		(((x) & ~0x00000020U) | ((v) << 5))
+#define AGP_MODE_SET_GART_64(x,v)	(((x) & ~0x00000080U) | ((v) << 7))
+#define AGP_MODE_SET_OVER_4G(x,v)	(((x) & ~0x00000020U) | ((v) << 5))
 #define AGP_MODE_SET_FW(x,v)		(((x) & ~0x00000010U) | ((v) << 4))
-#define AGP_MODE_SET_RATE(x,v)		(((x) & ~0x00000003U) | (v))
-#define AGP_MODE_RATE_1x		0x00000001
-#define AGP_MODE_RATE_2x		0x00000002
-#define AGP_MODE_RATE_4x		0x00000004
+#define AGP_MODE_SET_MODE_3(x,v)	(((x) & ~0x00000008U) | ((v) << 3))
+#define AGP_MODE_SET_RATE(x,v)		(((x) & ~0x00000007U) | (v))
+#define AGP_MODE_V2_RATE_1x		0x00000001
+#define AGP_MODE_V2_RATE_2x		0x00000002
+#define AGP_MODE_V2_RATE_4x		0x00000004
+#define AGP_MODE_V3_RATE_4x		0x00000001
+#define AGP_MODE_V3_RATE_8x		0x00000002
+#define AGP_MODE_V3_RATE_RSVD		0x00000004
+
+/* XXX: Compat */
+#define AGP_MODE_GET_4G(x)		AGP_MODE_GET_OVER_4G(x)
+#define AGP_MODE_SET_4G(x)		AGP_MODE_SET_OVER_4G(x)
+#define AGP_MODE_RATE_1x		AGP_MODE_V2_RATE_1x
+#define AGP_MODE_RATE_2x		AGP_MODE_V2_RATE_2x
+#define AGP_MODE_RATE_4x		AGP_MODE_V2_RATE_4x
 
 #define AGPIOC_BASE       'A'
 #define AGPIOC_INFO       _IOR (AGPIOC_BASE, 0, agp_info)



Visit your host, monkey.org