Module Name:    src
Committed By:   riastradh
Date:           Tue May 27 03:17:33 UTC 2014

Modified Files:
        src/sys/dev/pci: agp_i810.c agp_i810var.h

Log Message:
Rework agp_i810 attachment code a little.

- Fix up error branches in agp_i810_attach.

- Use a separate bus space handle for the GTT, whether it is in a
separate BAR or a subregion of the MMIO device registers, so that

(a) agp_i810_write_gtt_entry and agp_i810_post_gtt_entry are easier to
follow, and

(b) we can map the GTT prefetchable eventually.


To generate a diff of this commit:
cvs rdiff -u -r1.78 -r1.79 src/sys/dev/pci/agp_i810.c
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/pci/agp_i810var.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/agp_i810.c
diff -u src/sys/dev/pci/agp_i810.c:1.78 src/sys/dev/pci/agp_i810.c:1.79
--- src/sys/dev/pci/agp_i810.c:1.78	Mon May 26 19:15:39 2014
+++ src/sys/dev/pci/agp_i810.c	Tue May 27 03:17:33 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: agp_i810.c,v 1.78 2014/05/26 19:15:39 riastradh Exp $	*/
+/*	$NetBSD: agp_i810.c,v 1.79 2014/05/27 03:17:33 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2000 Doug Rabson
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: agp_i810.c,v 1.78 2014/05/26 19:15:39 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: agp_i810.c,v 1.79 2014/05/27 03:17:33 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -88,6 +88,7 @@ static bool agp_i810_resume(device_t, co
 static int agp_i810_init(struct agp_softc *);
 
 static int agp_i810_setup_chipset_flush_page(struct agp_softc *);
+static void agp_i810_teardown_chipset_flush_page(struct agp_softc *);
 static int agp_i810_init(struct agp_softc *);
 
 static struct agp_methods agp_i810_methods = {
@@ -107,7 +108,6 @@ int
 agp_i810_write_gtt_entry(struct agp_i810_softc *isc, off_t off, bus_addr_t v)
 {
 	u_int32_t pte;
-	bus_size_t base_off, wroff;
 
 	/* Bits 11:4 (physical start address extension) should be zero. */
 	if ((v & 0xff0) != 0)
@@ -132,58 +132,18 @@ agp_i810_write_gtt_entry(struct agp_i810
 		}
 	}
 
-	base_off = 0;
-	wroff = (off >> AGP_PAGE_SHIFT) * 4;
+	bus_space_write_4(isc->gtt_bst, isc->gtt_bsh,
+	    4*(off >> AGP_PAGE_SHIFT), pte);
 
-	switch (isc->chiptype) {
-	case CHIP_I810:
-	case CHIP_I830:
-	case CHIP_I855:
-		base_off = AGP_I810_GTT;
-		break;
-	case CHIP_I965:
-		base_off = AGP_I965_GTT;
-		break;
-	case CHIP_G4X:
-		base_off = AGP_G4X_GTT;
-		break;
-	case CHIP_I915:
-	case CHIP_G33:
-		bus_space_write_4(isc->gtt_bst, isc->gtt_bsh, wroff, pte);
-		return 0;
-	}
-
-	WRITE4(base_off + wroff, pte);
 	return 0;
 }
 
 void
 agp_i810_post_gtt_entry(struct agp_i810_softc *isc, off_t off)
 {
-	bus_size_t base_off, wroff;
-
-	base_off = 0;
-	wroff = (off >> AGP_PAGE_SHIFT) * 4;
-
-	switch (isc->chiptype) {
-	case CHIP_I810:
-	case CHIP_I830:
-	case CHIP_I855:
-		base_off = AGP_I810_GTT;
-		break;
-	case CHIP_I965:
-		base_off = AGP_I965_GTT;
-		break;
-	case CHIP_G4X:
-		base_off = AGP_G4X_GTT;
-		break;
-	case CHIP_I915:
-	case CHIP_G33:
-		(void)bus_space_read_4(isc->gtt_bst, isc->gtt_bsh, wroff);
-		return;
-	}
 
-	(void)READ4(base_off + wroff);
+	(void)bus_space_read_4(isc->gtt_bst, isc->gtt_bsh,
+	    4*(off >> AGP_PAGE_SHIFT));
 }
 
 static void
