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