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

Revised patch for adding i915 AGP support



I heard that my previous patch to add AGP support for the Intel i915
chipset seems to fail on some i810 hardware.  Since I didn't get any
reports with details, I can only guess what the cause is.

Anyway, I've rearranged the patch so that it should have absolutely NO
effects, unless you are specifically using a i915 chip.  For all other
chips, the complete execution path is unchanged.

Please test this out on your i810 and/or i915 hardware, and let me know
if (and WHY) it fails!

Cheers,
Dimitry

Index: sys/arch/i386/pci/agp_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/pci/agp_machdep.c,v
retrieving revision 1.5
diff -u -d -r1.5 agp_machdep.c
--- sys/arch/i386/pci/agp_machdep.c	3 Feb 2006 19:24:42 -0000	1.5
+++ sys/arch/i386/pci/agp_machdep.c	10 Feb 2006 16:00:16 -0000
@@ -47,6 +47,8 @@
 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82845G_IGD, agp_i810_attach },
 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82852GM_AGP, agp_i810_attach },
 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82865_IGD, agp_i810_attach },
+	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82915G_IV, agp_i810_attach },
+	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82915GM_IGD, agp_i810_attach },
 	{ PCI_VENDOR_INTEL, -1, agp_intel_attach },
 	{ PCI_VENDOR_SIS, -1, agp_sis_attach },
 	{ PCI_VENDOR_VIATECH, -1, agp_via_attach },
Index: sys/dev/pci/agp_i810.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/agp_i810.c,v
retrieving revision 1.10
diff -u -d -r1.10 agp_i810.c
--- sys/dev/pci/agp_i810.c	3 Feb 2006 19:24:42 -0000	1.10
+++ sys/dev/pci/agp_i810.c	10 Feb 2006 16:00:22 -0000
@@ -53,10 +53,22 @@
 #define READ1(off)	bus_space_read_1(isc->bst, isc->bsh, off)
 #define READ4(off)	bus_space_read_4(isc->bst, isc->bsh, off)
 #define WRITE4(off,v)	bus_space_write_4(isc->bst, isc->bsh, off, v)
+#define WRITEGTT(off,v)	bus_space_write_4(isc->gtt_bst, isc->gtt_bsh, off, v)
 
 #define CHIP_I810 0	/* i810/i815 */
 #define CHIP_I830 1	/* i830/i845 */
 #define CHIP_I855 2	/* i852GM/i855GM/i865G */
+#define CHIP_I915 3	/* i915G/i915GM */
+
+#define WRITE_GATT(off,v)						   \
+	do {								   \
+		if (isc->chiptype == CHIP_I915)				   \
+			WRITEGTT((u_int32_t)((off) >> AGP_PAGE_SHIFT) * 4, \
+			    v);						   \
+		else							   \
+			WRITE4(AGP_I810_GTT +				   \
+			    (u_int32_t)((off) >> AGP_PAGE_SHIFT) * 4, v);  \
+	} while (0)
 
 struct agp_i810_softc {
 	struct agp_gatt *gatt;
@@ -66,6 +78,8 @@
 					   for stolen memory */
 	bus_space_tag_t bst;		/* bus_space tag */
 	bus_space_handle_t bsh;		/* bus_space handle */
+	bus_space_tag_t gtt_bst;	/* GATT bus_space tag */
+	bus_space_handle_t gtt_bsh;	/* GATT bus_space handle */
 	struct pci_attach_args bridge_pa;
 };
 
@@ -134,15 +148,30 @@
 	case PCI_PRODUCT_INTEL_82865_IGD:
 		isc->chiptype = CHIP_I855;
 		break;
+	case PCI_PRODUCT_INTEL_82915G_IV:
+	case PCI_PRODUCT_INTEL_82915GM_IGD:
+		isc->chiptype = CHIP_I915;
+		break;
 	}
 
