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);
}
/*