Subject: Attempt to resolve agp_i810 vs i915_drv
To: None <tech-kern@netbsd.org>
From: Yorick Hardy <yhardy@uj.ac.za>
List: tech-kern
Date: 10/08/2007 09:50:35
This is a multi-part message in MIME format.
--------------080702070007040304010003
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

When drm was introduced we had the problem that agp_i810.c
and i915_drv.c both need access to the same memory region.

 http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/dev/pci/agp_i810.c.diff?r1=1.36&r2=1.37
 http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/dev/pci/agp_i810.c.diff?r1=1.39&r2=1.40

I have attached a patch which attempts to resolve the problem.

I assumed, for simplicity, that the bus space tag need not be returned
by AGP_GET_PCIMAP, since i915_drv can get the tag when attaching.

Another assumption is that the other agp drivers need not implement
get_pcimap unless there is a known conflict.

Would it be better to use AGP_GET_PCIMAP in drm_ioremap?
(sys/dev/drm/drm_memory.h)

Is this an acceptable solution?

I would appreciate any comments.

-- 
Kind regards,

Yorick Hardy

--------------080702070007040304010003
Content-Type: text/plain;
 name="drm.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="drm.patch"

--- sys/dev/drm/drm_drv.c.orig	2007-10-07 13:28:17.000000000 +0200
+++ sys/dev/drm/drm_drv.c	2007-10-07 13:32:54.000000000 +0200
@@ -526,7 +526,7 @@
 	}
 
 	for(i = 0; i<DRM_MAX_PCI_RESOURCE; i++) {
-		if (dev->pci_map_data[i].mapped > 1) {
+		if (dev->pci_map_data[i].mapped > 0) {
 			bus_space_unmap(dev->pci_map_data[i].maptype,
 					dev->pci_map_data[i].bsh,
 					dev->pci_map_data[i].size);
@@ -691,7 +691,7 @@
 	i = 0;
 
 	for (i = 0; i < DRM_MAX_PCI_RESOURCE; i++)
-		if (dev->pci_map_data[i].mapped != 0)
+		if (dev->pci_map_data[i].mapped > 0)
 		{
 			bus_space_unmap(dev->pa.pa_memt,
 					dev->pci_map_data[i].bsh,
--- sys/dev/drm/drm_memory.c.orig	2007-10-07 13:28:05.000000000 +0200
+++ sys/dev/drm/drm_memory.c	2007-10-07 13:38:35.000000000 +0200
@@ -97,8 +97,9 @@
 			map->bst = dev->pa.pa_memt;
 			map->cnt = &(dev->pci_map_data[i].mapped);
 			map->mapsize = dev->pci_map_data[i].size;
-			dev->pci_map_data[i].mapped++;
-			if (dev->pci_map_data[i].mapped > 1)
+			if (dev->pci_map_data[i].mapped >= 0)
+				dev->pci_map_data[i].mapped++;
+			if (dev->pci_map_data[i].mapped != 1)
 			{
 				map->bsh = dev->pci_map_data[i].bsh;
 				return dev->pci_map_data[i].vaddr;
--- sys/dev/pci/drm/i915_drv.c.orig	2007-10-07 15:48:45.000000000 +0200
+++ sys/dev/pci/drm/i915_drv.c	2007-10-07 18:07:43.000000000 +0200
@@ -36,6 +36,7 @@
 
 #include <dev/drm/drmP.h>
 #include <dev/drm/drm.h>
+#include <dev/pci/agpvar.h>
 #include "i915_drm.h"
 #include "i915_drv.h"
 #include "drm_pciids.h"
@@ -133,10 +134,27 @@
 {
 	struct pci_attach_args *pa = aux;
 	drm_device_t *dev = (drm_device_t *)self;
+	struct agp_softc *agpsc;
 
 	i915_configure(dev);
 
 	drm_attach(self, pa, i915_pciidlist);
+
+	agpsc = (struct agp_softc *)agp_find_device(0);
+
+	if(agpsc == NULL || agpsc->as_chipc == NULL)
+		return;
+
+        /*
+	 * AGP_I915_MMADR might be in use by agp_i810.c 
+         * AGP_I915_MMADR is 0x10 (register 0)
+	 */
+	if(AGP_GET_PCIMAP(agpsc, 0x10, &dev->pci_map_data[0].bsh)) {
+		dev->pci_map_data[0].mapped = -1; /* never unmap */
+		dev->pci_map_data[0].vaddr =
+			bus_space_vaddr(dev->pa.pa_memt,
+					dev->pci_map_data[0].bsh);
+	}
 }
 
 CFATTACH_DECL(i915drm, sizeof(drm_device_t), i915drm_probe, i915drm_attach,
--- sys/dev/pci/agpvar.h.orig	2007-10-07 16:38:28.000000000 +0200
+++ sys/dev/pci/agpvar.h	2007-10-07 16:49:28.000000000 +0200
@@ -111,6 +111,7 @@
 	int (*free_memory)(struct agp_softc *, struct agp_memory *);
 	int (*bind_memory)(struct agp_softc *, struct agp_memory *, off_t);
 	int (*unbind_memory)(struct agp_softc *, struct agp_memory *);
+	int (*get_pcimap)(struct agp_softc *, int, bus_space_handle_t *);
 };
 
 #define AGP_GET_APERTURE(sc)	 ((sc)->as_methods->get_aperture(sc))
@@ -123,6 +124,7 @@
 #define AGP_FREE_MEMORY(sc,m)	 ((sc)->as_methods->free_memory((sc),(m)))
 #define AGP_BIND_MEMORY(sc,m,o)	 ((sc)->as_methods->bind_memory((sc),(m),(o)))
 #define AGP_UNBIND_MEMORY(sc,m)	 ((sc)->as_methods->unbind_memory((sc),(m)))
+#define AGP_GET_PCIMAP(sc,r,h)	 ((sc)->as_methods->get_pcimap((sc),(r),(h)))
 
 /*
  * All chipset drivers must have this at the start of their softc.
@@ -178,6 +180,7 @@
 int agp_generic_free_memory(struct agp_softc *, struct agp_memory *);
 int agp_generic_bind_memory(struct agp_softc *, struct agp_memory *, off_t);
 int agp_generic_unbind_memory(struct agp_softc *, struct agp_memory *);
+int agp_generic_get_pcimap(struct agp_softc *, int, bus_space_handle_t *);
 
 /* The vendor has already been matched when these functions are called */
 int agp_amd_match(const struct pci_attach_args *);
--- sys/dev/pci/agp.c.orig	2007-10-07 16:48:07.000000000 +0200
+++ sys/dev/pci/agp.c	2007-10-07 16:52:10.000000000 +0200
@@ -685,6 +685,13 @@
 	return 0;
 }
 
+int
+agp_generic_get_pcimap(struct agp_softc *sc, int reg, bus_space_handle_t *h)
+{
+	printf("%s: get_pcimap not implemented\n", sc->as_dev.dv_xname);
+	return 0;
+}
+
 /* Helper functions for implementing user/kernel api */
 
 static int
--- sys/dev/pci/agp_ali.c.orig	2007-10-07 16:54:19.000000000 +0200
+++ sys/dev/pci/agp_ali.c	2007-10-07 16:54:39.000000000 +0200
@@ -74,6 +74,7 @@
 	agp_generic_free_memory,
 	agp_generic_bind_memory,
 	agp_generic_unbind_memory,
+	agp_generic_get_pcimap,
 };
 
 int
--- sys/dev/pci/agp_amd.c.orig	2007-10-07 16:54:45.000000000 +0200
+++ sys/dev/pci/agp_amd.c	2007-10-07 16:54:55.000000000 +0200
@@ -92,6 +92,7 @@
 	agp_generic_free_memory,
 	agp_generic_bind_memory,
 	agp_generic_unbind_memory,
+	agp_generic_get_pcimap,
 };
 
 
--- sys/dev/pci/agp_amd64.c.orig	2007-10-07 16:54:56.000000000 +0200
+++ sys/dev/pci/agp_amd64.c	2007-10-07 16:55:04.000000000 +0200
@@ -98,6 +98,7 @@
 	agp_generic_free_memory,
 	agp_generic_bind_memory,
 	agp_generic_unbind_memory,
+	agp_generic_get_pcimap,
 };
 
 
--- sys/dev/pci/agp_apple.c.orig	2007-10-07 16:55:07.000000000 +0200
+++ sys/dev/pci/agp_apple.c	2007-10-07 16:55:15.000000000 +0200
@@ -67,6 +67,7 @@
 	agp_generic_free_memory,
 	agp_generic_bind_memory,
 	agp_generic_unbind_memory,
+	agp_generic_get_pcimap,
 };
 
 struct agp_apple_softc {
--- sys/dev/pci/agp_i810.c.orig	2007-10-07 16:55:17.000000000 +0200
+++ sys/dev/pci/agp_i810.c	2007-10-07 18:56:54.000000000 +0200
@@ -109,6 +109,7 @@
 static int agp_i810_free_memory(struct agp_softc *, struct agp_memory *);
 static int agp_i810_bind_memory(struct agp_softc *, struct agp_memory *, off_t);
 static int agp_i810_unbind_memory(struct agp_softc *, struct agp_memory *);
+static int agp_i810_get_pcimap(struct agp_softc *, int , bus_space_handle_t *);
 static void agp_i810_powerhook(int, void *);
 
 static struct agp_methods agp_i810_methods = {
@@ -122,6 +123,7 @@
 	agp_i810_free_memory,
 	agp_i810_bind_memory,
 	agp_i810_unbind_memory,
+	agp_i810_get_pcimap,
 };
 
 /* XXXthorpej -- duplicated code (see arch/i386/pci/pchb.c) */
@@ -441,14 +443,6 @@
 		printf("%s: WARNING: unable to establish PCI power hook\n",
 		    sc->as_dev.dv_xname);
 
-#if 0
-	/*      
-	 * another device (drm) may need access to this region
-	 * we do not need it anymore
-	 */     
-	bus_space_unmap(isc->bst, isc->bsh, mmadrsize);
-#endif
-
 	return 0;
 }
 
@@ -767,7 +761,6 @@
 	 * Until the issue is solved, simply restore it.
 	 */
 
-#if 0
 	regval = bus_space_read_4(isc->bst, isc->bsh, AGP_I810_PGTBL_CTL);
 	if (regval != (isc->gatt->ag_physical | 1)) {
 		printf("agp_i810_bind_memory: PGTBL_CTL is 0x%x - fixing\n",
@@ -775,8 +768,6 @@
 		bus_space_write_4(isc->bst, isc->bsh, AGP_I810_PGTBL_CTL,
 				  isc->gatt->ag_physical | 1);
 	}
-#endif
-	regval = 0;
 
 	if (mem->am_type == 2) {
 		WRITEGTT(offset, mem->am_physical | 1);
@@ -822,6 +813,23 @@
 	return 0;
 }
 
+static int
+agp_i810_get_pcimap(struct agp_softc *sc, int reg, bus_space_handle_t *bh)
+{
+	struct agp_i810_softc *isc = sc->as_chipc;
+	if((reg == AGP_I810_MMADR && isc->chiptype == CHIP_I810) ||
+	   (reg == AGP_I915_MMADR && isc->chiptype == CHIP_I915) ||
+	   (reg == AGP_I965_MMADR && isc->chiptype == CHIP_I965)) {
+		*bh = isc->bsh;
+		return 1;
+	}
+	if(reg == AGP_I915_GTTADR && isc->chiptype == CHIP_I915) {
+		*bh = isc->gtt_bsh; /* should this be allowed? */
+		return 1;
+	}
+	return 0;
+}
+
 static void
 agp_i810_powerhook(int why, void *arg)
 {
--- sys/dev/pci/agp_intel.c.orig	2007-10-07 16:55:27.000000000 +0200
+++ sys/dev/pci/agp_intel.c	2007-10-07 16:55:38.000000000 +0200
@@ -86,6 +86,7 @@
 	agp_generic_free_memory,
 	agp_generic_bind_memory,
 	agp_generic_unbind_memory,
+	agp_generic_get_pcimap,
 };
 
 static int
--- sys/dev/pci/agp_sis.c.orig	2007-10-07 16:55:39.000000000 +0200
+++ sys/dev/pci/agp_sis.c	2007-10-07 16:55:47.000000000 +0200
@@ -72,6 +72,7 @@
 	agp_generic_free_memory,
 	agp_generic_bind_memory,
 	agp_generic_unbind_memory,
+	agp_generic_get_pcimap,
 };
 
 int
--- sys/dev/pci/agp_via.c.orig	2007-10-07 16:55:48.000000000 +0200
+++ sys/dev/pci/agp_via.c	2007-10-07 16:55:58.000000000 +0200
@@ -68,6 +68,7 @@
 	agp_generic_free_memory,
 	agp_generic_bind_memory,
 	agp_generic_unbind_memory,
+	agp_generic_get_pcimap,
 };
 
 struct agp_via_softc {

--------------080702070007040304010003--