-	error = pci_mapreg_map(pa, AGP_I810_MMADR,
+	error = pci_mapreg_map(pa,
+	    (isc->chiptype == CHIP_I915) ? AGP_I915_MMADR : AGP_I810_MMADR,
 	    PCI_MAPREG_TYPE_MEM, 0, &isc->bst, &isc->bsh, NULL, NULL, 0);
 	if (error != 0) {
 		printf(": can't map mmadr registers\n");
 		return (error);
 	}
 
+	if (isc->chiptype == CHIP_I915) {
+		error = pci_mapreg_map(pa, AGP_I915_GTTADR, PCI_MAPREG_TYPE_MEM,
+		    0, &isc->gtt_bst, &isc->gtt_bsh, NULL, NULL, 0);
+		if (error != 0) {
+			printf(": can't map gatt registers\n");
+			agp_generic_detach(sc);
+			return (error);
+		}
+	}
+
 	gatt = malloc(sizeof(struct agp_gatt), M_DEVBUF, M_NOWAIT);
 	if (!gatt) {
  		agp_generic_detach(sc);
@@ -214,6 +243,57 @@
 		WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
 
 		gatt->ag_physical = pgtblctl & ~1;
+	} else if (isc->chiptype == CHIP_I915) {
+		/* The 915G automatically initializes the 256k gatt on boot. */
+		pcireg_t reg;
+		u_int32_t pgtblctl;
+		u_int16_t gcc1;
+
+		reg = pci_conf_read(isc->bridge_pa.pa_pc,
+		    isc->bridge_pa.pa_tag, AGP_I855_GCC1);
+		gcc1 = (u_int16_t)(reg >> 16);
+		switch (gcc1 & AGP_I855_GCC1_GMS) {
+		case AGP_I855_GCC1_GMS_STOLEN_1M:
+			isc->stolen = (1024 - 260) * 1024 / 4096;
+			break;
+		case AGP_I855_GCC1_GMS_STOLEN_4M:
+			isc->stolen = (4096 - 260) * 1024 / 4096;
+			break;
+		case AGP_I855_GCC1_GMS_STOLEN_8M:
+			isc->stolen = (8192 - 260) * 1024 / 4096;
+			break;
+		case AGP_I855_GCC1_GMS_STOLEN_16M:
+			isc->stolen = (16384 - 260) * 1024 / 4096;
+			break;
+		case AGP_I855_GCC1_GMS_STOLEN_32M:
+			isc->stolen = (32768 - 260) * 1024 / 4096;
+			break;
+		case AGP_I915_GCC1_GMS_STOLEN_48M:
+			isc->stolen = (49152 - 260) * 1024 / 4096;
+			break;
+		case AGP_I915_GCC1_GMS_STOLEN_64M:
+			isc->stolen = (65536 - 260) * 1024 / 4096;
+			break;
+		default:
+			isc->stolen = 0;
+			printf(
+			    ": unknown memory configuration, disabling\n");
+			agp_generic_detach(sc);
+			return (EINVAL);
+		}
+#ifdef DEBUG
+		if (isc->stolen > 0) {
+			printf(": detected %dk stolen memory",
+			    isc->stolen * 4);
+		}
+#endif
+
+		/* GATT address is already in there, make sure it's enabled */
+		pgtblctl = READ4(AGP_I810_PGTBL_CTL);
+		pgtblctl |= 1;
+		WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
+
+		gatt->ag_physical = pgtblctl & ~1;
 	} else {	/* CHIP_I855 */
 		/* The 855GM automatically initializes the 128k gatt on boot. */
 		pcireg_t reg;
@@ -296,6 +376,14 @@
 			return (64 * 1024 * 1024);
 		else
 			return (128 * 1024 * 1024);
+	} else if (isc->chiptype == CHIP_I915) {
+		reg = pci_conf_read(isc->bridge_pa.pa_pc,
+		    isc->bridge_pa.pa_tag, AGP_I915_MSAC);
+		if ((reg & AGP_I915_MSAC_GMASIZE) == AGP_I915_MSAC_GMASIZE_128) {
+			return (128 * 1024 * 1024);
+		} else {
+			return (256 * 1024 * 1024);
+		}
 	} else {	/* CHIP_I855 */
 		return (128 * 1024 * 1024);
 	}
@@ -353,6 +441,21 @@
 		reg |= ((pcireg_t)gcc1) << 16;
 		pci_conf_write(isc->bridge_pa.pa_pc,
 		    isc->bridge_pa.pa_tag, AGP_I830_GCC0, reg);
+	} else if (isc->chiptype == CHIP_I915) {
+		if (aperture != (128 * 1024 * 1024) &&
+		    aperture != (256 * 1024 * 1024)) {
+			printf("agp: bad aperture size %d\n", aperture);
+			return (EINVAL);
+		}
+		reg = pci_conf_read(isc->bridge_pa.pa_pc,
+		    isc->bridge_pa.pa_tag, AGP_I915_MSAC);
+		reg &= ~AGP_I915_MSAC_GMASIZE;
+		if (aperture == (128 * 1024 * 1024))
+			reg |= AGP_I915_MSAC_GMASIZE_128;
+		else
+			reg |= AGP_I915_MSAC_GMASIZE_256;
+		pci_conf_write(isc->bridge_pa.pa_pc,
+		    isc->bridge_pa.pa_tag, AGP_I915_MSAC, reg);
 	} else {	/* CHIP_I855 */
 		if (aperture != (128 * 1024 * 1024)) {
 			printf("agp: bad aperture size %d\n", aperture);
@@ -386,8 +489,7 @@
 		}
 	}
 
