mirror of
https://github.com/opnsense/src.git
synced 2026-06-08 16:22:46 -04:00
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>.
This commit is contained in:
parent
015d72e0c9
commit
3080733f2e
4 changed files with 438 additions and 104 deletions
|
|
@ -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;
|
||||
|
||||
for (;;) {
|
||||
gatt = agp_alloc_gatt(dev);
|
||||
if (gatt)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Probably contigmalloc failure. Try reducing the
|
||||
* aperture so that the gatt size reduces.
|
||||
*/
|
||||
if (AGP_SET_APERTURE(dev, AGP_GET_APERTURE(dev) / 2)) {
|
||||
agp_generic_detach(dev);
|
||||
return ENOMEM;
|
||||
}
|
||||
gatt = malloc( sizeof(struct agp_gatt), M_AGP, M_NOWAIT);
|
||||
if (!gatt) {
|
||||
agp_generic_detach(dev);
|
||||
return ENOMEM;
|
||||
}
|
||||
sc->gatt = gatt;
|
||||
|
||||
/* Install the GATT. */
|
||||
WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1);
|
||||
gatt->ag_entries = AGP_GET_APERTURE(dev) >> AGP_PAGE_SHIFT;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
for (;;) {
|
||||
gatt = agp_alloc_gatt(dev);
|
||||
if (gatt)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Probably contigmalloc failure. Try reducing the
|
||||
* aperture so that the gatt size reduces.
|
||||
*/
|
||||
if (AGP_SET_APERTURE(dev, AGP_GET_APERTURE(dev) / 2)) {
|
||||
agp_generic_detach(dev);
|
||||
return ENOMEM;
|
||||
}
|
||||
gatt = malloc( sizeof(struct agp_gatt), M_AGP, M_NOWAIT);
|
||||
if (!gatt) {
|
||||
agp_generic_detach(dev);
|
||||
return ENOMEM;
|
||||
}
|
||||
sc->gatt = gatt;
|
||||
|
||||
/* Install the GATT. */
|
||||
WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1);
|
||||
gatt->ag_entries = AGP_GET_APERTURE(dev) >> AGP_PAGE_SHIFT;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
Loading…
Reference in a new issue