Module Name:    src
Committed By:   gsutre
Date:           Sun Jan 30 23:43:09 UTC 2011

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

Log Message:
Enable 36-bit addressing for chipsets that support it.  While there,
factorize offset computation.  Inspired from OpenBSD and Intel docs.

Note: agp_i810_bind/unbind_page will now fail with EINVAL if the
physical address is too large for the chipset (instead of silently
truncating it).

ok jmcneill@


To generate a diff of this commit:
cvs rdiff -u -r1.70 -r1.71 src/sys/dev/pci/agp_i810.c

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.70 src/sys/dev/pci/agp_i810.c:1.71
--- src/sys/dev/pci/agp_i810.c:1.70	Tue Jan 25 10:52:11 2011
+++ src/sys/dev/pci/agp_i810.c	Sun Jan 30 23:43:08 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: agp_i810.c,v 1.70 2011/01/25 10:52:11 gsutre Exp $	*/
+/*	$NetBSD: agp_i810.c,v 1.71 2011/01/30 23:43:08 gsutre Exp $	*/
 
 /*-
  * Copyright (c) 2000 Doug Rabson
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: agp_i810.c,v 1.70 2011/01/25 10:52:11 gsutre Exp $");
+__KERNEL_RCSID(0, "$NetBSD: agp_i810.c,v 1.71 2011/01/30 23:43:08 gsutre Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -100,8 +100,8 @@
 static int agp_i810_init(struct agp_softc *);
 
 static int agp_i810_init(struct agp_softc *);
-static void agp_i810_write_gtt_entry(struct agp_i810_softc *, off_t,
-				     u_int32_t);
+static int agp_i810_write_gtt_entry(struct agp_i810_softc *, off_t,
+				    bus_addr_t);
 
 static struct agp_methods agp_i810_methods = {
 	agp_i810_get_aperture,
@@ -116,12 +116,37 @@
 	agp_i810_unbind_memory,
 };
 
-static void
-agp_i810_write_gtt_entry(struct agp_i810_softc *isc, off_t off, u_int32_t v)
+static int
+agp_i810_write_gtt_entry(struct agp_i810_softc *isc, off_t off, bus_addr_t v)
 {
-	u_int32_t base_off;
+	u_int32_t pte;
+	bus_size_t base_off, wroff;
+
+	/* Bits 11:4 (physical start address extension) should be zero. */
+	if ((v & 0xff0) != 0)
+		return EINVAL;
+
+	pte = (u_int32_t)v;
+	/*
+	 * We need to massage the pte if bus_addr_t is wider than 32 bits.
+	 * The compiler isn't smart enough, hence the casts to uintmax_t.
+	 */
+	if (sizeof(bus_addr_t) > sizeof(u_int32_t)) {
+		/* 965+ can do 36-bit addressing, add in the extra bits. */
+		if (isc->chiptype == CHIP_I965 ||
+		    isc->chiptype == CHIP_G33 ||
+		    isc->chiptype == CHIP_G4X) {
+			if (((uintmax_t)v >> 36) != 0)
+				return EINVAL;
+			pte |= (v >> 28) & 0xf0;
+		} else {
+			if (((uintmax_t)v >> 32) != 0)
+				return EINVAL;
+		}
+	}
 
 	base_off = 0;
+	wroff = (off >> AGP_PAGE_SHIFT) * 4;
 
 	switch (isc->chiptype) {
 	case CHIP_I810:
@@ -137,12 +162,12 @@
 		break;
 	case CHIP_I915:
 	case CHIP_G33:
-		bus_space_write_4(isc->gtt_bst, isc->gtt_bsh,
-		    (u_int32_t)((off) >> AGP_PAGE_SHIFT) * 4, (v));
-		return;
+		bus_space_write_4(isc->gtt_bst, isc->gtt_bsh, wroff, pte);
+		return 0;
 	}
-		
-	WRITE4(base_off + (u_int32_t)(off >> AGP_PAGE_SHIFT) * 4, v);
+
+	WRITE4(base_off + wroff, pte);
+	return 0;
 }
 
 /* XXXthorpej -- duplicated code (see arch/x86/pci/pchb.c) */
@@ -829,8 +854,7 @@
 		}
 	}
 
-	agp_i810_write_gtt_entry(isc, offset, physical | 1);
-	return 0;
+	return agp_i810_write_gtt_entry(isc, offset, physical | 1);
 }
 
 static int
@@ -851,8 +875,7 @@
 		}
 	}
 
-	agp_i810_write_gtt_entry(isc, offset, 0);
-	return 0;
+	return agp_i810_write_gtt_entry(isc, offset, 0);
 }
 
 /*

Reply via email to