-	WRITE4(AGP_I810_GTT + (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4,
-	    physical | 1);
+	WRITE_GATT(offset, physical | 1);
 	return (0);
 }
 
@@ -408,7 +510,7 @@
 		}
 	}
 
-	WRITE4(AGP_I810_GTT + (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4, 0);
+	WRITE_GATT(offset, 0);
 	return (0);
 }
 
@@ -449,10 +551,12 @@
 			return (NULL);
 	} else if (type == 2) {
 		/*
-		 * Bogus mapping of a single page for the hardware cursor.
+		 * Bogus mapping of 1 or 4 pages for the hardware cursor.
 		 */
-		if (size != AGP_PAGE_SIZE)
+		if (size != AGP_PAGE_SIZE && size != 4 * AGP_PAGE_SIZE) {
+			printf("agp: trying to map %lu for hw cursor\n", size);
 			return (NULL);
+		}
 	}
 
 	mem = malloc(sizeof *mem, M_DEVBUF, M_WAITOK);
@@ -538,8 +642,7 @@
 	}
 
 	if (mem->am_type == 2) {
-		WRITE4(AGP_I810_GTT + (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4,
-		    mem->am_physical | 1);
+		WRITE_GATT(offset, mem->am_physical | 1);
 		mem->am_offset = offset;
 		mem->am_is_bound = 1;
 		return (0);
@@ -566,8 +669,7 @@
 	u_int32_t i;
 
 	if (mem->am_type == 2) {
-		WRITE4(AGP_I810_GTT +
-		    (u_int32_t)(mem->am_offset >> AGP_PAGE_SHIFT) * 4, 0);
+		WRITE_GATT(mem->am_offset, 0);
 		mem->am_offset = 0;
 		mem->am_is_bound = 0;
 		return (0);
Index: sys/dev/pci/agpreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/agpreg.h,v
retrieving revision 1.5
diff -u -d -r1.5 agpreg.h
--- sys/dev/pci/agpreg.h	3 Feb 2006 19:24:42 -0000	1.5
+++ sys/dev/pci/agpreg.h	10 Feb 2006 16:00:22 -0000
@@ -186,4 +186,21 @@
 #define AGP_I855_GCC1_GMS_STOLEN_16M	0x40
 #define AGP_I855_GCC1_GMS_STOLEN_32M	0x50
 
+/*
+ * 915G registers
+ */
+#define AGP_I915_GMADR			0x18
+#define AGP_I915_MMADR			0x10
+#define AGP_I915_GTTADR			0x1C
+#define AGP_I915_GCC1_GMS_STOLEN_48M	0x60
+#define AGP_I915_GCC1_GMS_STOLEN_64M	0x70
+#define AGP_I915_DEVEN			0x54
+#define AGP_I915_DEVEN_D2F0		0x08
+#define AGP_I915_DEVEN_D2F0_ENABLED	0x08
+#define AGP_I915_DEVEN_D2F0_DISABLED	0x00
+#define AGP_I915_MSAC			0x62
+#define AGP_I915_MSAC_GMASIZE		0x02
+#define AGP_I915_MSAC_GMASIZE_128	0x02
+#define AGP_I915_MSAC_GMASIZE_256	0x00
+
 #endif /* !_PCI_AGPREG_H_ */



Visit your host, monkey.org