summaryrefslogtreecommitdiffstats
path: root/sys/pci/agp_i810.c
diff options
context:
space:
mode:
authoranholt <anholt@FreeBSD.org>2002-09-12 04:23:18 +0000
committeranholt <anholt@FreeBSD.org>2002-09-12 04:23:18 +0000
commit20e15ff61d8946fded44787e99633937ae069043 (patch)
tree282c4189307601bf27244cd8bbcc1e479c2d7708 /sys/pci/agp_i810.c
parent23faaeb316f2c857606ee713dfa149a835aa0500 (diff)
downloadFreeBSD-src-20e15ff61d8946fded44787e99633937ae069043.zip
FreeBSD-src-20e15ff61d8946fded44787e99633937ae069043.tar.gz
Add AGP support for Intel i830M and i845 thanks to patches from moto kawasaki
<kawasaki@mbg.sphere.ne.jp> and David Dawes <dawes@XFree86.org>.
Diffstat (limited to 'sys/pci/agp_i810.c')
-rw-r--r--sys/pci/agp_i810.c250
1 files changed, 201 insertions, 49 deletions
diff --git a/sys/pci/agp_i810.c b/sys/pci/agp_i810.c
index 942dc92..a8ac38e 100644
--- a/sys/pci/agp_i810.c
+++ b/sys/pci/agp_i810.c
@@ -27,6 +27,10 @@
* $FreeBSD$
*/
+/*
+ * Fixes for 830/845G support: David Dawes <dawes@xfree86.org>
+ */
+
#include "opt_bus.h"
#include "opt_pci.h"
@@ -58,13 +62,19 @@
MALLOC_DECLARE(M_AGP);
#define READ1(off) bus_space_read_1(sc->bst, sc->bsh, off)
+#define READ4(off) bus_space_read_4(sc->bst, sc->bsh, off)
#define WRITE4(off,v) bus_space_write_4(sc->bst, sc->bsh, off, v)
+#define CHIP_I810 0 /* i810/i815 */
+#define CHIP_I830 1 /* i830/i845 */
+
struct agp_i810_softc {
struct agp_softc agp;
u_int32_t initial_aperture; /* aperture size at startup */
struct agp_gatt *gatt;
- u_int32_t dcache_size;
+ 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 */
device_t bdev; /* bridge device */
struct resource *regs; /* memory mapped GC registers */
bus_space_tag_t bst; /* bus_space tag */
@@ -90,6 +100,12 @@ agp_i810_match(device_t dev)
case 0x11328086:
return ("Intel 82815 (i815 GMCH) SVGA controller");
+
+ case 0x35778086:
+ return ("Intel 82830 (i830M GMCH) SVGA controller");
+
+ case 0x25628086:
+ return ("Intel 82845 (i845 GMCH) SVGA controller");
};
return NULL;
@@ -117,7 +133,9 @@ agp_i810_find_bridge(device_t dev)
break;
case 0x11328086:
- devid = 0x11308086;
+ case 0x35778086:
+ case 0x25628086:
+ devid -= 0x20000;
break;
};
if (device_get_children(device_get_parent(dev), &children, &nchildren))
@@ -144,6 +162,7 @@ agp_i810_probe(device_t dev)
if (desc) {
device_t bdev;
u_int8_t smram;
+ int devid = pci_get_devid(dev);
bdev = agp_i810_find_bridge(dev);
if (!bdev) {
@@ -152,12 +171,26 @@ agp_i810_probe(device_t dev)
return ENXIO;
}
- smram = pci_read_config(bdev, AGP_I810_SMRAM, 1);
- if ((smram & AGP_I810_SMRAM_GMS)
- == AGP_I810_SMRAM_GMS_DISABLED) {
- if (bootverbose)
- printf("I810: disabled, not probing\n");
- return ENXIO;
+ /*
+ * checking whether internal graphics device has been activated.
+ */
+ if ( (devid != 0x35778086 ) &&
+ (devid != 0x25628086 ) ) {
+ smram = pci_read_config(bdev, AGP_I810_SMRAM, 1);
+ if ((smram & AGP_I810_SMRAM_GMS)
+ == AGP_I810_SMRAM_GMS_DISABLED) {
+ if (bootverbose)
+ printf("I810: disabled, not probing\n");
+ return ENXIO;
+ }
+ } else { /* I830MG */
+ unsigned int gcc1;
+ gcc1 = pci_read_config(bdev, AGP_I830_GCC1, 1);
+ if ((gcc1 & AGP_I830_GCC1_DEV2) == AGP_I830_GCC1_DEV2_DISABLED) {
+ if (bootverbose)
+ printf("I830: disabled, not probing\n");
+ return ENXIO;
+ }
}
device_verbose(dev);
@@ -183,6 +216,18 @@ agp_i810_attach(device_t dev)
if (error)
return error;
+ switch (pci_get_devid(dev)) {
+ case 0x71218086:
+ case 0x71238086:
+ case 0x71258086:
+ case 0x11328086:
+ sc->chiptype = CHIP_I810;
+ case 0x35778086:
+ case 0x25628086:
+ sc->chiptype = CHIP_I830;
+ };
+
+ /* Same for i810 and i830 */
rid = AGP_I810_MMADR;
sc->regs = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
0, ~0, 1, RF_ACTIVE);
@@ -195,29 +240,73 @@ agp_i810_attach(device_t dev)
sc->initial_aperture = AGP_GET_APERTURE(dev);
- if (READ1(AGP_I810_DRT) & AGP_I810_DRT_POPULATED)
- sc->dcache_size = 4 * 1024 * 1024;
- else
- sc->dcache_size = 0;
+ gatt = malloc( sizeof(struct agp_gatt), M_AGP, M_NOWAIT);
+ if (!gatt) {
+ agp_generic_detach(dev);
+ return ENOMEM;
+ }
+ sc->gatt = gatt;
- for (;;) {
- gatt = agp_alloc_gatt(dev);
- if (gatt)
- break;
+ gatt->ag_entries = AGP_GET_APERTURE(dev) >> AGP_PAGE_SHIFT;
- /*
- * Probably contigmalloc failure. Try reducing the
- * aperture so that the gatt size reduces.
- */
- if (AGP_SET_APERTURE(dev, AGP_GET_APERTURE(dev) / 2)) {
+ if ( sc->chiptype == CHIP_I810 ) {
+ /* Some i810s have on-chip memory called dcache */
+ if (READ1(AGP_I810_DRT) & AGP_I810_DRT_POPULATED)
+ sc->dcache_size = 4 * 1024 * 1024;
+ else
+ sc->dcache_size = 0;
+
+ /* According to the specs the gatt on the i810 must be 64k */
+ gatt->ag_virtual = contigmalloc( 64 * 1024, M_AGP, 0,
+ 0, ~0, PAGE_SIZE, 0);
+ if (!gatt->ag_virtual) {
+ if (bootverbose)
+ device_printf(dev, "contiguous allocation failed\n");
+ free(gatt, M_AGP);
agp_generic_detach(dev);
return ENOMEM;
}
+ bzero(gatt->ag_virtual, gatt->ag_entries * sizeof(u_int32_t));
+
+ gatt->ag_physical = vtophys((vm_offset_t) gatt->ag_virtual);
+ agp_flush_cache();
+ /* Install the GATT. */
+ WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1);
+ } else {
+ /* The i830 automatically initializes the 128k gatt on boot. */
+ unsigned int gcc1, pgtblctl;
+
+ gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 1);
+ switch (gcc1 & AGP_I830_GCC1_GMS) {
+ case AGP_I830_GCC1_GMS_STOLEN_512:
+ sc->stolen = (512 - 132) * 1024 / 4096;
+ break;
+ case AGP_I830_GCC1_GMS_STOLEN_1024:
+ sc->stolen = (1024 - 132) * 1024 / 4096;
+ break;
+ case AGP_I830_GCC1_GMS_STOLEN_8192:
+ sc->stolen = (8192 - 132) * 1024 / 4096;
+ break;
+ default:
+ sc->stolen = 0;
+ device_printf(dev, "unknown memory configuration, disabling\n");
+ agp_generic_detach(dev);
+ return EINVAL;
+ }
+ if (sc->stolen > 0)
+ device_printf(dev, "detected %dk stolen memory\n", sc->stolen * 4);
+ device_printf(dev, "aperture size is %dM\n", sc->initial_aperture / 1024 / 1024);
+
+ /* GATT address is already in there, make sure it's enabled */
+ pgtblctl = READ4(AGP_I810_PGTBL_CTL);
+#if 0
+ device_printf(dev, "PGTBL_CTL is 0x%08x\n", pgtblctl);
+#endif
+ pgtblctl |= 1;
+ WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
+
+ gatt->ag_physical = pgtblctl & ~1;
}
- sc->gatt = gatt;
-
- /* Install the GATT. */
- WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1);
/*
* Make sure the chipset can see everything.
@@ -238,12 +327,22 @@ agp_i810_detach(device_t dev)
return error;
/* Clear the GATT base. */
- WRITE4(AGP_I810_PGTBL_CTL, 0);
+ if ( sc->chiptype == CHIP_I810 ) {
+ WRITE4(AGP_I810_PGTBL_CTL, 0);
+ } else {
+ unsigned int pgtblctl;
+ pgtblctl = READ4(AGP_I810_PGTBL_CTL);
+ pgtblctl &= ~1;
+ WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
+ }
/* Put the aperture back the way it started. */
AGP_SET_APERTURE(dev, sc->initial_aperture);
- agp_free_gatt(sc->gatt);
+ if ( sc->chiptype == CHIP_I810 ) {
+ contigfree(sc->gatt->ag_virtual, 64 * 1024, M_AGP);
+ }
+ free(sc->gatt, M_AGP);
bus_release_resource(dev, SYS_RES_MEMORY,
AGP_I810_MMADR, sc->regs);
@@ -255,13 +354,23 @@ static u_int32_t
agp_i810_get_aperture(device_t dev)
{
struct agp_i810_softc *sc = device_get_softc(dev);
- u_int16_t miscc;
- miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
- if ((miscc & AGP_I810_MISCC_WINSIZE) == AGP_I810_MISCC_WINSIZE_32)
- return 32 * 1024 * 1024;
- else
- return 64 * 1024 * 1024;
+ if ( sc->chiptype == CHIP_I810 ) {
+ u_int16_t miscc;
+ miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
+ if ((miscc & AGP_I810_MISCC_WINSIZE) == AGP_I810_MISCC_WINSIZE_32)
+ return 32 * 1024 * 1024;
+ else
+ return 64 * 1024 * 1024;
+ } else { /* I830 */
+ unsigned int gcc1;
+
+ gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
+ if ((gcc1 & AGP_I830_GCC1_GMASIZE) == AGP_I830_GCC1_GMASIZE_64)
+ return 64 * 1024 * 1024;
+ else
+ return 128 * 1024 * 1024;
+ }
}
static int
@@ -270,23 +379,40 @@ agp_i810_set_aperture(device_t dev, u_int32_t aperture)
struct agp_i810_softc *sc = device_get_softc(dev);
u_int16_t miscc;
- /*
- * Double check for sanity.
- */
- if (aperture != 32 * 1024 * 1024 && aperture != 64 * 1024 * 1024) {
- device_printf(dev, "bad aperture size %d\n", aperture);
- return EINVAL;
+ if ( sc->chiptype == CHIP_I810 ) {
+ /*
+ * Double check for sanity.
+ */
+ if (aperture != 32 * 1024 * 1024 && aperture != 64 * 1024 * 1024) {
+ device_printf(dev, "bad aperture size %d\n", aperture);
+ return EINVAL;
+ }
+
+ miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
+ miscc &= ~AGP_I810_MISCC_WINSIZE;
+ if (aperture == 32 * 1024 * 1024)
+ miscc |= AGP_I810_MISCC_WINSIZE_32;
+ else
+ miscc |= AGP_I810_MISCC_WINSIZE_64;
+
+ pci_write_config(sc->bdev, AGP_I810_MISCC, miscc, 2);
+ } else { /* I830 */
+ unsigned int gcc1;
+
+ if (aperture != 64 * 1024 * 1024 && aperture != 128 * 1024 * 1024) {
+ device_printf(dev, "bad aperture size %d\n", aperture);
+ return EINVAL;
+ }
+ gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
+ gcc1 &= ~AGP_I830_GCC1_GMASIZE;
+ if (aperture == 64 * 1024 * 1024)
+ gcc1 |= AGP_I830_GCC1_GMASIZE_64;
+ else
+ gcc1 |= AGP_I830_GCC1_GMASIZE_128;
+
+ pci_write_config(sc->bdev, AGP_I830_GCC1, gcc1, 2);
}
- miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
- miscc &= ~AGP_I810_MISCC_WINSIZE;
- if (aperture == 32 * 1024 * 1024)
- miscc |= AGP_I810_MISCC_WINSIZE_32;
- else
- miscc |= AGP_I810_MISCC_WINSIZE_64;
-
- pci_write_config(sc->bdev, AGP_I810_MISCC, miscc, 2);
-
return 0;
}
@@ -295,8 +421,17 @@ agp_i810_bind_page(device_t dev, int offset, vm_offset_t physical)
{
struct agp_i810_softc *sc = device_get_softc(dev);
- if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) {
+ device_printf(dev, "failed: offset is 0x%08x, shift is %d, entries is %d\n", offset, AGP_PAGE_SHIFT, sc->gatt->ag_entries);
return EINVAL;
+ }
+
+ if ( sc->chiptype == CHIP_I830 ) {
+ if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) {
+ device_printf(dev, "trying to bind into stolen memory");
+ return EINVAL;
+ }
+ }
WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, physical | 1);
return 0;
@@ -310,6 +445,12 @@ agp_i810_unbind_page(device_t dev, int offset)
if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
return EINVAL;
+ if ( sc->chiptype == CHIP_I830 ) {
+ if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen )
+ device_printf(dev, "trying to unbind from stolen memory");
+ return EINVAL;
+ }
+
WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, 0);
return 0;
}
@@ -345,6 +486,8 @@ agp_i810_alloc_memory(device_t dev, int type, vm_size_t size)
/*
* Mapping local DRAM into GATT.
*/
+ if ( sc->chiptype == CHIP_I830 )
+ return 0;
if (size != sc->dcache_size)
return 0;
} else if (type == 2) {
@@ -427,6 +570,12 @@ agp_i810_bind_memory(device_t dev, struct agp_memory *mem,
if (mem->am_type != 1)
return agp_generic_bind_memory(dev, mem, offset);
+ if ( sc->chiptype == CHIP_I830 ) {
+ if ((offset >> AGP_PAGE_SHIFT) < sc->stolen)
+ device_printf(dev, "trying to bind into stolen memory");
+ return EINVAL;
+ }
+
for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4,
i | 3);
@@ -444,6 +593,9 @@ agp_i810_unbind_memory(device_t dev, struct agp_memory *mem)
if (mem->am_type != 1)
return agp_generic_unbind_memory(dev, mem);
+ if ( sc->chiptype == CHIP_I830 )
+ return EINVAL;
+
for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
WRITE4(AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, 0);
OpenPOWER on IntegriCloud