@@ -313,14 +273,17 @@ agp_i810_attach(device_t parent, device_
 	struct agp_softc *sc = device_private(self);
 	struct agp_i810_softc *isc;
 	struct agp_gatt *gatt;
-	int error, apbase;
-	bus_addr_t mmadr;
-	bus_size_t mmadrsize;
+	int apbase, mmadr_bar, gtt_bar;
+	int mmadr_type, mmadr_flags;
+	bus_addr_t mmadr, gtt_off;
+	bus_size_t mmadr_size;
+	int error;
 
 	isc = malloc(sizeof *isc, M_AGP, M_NOWAIT|M_ZERO);
 	if (isc == NULL) {
 		aprint_error(": can't allocate chipset-specific softc\n");
-		return ENOMEM;
+		error = ENOMEM;
+		goto fail0;
 	}
 	sc->as_chipc = isc;
 	sc->as_methods = &agp_i810_methods;
@@ -335,12 +298,13 @@ agp_i810_attach(device_t parent, device_
 		case PCI_PRODUCT_INTEL_82845G_DRAM:
 		case PCI_PRODUCT_INTEL_82815_FULL_HUB:
 		case PCI_PRODUCT_INTEL_82855GM_MCH:
+			free(isc, M_AGP);
 			return agp_intel_attach(parent, self, aux);
 		}
 #endif
 		aprint_error(": can't find internal VGA device config space\n");
-		free(isc, M_AGP);
-		return ENOENT;
+		error = ENOENT;
+		goto fail1;
 	}
 
 	/* XXXfvdl */
@@ -405,80 +369,129 @@ agp_i810_attach(device_t parent, device_
 		break;
 	}
 
+	mmadr_type = PCI_MAPREG_TYPE_MEM;
 	switch (isc->chiptype) {
 	case CHIP_I915:
 	case CHIP_G33:
 		apbase = AGP_I915_GMADR;
+		mmadr_bar = AGP_I915_MMADR;
+		gtt_bar = AGP_I915_GTTADR;
 		break;
 	case CHIP_I965:
+		apbase = AGP_I965_GMADR;
+		mmadr_bar = AGP_I965_MMADR;
+		mmadr_type |= PCI_MAPREG_MEM_TYPE_64BIT;
+		gtt_bar = 0;
+		gtt_off = AGP_I965_GTT;
+		break;
 	case CHIP_G4X:
 		apbase = AGP_I965_GMADR;
+		mmadr_bar = AGP_I965_MMADR;
+		mmadr_type |= PCI_MAPREG_MEM_TYPE_64BIT;
+		gtt_bar = 0;
+		gtt_off = AGP_G4X_GTT;
 		break;
 	default:
 		apbase = AGP_I810_GMADR;
+		mmadr_bar = AGP_I810_MMADR;
+		gtt_bar = 0;
+		gtt_off = AGP_I810_GTT;
 		break;
 	}
 
