[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[patch] AGP 3.0 support, from FreeBSD
- To: tech_(_at_)_openbsd_(_dot_)_org
- Subject: [patch] AGP 3.0 support, from FreeBSD
- From: Dimitry Andric <dimitry_(_at_)_andric_(_dot_)_com>
- Date: Mon, 27 Feb 2006 20:45:09 +0100
- Cc: Matthieu Herrb <matthieu_(_dot_)_herrb_(_at_)_laas_(_dot_)_fr>
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