Subject: i915 integrated graphics
To: None <port-i386@netbsd.org>
From: ITOH Yasufumi <itohy@netbsd.org>
List: port-i386
Date: 12/23/2004 22:23:53
Hello,

Has anyone got X working on i915?
I'm trying to, but have only partial success.

kernel:	apply patch below (to NetBSD 2.0)
xsrc:	grab newer XFree86 source (I got XFree86-4.4.99.19) and use new
	xc/programs/Xserver/hw/xfree86/drivers/i810/*.[ch] files

By this change the "i810" driver should work for i915, but
  - the hardware cursor doesn't shown correctly (needs Option "SWCursor"),
  - the acceleration (xterm scroll) doesn't work correctly
    (needs Option "no_accel").

I have no clue to what is wrong.  The details of the graphic engine
seem secret.

Can anyone finish this work?

I'm not on this list.  Please Cc: me replies.

Thanks,
-- 
ITOH Yasufumi


diff -uF^[a-zA-Z_][a-z 	A-Z0-9_]*([^;]*$ sys/arch/i386/pci/pchb.c.orig sys/arch/i386/pci/pchb.c
--- sys/arch/i386/pci/pchb.c.orig	Tue Jul  6 14:47:40 2004
+++ sys/arch/i386/pci/pchb.c	Mon Dec 23 15:55:35 2004
@@ -279,6 +279,7 @@ pchbattach(struct device *parent, struct
 		case PCI_PRODUCT_INTEL_82845G_DRAM:
 		case PCI_PRODUCT_INTEL_82855GM_MCH:
 		case PCI_PRODUCT_INTEL_82865_HB:
+		case 0x2580/*XXX PCI_PRODUCT_INTEL_82915_HB*:
 			/*
 			 * The host bridge is either in GFX mode (internal
 			 * graphics) or in AGP mode. In GFX mode, we pretend
diff -uF^[a-zA-Z_][a-z 	A-Z0-9_]*([^;]*$ sys/arch/i386/pci/pci_intr_fixup.c.orig sys/arch/i386/pci/pci_intr_fixup.c
--- sys/arch/i386/pci/pci_intr_fixup.c.orig	Wed Apr 28 14:19:04 2004
+++ sys/arch/i386/pci/pci_intr_fixup.c	Wed Dec 23 15:03:33 2004
@@ -155,6 +155,8 @@
 	  ich_init },			/* ICH4M */
 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82801EB_LPC,
 	  ich_init },			/* ICH5 */
+	{ PCI_VENDOR_INTEL,	0x2640/*XXX PCI_PRODUCT_INTEL_82801FB_LPC*/,
+	  ich_init },			/* ICH6 */
 
 	{ PCI_VENDOR_OPTI,	PCI_PRODUCT_OPTI_82C558,
 	  opti82c558_init },