-	if (isc->chiptype == CHIP_I965 || isc->chiptype == CHIP_G4X) {
+	/* Map (or, rather, find the address and size of) the aperture.  */
+	if (isc->chiptype == CHIP_I965 || isc->chiptype == CHIP_G4X)
 		error = agp_i965_map_aperture(&isc->vga_pa, sc, apbase);
-	} else {
+	else
 		error = agp_map_aperture(&isc->vga_pa, sc, apbase);
-	}
-	if (error != 0) {
+	if (error) {
 		aprint_error(": can't map aperture\n");
-		free(isc, M_AGP);
-		return error;
+		goto fail1;
 	}
 
-	if (isc->chiptype == CHIP_I915 || isc->chiptype == CHIP_G33) {
-		error = pci_mapreg_map(&isc->vga_pa, AGP_I915_MMADR,
-		    PCI_MAPREG_TYPE_MEM, 0, &isc->bst, &isc->bsh,
-		    &mmadr, &mmadrsize);
-		if (error != 0) {
-			aprint_error(": can't map mmadr registers\n");
-			agp_generic_detach(sc);
-			return error;
-		}
-		error = pci_mapreg_map(&isc->vga_pa, AGP_I915_GTTADR,
-		    PCI_MAPREG_TYPE_MEM, 0, &isc->gtt_bst, &isc->gtt_bsh,
-		    NULL, NULL);
-		if (error != 0) {
-			aprint_error(": can't map gttadr registers\n");
-			/* XXX we should release mmadr here */
-			agp_generic_detach(sc);
-			return error;
+	/* Map the memory-mapped I/O registers, or the non-GTT part.  */
+	if (pci_mapreg_info(isc->vga_pa.pa_pc, isc->vga_pa.pa_tag, mmadr_bar,
+		mmadr_type, &mmadr, &mmadr_size, &mmadr_flags)) {
+		aprint_error_dev(self, "can't find MMIO registers\n");
+		error = ENXIO;
+		goto fail1;
+	}
+	if (gtt_bar == 0) {
+		if (mmadr_size < gtt_off) {
+			aprint_error_dev(self, "MMIO registers too small"
+			    ": %"PRIuMAX" < %"PRIuMAX"\n",
+			    (uintmax_t)mmadr_size, (uintmax_t)gtt_off);
+			error = ENXIO;
+			goto fail1;
 		}
-	} else if (isc->chiptype == CHIP_I965 || isc->chiptype == CHIP_G4X) {
-		error = pci_mapreg_map(&isc->vga_pa, AGP_I965_MMADR,
-		    PCI_MAPREG_TYPE_MEM, 0, &isc->bst, &isc->bsh,
-		    &mmadr, &mmadrsize);
-		if (error != 0) {
-			aprint_error(": can't map mmadr registers\n");
-			agp_generic_detach(sc);
-			return error;
+		isc->size = gtt_off;
+	} else {
+		isc->size = mmadr_size;
+	}
+	isc->bst = isc->vga_pa.pa_memt;
+	error = bus_space_map(isc->bst, mmadr, isc->size, mmadr_flags,
+	    &isc->bsh);
+	if (error) {
+		aprint_error_dev(self, "can't map MMIO registers: %d\n",
+		    error);
+		error = ENXIO;
+		goto fail1;
+	}
+
+	/* Map the GTT, from either part of the MMIO region or its own BAR.  */
+	if (gtt_bar == 0) {
+		isc->gtt_bst = isc->bst;
+		isc->gtt_size = (mmadr_size - gtt_off);
+		error = bus_space_map(isc->gtt_bst, gtt_off, isc->gtt_size,
+		    mmadr_flags, &isc->gtt_bsh);
+		if (error) {
+			aprint_error_dev(self, "can't map GTT: %d\n", error);
+			error = ENXIO;
+			goto fail2;
 		}
 	} else {
-		error = pci_mapreg_map(&isc->vga_pa, AGP_I810_MMADR,
-		    PCI_MAPREG_TYPE_MEM, 0, &isc->bst, &isc->bsh,
-		    &mmadr, &mmadrsize);
-		if (error != 0) {
-			aprint_error(": can't map mmadr registers\n");
-			agp_generic_detach(sc);
-			return error;
+		/*
+		 * All chipsets with a separate BAR for the GTT, namely
+		 * the i915 and G33 families, have 32-bit GTT BARs.
+		 *
+		 * XXX [citation needed]
+		 */
+		if (pci_mapreg_map(&isc->vga_pa, gtt_bar, PCI_MAPREG_TYPE_MEM,
+			0,
+			&isc->gtt_bst, &isc->gtt_bsh, NULL, &isc->gtt_size)) {
+			aprint_error_dev(self, "can't map GTT\n");
+			error = ENXIO;
+			goto fail2;
 		}
 	}
 
-	isc->initial_aperture = AGP_GET_APERTURE(sc);
+	/* Set up a chipset flush page if necessary.  */
+	switch (isc->chiptype) {
+	case CHIP_I915:
+	case CHIP_I965:
+	case CHIP_G33:
+	case CHIP_G4X:
+		error = agp_i810_setup_chipset_flush_page(sc);
+		if (error) {
+			aprint_error_dev(self,
+			    "failed to set up chipset flush page: %d\n",
+			    error);
+			goto fail3;
+		}
+		break;
+	}
 
+	/* Set up the generic AGP GATT record.  */
+	isc->initial_aperture = AGP_GET_APERTURE(sc);
 	gatt = malloc(sizeof(struct agp_gatt), M_AGP, M_NOWAIT);
 	if (!gatt) {
- 		agp_generic_detach(sc);
- 		return ENOMEM;
+		error = ENOMEM;
+		goto fail4;
 	}
 	isc->gatt = gatt;
-
 	gatt->ag_entries = AGP_GET_APERTURE(sc) >> AGP_PAGE_SHIFT;
 
+	/* Power management.  (XXX Nothing to save on suspend?  Fishy...)  */
 	if (!pmf_device_register(self, NULL, agp_i810_resume))
 		aprint_error_dev(self, "couldn't establish power handler\n");
 
@@ -489,24 +502,38 @@ agp_i810_attach(device_t parent, device_
 	agp_i810_vga_regbase = mmadr;
 	agp_i810_vga_bsh = isc->bsh;
 
-	/* Set up a chipset flush page if necessary.  */
-	switch (isc->chiptype) {
+	/* Initialize the chipset.  */
+	error = agp_i810_init(sc);
+	if (error)
+		goto fail5;
+
+	/* Success!  */
+	return 0;
+
+#if notyet
+fail6: __unused
+	agp_i810_fini(sc);
+#endif
+fail5:	pmf_device_deregister(self);
+	free(gatt, M_AGP);
+	isc->gatt = NULL;
+fail4:	switch (isc->chiptype) {
 	case CHIP_I915:
 	case CHIP_I965:
 	case CHIP_G33:
 	case CHIP_G4X:
-		error = agp_i810_setup_chipset_flush_page(sc);
-		if (error) {
-			aprint_error_dev(self,
-			    "failed to set up chipset flush page: %d\n",
-			    error);
-			agp_generic_detach(sc);
-			return error;
-		}
+		agp_i810_teardown_chipset_flush_page(sc);
 		break;
 	}
-
-	return agp_i810_init(sc);
+fail3:	bus_space_unmap(isc->gtt_bst, isc->gtt_bsh, isc->gtt_size);
+	isc->gtt_size = 0;
+fail2:	bus_space_unmap(isc->bst, isc->bsh, isc->size);
+	isc->size = 0;
+fail1:	free(isc, M_AGP);
+	sc->as_chipc = NULL;
+fail0:	agp_generic_detach(sc);
+	KASSERT(error);
+	return error;
 }
 
 static int
@@ -587,6 +614,31 @@ agp_i810_setup_chipset_flush_page(struct
 	return 0;
 }
 
+static void
+agp_i810_teardown_chipset_flush_page(struct agp_softc *sc)
+{
+	struct agp_i810_softc *const isc = sc->as_chipc;
+
+	if (isc->flush_addr) {
+		/* If we allocated a page, clear it.  */
+		if (isc->chiptype == CHIP_I915) {
+			pci_conf_write(sc->as_pc, sc->as_tag, AGP_I915_IFPADDR,
+			    0);
+		} else {
+			pci_conf_write(sc->as_pc, sc->as_tag,
+			    AGP_I965_IFPADDR, 0);
+			pci_conf_write(sc->as_pc, sc->as_tag,
+			    AGP_I965_IFPADDR + 4, 0);
+		}
+		isc->flush_addr = 0;
+		bus_space_free(isc->flush_bst, isc->flush_bsh,
+		    PAGE_SIZE);
+	} else {
+		/* Otherwise, just unmap the pre-allocated page.  */
+		bus_space_unmap(isc->flush_bst, isc->flush_bsh, PAGE_SIZE);
+	}
+}
+
 /*
  * XXX horrible hack to allow drm code to use our mapping
  * of VGA chip registers
@@ -861,25 +913,7 @@ agp_i810_detach(struct agp_softc *sc)
 	case CHIP_I965:
 	case CHIP_G33:
 	case CHIP_G4X:
-		if (isc->flush_addr) {
-			/* If we allocated a page, clear it.  */
-			if (isc->chiptype == CHIP_I915) {
-				pci_conf_write(sc->as_pc, sc->as_tag,
-				    AGP_I915_IFPADDR, 0);
-			} else {
-				pci_conf_write(sc->as_pc, sc->as_tag,
-				    AGP_I965_IFPADDR, 0);
-				pci_conf_write(sc->as_pc, sc->as_tag,
-				    AGP_I965_IFPADDR + 4, 0);
-			}
-			isc->flush_addr = 0;
-			bus_space_free(isc->flush_bst, isc->flush_bsh,
-			    PAGE_SIZE);
-		} else {
-			/* Otherwise, just unmap the pre-allocated page.  */
-			bus_space_unmap(isc->flush_bst, isc->flush_bsh,
-			    PAGE_SIZE);
-		}
+		agp_i810_teardown_chipset_flush_page(sc);
 		break;
 	}
 
@@ -1262,6 +1296,10 @@ agp_i810_resume(device_t dv, const pmf_q
 	struct agp_softc *sc = device_private(dv);
 	struct agp_i810_softc *isc = sc->as_chipc;
 
+	/*
+	 * XXX Nothing uses isc->pgtblctl!  Save on suspend, restore on
+	 * resume?
+	 */
 	isc->pgtblctl = READ4(AGP_I810_PGTBL_CTL);
 	agp_flush_cache();
 

Index: src/sys/dev/pci/agp_i810var.h
diff -u src/sys/dev/pci/agp_i810var.h:1.3 src/sys/dev/pci/agp_i810var.h:1.4
--- src/sys/dev/pci/agp_i810var.h:1.3	Fri May 23 22:58:56 2014
+++ src/sys/dev/pci/agp_i810var.h	Tue May 27 03:17:33 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: agp_i810var.h,v 1.3 2014/05/23 22:58:56 riastradh Exp $	*/
+/*	$NetBSD: agp_i810var.h,v 1.4 2014/05/27 03:17:33 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2000 Doug Rabson
@@ -35,23 +35,30 @@
 #include <dev/pci/agpvar.h>
 
 struct agp_i810_softc {
-	u_int32_t initial_aperture;	/* aperture size at startup */
-	struct agp_gatt *gatt;
-	int chiptype;			/* i810-like or i830 */
-	u_int32_t dcache_size;		/* i810 only */
-	u_int32_t stolen;		/* number of i830/845 gtt entries
-					   for stolen memory */
-	bus_space_tag_t bst;		/* register bus_space tag */
-	bus_space_handle_t bsh;		/* register bus_space handle */
-	bus_space_tag_t gtt_bst;	/* GTT bus_space tag */
-	bus_space_handle_t gtt_bsh;	/* GTT bus_space handle */
-	struct pci_attach_args vga_pa;
-
-	u_int32_t pgtblctl;
-
-	bus_space_tag_t flush_bst;	/* flush page bus_space tag */
-	bus_space_handle_t flush_bsh;	/* flush page bus_space handle */
-	bus_addr_t flush_addr;		/* flush page bus address */
+	struct pci_attach_args vga_pa;	/* integrated graphics device args */
+	int chiptype;			/* chipset family: i810, i830, &c. */
+
+	/* Memory-mapped I/O for device registers.  */
+	bus_space_tag_t bst;
+	bus_space_handle_t bsh;
+	bus_size_t size;
+
+	/* Graphics translation table.  */
+	bus_space_tag_t gtt_bst;
+	bus_space_handle_t gtt_bsh;
+	bus_size_t gtt_size;
+
+	/* Chipset flush page.  */
+	bus_space_tag_t flush_bst;
+	bus_space_handle_t flush_bsh;
+	bus_addr_t flush_addr;
+
+	uint32_t initial_aperture;	/* aperture size at startup */
+	struct agp_gatt *gatt;		/* AGP graphics addr. trans. tbl. */
+	uint32_t dcache_size;		/* i810-only on-chip memory size */
+	uint32_t stolen;		/* num. GTT entries for stolen mem. */
+
+	uint32_t pgtblctl;		/* saved PGTBL_CTL?  XXX unused */
 };
 
 extern struct agp_softc	*agp_i810_sc;

Reply via email to