diff options
author | anholt <anholt@FreeBSD.org> | 2002-09-12 04:23:18 +0000 |
---|---|---|
committer | anholt <anholt@FreeBSD.org> | 2002-09-12 04:23:18 +0000 |
commit | 20e15ff61d8946fded44787e99633937ae069043 (patch) | |
tree | 282c4189307601bf27244cd8bbcc1e479c2d7708 /sys/pci | |
parent | 23faaeb316f2c857606ee713dfa149a835aa0500 (diff) | |
download | FreeBSD-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')
-rw-r--r-- | sys/pci/agp_i810.c | 250 | ||||
-rw-r--r-- | sys/pci/agpreg.h | 15 |
2 files changed, 216 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); diff --git a/sys/pci/agpreg.h b/sys/pci/agpreg.h index 13f08e3..36a11bc 100644 --- a/sys/pci/agpreg.h +++ b/sys/pci/agpreg.h @@ -160,5 +160,20 @@ #define AGP_I810_DRT_UNPOPULATED 0x00 #define AGP_I810_DRT_POPULATED 0x01 #define AGP_I810_GTT 0x10000 + +/* + * Config registers for i830MG device 0 + */ +#define AGP_I830_GCC1 0x52 +#define AGP_I830_GCC1_DEV2 0x08 +#define AGP_I830_GCC1_DEV2_ENABLED 0x00 +#define AGP_I830_GCC1_DEV2_DISABLED 0x08 +#define AGP_I830_GCC1_GMS 0x70 +#define AGP_I830_GCC1_GMS_STOLEN_512 0x20 +#define AGP_I830_GCC1_GMS_STOLEN_1024 0x30 +#define AGP_I830_GCC1_GMS_STOLEN_8192 0x40 +#define AGP_I830_GCC1_GMASIZE 0x01 +#define AGP_I830_GCC1_GMASIZE_64 0x01 +#define AGP_I830_GCC1_GMASIZE_128 0x00 #endif /* !_PCI_AGPREG_H_ */ |