diff -uF^[a-zA-Z_][a-z 	A-Z0-9_]*([^;]*$ sys/arch/i386/pci/pchb_rnd.c.orig sys/arch/i386/pci/pchb_rnd.c
--- sys/arch/i386/pci/pchb_rnd.c.orig	Sun Jul  6 16:24:31 2003
+++ sys/arch/i386/pci/pchb_rnd.c	Thu Dec 23 12:50:30 2004
@@ -75,6 +75,7 @@ pchb_attach_rnd(struct pchb_softc *sc, s
 		case PCI_PRODUCT_INTEL_82860_HB:
 		case PCI_PRODUCT_INTEL_82865_HB:
 		case PCI_PRODUCT_INTEL_82875P_HB:
+		case 0x2580/*XXX PCI_PRODUCT_INTEL_82915_HB*/:
 			sc->sc_st = pa->pa_memt;
 			if (bus_space_map(sc->sc_st, I82802_IOBASE,
 			    I82802_IOSIZE, 0, &sc->sc_sh) != 0) {
diff -uF^[a-zA-Z_][a-z 	A-Z0-9_]*([^;]*$ sys/dev/pci/agp.c.orig sys/dev/pci/agp.c
--- sys/dev/pci/agp.c.orig	Fri Feb 13 20:36:22 2004
+++ sys/dev/pci/agp.c	Sun Dec 23 00:14:56 2004
@@ -161,6 +161,8 @@ CFATTACH_DECL(agp, sizeof(struct agp_sof
 	  NULL,			agp_i810_attach },
 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82865_HB,
 	  NULL,			agp_i810_attach },
+	{ PCI_VENDOR_INTEL,	0x2580/*XXX PCI_PRODUCT_INTEL_82915_HB*/,
+	  NULL,			agp_i810_attach },
 #endif
 
 #if NAGP_INTEL > 0
diff -uF^[a-zA-Z_][a-z 	A-Z0-9_]*([^;]*$ sys/dev/pci/agp_i810.c.orig sys/dev/pci/agp_i810.c
--- sys/dev/pci/agp_i810.c.orig	Fri Nov 12 15:04:32 2004
+++ sys/dev/pci/agp_i810.c	Mon Dec 23 13:48:51 2004
@@ -62,6 +62,7 @@
 #define CHIP_I810 0	/* i810/i815 */
 #define CHIP_I830 1	/* 830M/845G */
 #define CHIP_I855 2	/* 852GM/855GM/865G */
+#define CHIP_I915 3	/* 915G */
 
 struct agp_i810_softc {
 	u_int32_t initial_aperture;	/* aperture size at startup */
@@ -118,12 +119,30 @@ agp_i810_vgamatch(struct pci_attach_args
 	case PCI_PRODUCT_INTEL_82845G_IGD:
 	case PCI_PRODUCT_INTEL_82855GM_IGD:
 	case PCI_PRODUCT_INTEL_82865_IGD:
+	case 0x2582/*XXX PCI_PRODUCT_INTEL_82915_IGD*/:
 		return (1);
 	}
 
 	return (0);
 }
 
+static int
+agp_i915_map_aperture(struct pci_attach_args *pa, struct agp_softc *sc)
+{
+	/*
+	 * Find the aperture. Don't map it (yet), this would
+	 * eat KVA.
+	 */
+	if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, 0x18 /*XXX AGP_i915_GMADR*/,
+	    PCI_MAPREG_TYPE_MEM, &sc->as_apaddr, &sc->as_apsize,
+	    &sc->as_apflags) != 0)
+		return ENXIO;
+
+	sc->as_apt = pa->pa_memt;
+
+	return 0;
+}
+
 int
 agp_i810_attach(struct device *parent, struct device *self, void *aux)
 {
@@ -149,6 +168,7 @@ agp_i810_attach(struct device *parent, s
 		case PCI_PRODUCT_INTEL_82865_HB:
 		case PCI_PRODUCT_INTEL_82845G_DRAM:
 		case PCI_PRODUCT_INTEL_82815_FULL_HUB:
+		case 0x2580/*XXX PCI_PRODUCT_INTEL_82915_HB*/:
 			return agp_intel_attach(parent, self, aux);
 		}
 #endif
@@ -160,13 +180,6 @@ agp_i810_attach(struct device *parent, s
 	/* XXXfvdl */
 	sc->as_dmat = isc->vga_pa.pa_dmat;
 
-	error = agp_map_aperture(&isc->vga_pa, sc);
-	if (error != 0) {
-		aprint_error(": can't map aperture\n");
-		free(isc, M_AGP);
-		return error;
-	}
-
 	switch (PCI_PRODUCT(isc->vga_pa.pa_id)) {
 	case PCI_PRODUCT_INTEL_82810_GC:
 	case PCI_PRODUCT_INTEL_82810_DC100_GC:
@@ -182,9 +195,23 @@ agp_i810_attach(struct device *parent, s
 	case PCI_PRODUCT_INTEL_82865_IGD:
 		isc->chiptype = CHIP_I855;
 		break;
+	case 0x2582/*XXX PCI_PRODUCT_INTEL_82915_IGD*/:
+		isc->chiptype = CHIP_I915;
+		break;
 	}
 
-	error = pci_mapreg_map(&isc->vga_pa, AGP_I810_MMADR,
+	if (isc->chiptype == CHIP_I915)
+		error = agp_i915_map_aperture(&isc->vga_pa, sc);
+	else
+		error = agp_map_aperture(&isc->vga_pa, sc);
+	if (error != 0) {
+		aprint_error(": can't map aperture\n");
+		free(isc, M_AGP);
+		return error;
+	}
+
+	error = pci_mapreg_map(&isc->vga_pa,
+	    isc->chiptype == CHIP_I915 ? 0x10/*XXX AGP_I915_MMADR*/ : AGP_I810_MMADR,
 	    PCI_MAPREG_TYPE_MEM, 0, &isc->bst, &isc->bsh, NULL, NULL);
 	if (error != 0) {
 		aprint_error(": can't map mmadr registers\n");
@@ -261,6 +288,46 @@ agp_i810_attach(struct device *parent, s
 		WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
 
 		gatt->ag_physical = pgtblctl & ~1;
+#if 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(sc->as_pc, sc->as_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_8M:
+			isc->stolen = (8192 - 260) * 1024 / 4096;
+			break;
+		default:
+			isc->stolen = 0;
+			aprint_error(
+			    ": unknown memory configuration, disabling\n");
+			agp_generic_detach(sc);
+			return EINVAL;
+		}
+		if (isc->stolen > 0) {
+			aprint_error(": detected %dk stolen memory\n%s",
+			    isc->stolen * 4, sc->as_dev.dv_xname);
+		}
+		/* XXX ? */
+printf("\ngatt (cnf): %x\n", pci_conf_read(sc->as_pc, isc->vga_pa.pa_tag, 0x1C /*XXX AGP_I915_GTTADR*/));
+printf("gatt (reg): %x\n", READ4(AGP_I810_PGTBL_CTL));
+		/* GATT address is already in there, make sure it's enabled */
+		pgtblctl = READ4(AGP_I810_PGTBL_CTL);
+		pci_conf_write(sc->as_pc, isc->vga_pa.pa_tag, 0x1C /*XXX AGP_I915_GTTADR*/, pgtblctl);	/* ? needed? */
+		pgtblctl |= 1;
+		WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
+
+		gatt->ag_physical = pgtblctl & ~1;
+printf("gatt (cnf): %x\n", pci_conf_read(sc->as_pc, isc->vga_pa.pa_tag, 0x1C /*XXX AGP_I915_GTTADR*/));
+printf("gatt (reg): %x\n", READ4(AGP_I810_PGTBL_CTL));
+#endif
 	} else {	/* CHIP_I855 */
 		/* The 855GM automatically initializes the 128k gatt on boot. */
 		pcireg_t reg;
@@ -372,6 +439,12 @@ agp_i810_get_aperture(struct agp_softc *
 			return 64 * 1024 * 1024;
 		else
 			return 128 * 1024 * 1024;
+	} if (isc->chiptype == CHIP_I915) {
+		reg = pci_conf_read(sc->as_pc, isc->vga_pa.pa_tag, 0x62 /*XXX AGP_I915_MSAC*/);
+		if (reg & 0x02 /*XXX 256MB Aperture Disable */)
+			return 128 * 1024 * 1024;
+		else
+			return 256 * 1024 * 1024;
 	} else {	/* CHIP_I855 */
 		return 128 * 1024 * 1024;
 	}
@@ -427,6 +500,13 @@ agp_i810_set_aperture(struct agp_softc *
 		reg &= 0x0000ffff;
 		reg |= ((pcireg_t)gcc1) << 16;
 		pci_conf_write(sc->as_pc, sc->as_tag, AGP_I830_GCC0, reg);
+	} if (isc->chiptype == CHIP_I915) {
+		/* only BIOS can set the size */
+		if (aperture != agp_i810_get_aperture(sc)) {
+			printf("%s: bad aperture size %d\n",
+			    sc->as_dev.dv_xname, aperture);
+			return EINVAL;
+		}
 	} else {	/* CHIP_I855 */
 		if (aperture != 128 * 1024 * 1024) {
 			printf("%s: bad aperture size %d\n",
@@ -452,7 +532,7 @@ agp_i810_bind_page(struct agp_softc *sc,
 		return EINVAL;
 	}
 
-	if (isc->chiptype != CHIP_I830) {
+	if (isc->chiptype != CHIP_I830 && isc->chiptype != CHIP_I915) {
 		if ((offset >> AGP_PAGE_SHIFT) < isc->stolen) {
 #ifdef DEBUG
 			printf("%s: trying to bind into stolen memory",
@@ -528,6 +608,7 @@ agp_i810_alloc_memory(struct agp_softc *
 		/*
 		 * Bogus mapping of a single page for the hardware cursor.
 		 */
+		if (isc->chiptype != CHIP_I915)	/* XXX? */
 		if (size != AGP_PAGE_SIZE)
 			return 0;
 	}