summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoranholt <anholt@FreeBSD.org>2005-09-16 22:59:47 +0000
committeranholt <anholt@FreeBSD.org>2005-09-16 22:59:47 +0000
commitcd7e9610083fb288a1e9f23608cb1c5fa19700da (patch)
treed3c98f55b36bf230b35c25c4dc903d82e2c38506
parent6adebfab812a023e8d2e349fa2ea5c3bd91e708d (diff)
downloadFreeBSD-src-cd7e9610083fb288a1e9f23608cb1c5fa19700da.zip
FreeBSD-src-cd7e9610083fb288a1e9f23608cb1c5fa19700da.tar.gz
Fix agp_nvidia.c to behave more like the linux driver, fixing DRI on Radeon
9200 according to one responder. The primary issue was not setting some bits to say that the entries were active, but also fix one place where some memory wasn't being used as volatile as it should. While here, change some use of ffs to a relatively short case statement, to make it more obvious what's going on. PR: kern/71638, kern/72372, kern/71547? Submitted by: Andrew J. Caines <A.J.Caines@halplant.com>, Robin Schoonover <end@endif.cjb.net>, Jason Henson <jason@ec.rr.com>
-rw-r--r--sys/dev/agp/agp_nvidia.c31
-rw-r--r--sys/pci/agp_nvidia.c31
2 files changed, 40 insertions, 22 deletions
diff --git a/sys/dev/agp/agp_nvidia.c b/sys/dev/agp/agp_nvidia.c
index e49c140..5e26622 100644
--- a/sys/dev/agp/agp_nvidia.c
+++ b/sys/dev/agp/agp_nvidia.c
@@ -148,8 +148,8 @@ agp_nvidia_attach (device_t dev)
sc->wbc_mask = 0x80000000;
break;
default:
- sc->wbc_mask = 0;
- break;
+ device_printf(dev, "Bad chip id\n");
+ return (ENODEV);
}
/* AGP Controller */
@@ -227,8 +227,7 @@ agp_nvidia_attach (device_t dev)
for (i = 0; i < 8; i++) {
pci_write_config(sc->mc2_dev, AGP_NVIDIA_2_ATTBASE(i),
(sc->gatt->ag_physical +
- (i % sc->num_dirs) * 64 * 1024),
- 4);
+ (i % sc->num_dirs) * 64 * 1024) | 1, 4);
}
/* GTLB Control */
@@ -279,10 +278,17 @@ agp_nvidia_detach (device_t dev)
static u_int32_t
agp_nvidia_get_aperture(device_t dev)
{
- u_int8_t key;
-
- key = ffs(pci_read_config(dev, AGP_NVIDIA_0_APSIZE, 1) & 0x0f);
- return (1 << (24 + (key ? key : 5)));
+ switch (pci_read_config(dev, AGP_NVIDIA_0_APSIZE, 1) & 0x0f) {
+ case 0: return (512 * 1024 * 1024); break;
+ case 8: return (256 * 1024 * 1024); break;
+ case 12: return (128 * 1024 * 1024); break;
+ case 14: return (64 * 1024 * 1024); break;
+ case 15: return (32 * 1024 * 1024); break;
+ default:
+ device_printf(dev, "Invalid aperture setting 0x%x",
+ pci_read_config(dev, AGP_NVIDIA_0_APSIZE, 1));
+ return 0;
+ }
}
static int
@@ -318,7 +324,7 @@ agp_nvidia_bind_page(device_t dev, int offset, vm_offset_t physical)
return (EINVAL);
index = (sc->pg_offset + offset) >> AGP_PAGE_SHIFT;
- sc->gatt->ag_virtual[index] = physical;
+ sc->gatt->ag_virtual[index] = physical | 1;
return (0);
}
@@ -343,6 +349,7 @@ agp_nvidia_flush_tlb (device_t dev, int offset)
{
struct agp_nvidia_softc *sc;
u_int32_t wbc_reg, temp;
+ volatile u_int32_t *ag_virtual;
int i;
sc = (struct agp_nvidia_softc *)device_get_softc(dev);
@@ -366,11 +373,13 @@ agp_nvidia_flush_tlb (device_t dev, int offset)
"TLB flush took more than 3 seconds.\n");
}
+ ag_virtual = (volatile u_int32_t *)sc->gatt->ag_virtual;
+
/* Flush TLB entries. */
for(i = 0; i < 32 + 1; i++)
- temp = sc->gatt->ag_virtual[i * PAGE_SIZE / sizeof(u_int32_t)];
+ temp = ag_virtual[i * PAGE_SIZE / sizeof(u_int32_t)];
for(i = 0; i < 32 + 1; i++)
- temp = sc->gatt->ag_virtual[i * PAGE_SIZE / sizeof(u_int32_t)];
+ temp = ag_virtual[i * PAGE_SIZE / sizeof(u_int32_t)];
return (0);
}
diff --git a/sys/pci/agp_nvidia.c b/sys/pci/agp_nvidia.c
index e49c140..5e26622 100644
--- a/sys/pci/agp_nvidia.c
+++ b/sys/pci/agp_nvidia.c
@@ -148,8 +148,8 @@ agp_nvidia_attach (device_t dev)
sc->wbc_mask = 0x80000000;
break;
default:
- sc->wbc_mask = 0;
- break;
+ device_printf(dev, "Bad chip id\n");
+ return (ENODEV);
}
/* AGP Controller */
@@ -227,8 +227,7 @@ agp_nvidia_attach (device_t dev)
for (i = 0; i < 8; i++) {
pci_write_config(sc->mc2_dev, AGP_NVIDIA_2_ATTBASE(i),
(sc->gatt->ag_physical +
- (i % sc->num_dirs) * 64 * 1024),
- 4);
+ (i % sc->num_dirs) * 64 * 1024) | 1, 4);
}
/* GTLB Control */
@@ -279,10 +278,17 @@ agp_nvidia_detach (device_t dev)
static u_int32_t
agp_nvidia_get_aperture(device_t dev)
{
- u_int8_t key;
-
- key = ffs(pci_read_config(dev, AGP_NVIDIA_0_APSIZE, 1) & 0x0f);
- return (1 << (24 + (key ? key : 5)));
+ switch (pci_read_config(dev, AGP_NVIDIA_0_APSIZE, 1) & 0x0f) {
+ case 0: return (512 * 1024 * 1024); break;
+ case 8: return (256 * 1024 * 1024); break;
+ case 12: return (128 * 1024 * 1024); break;
+ case 14: return (64 * 1024 * 1024); break;
+ case 15: return (32 * 1024 * 1024); break;
+ default:
+ device_printf(dev, "Invalid aperture setting 0x%x",
+ pci_read_config(dev, AGP_NVIDIA_0_APSIZE, 1));
+ return 0;
+ }
}
static int
@@ -318,7 +324,7 @@ agp_nvidia_bind_page(device_t dev, int offset, vm_offset_t physical)
return (EINVAL);
index = (sc->pg_offset + offset) >> AGP_PAGE_SHIFT;
- sc->gatt->ag_virtual[index] = physical;
+ sc->gatt->ag_virtual[index] = physical | 1;
return (0);
}
@@ -343,6 +349,7 @@ agp_nvidia_flush_tlb (device_t dev, int offset)
{
struct agp_nvidia_softc *sc;
u_int32_t wbc_reg, temp;
+ volatile u_int32_t *ag_virtual;
int i;
sc = (struct agp_nvidia_softc *)device_get_softc(dev);
@@ -366,11 +373,13 @@ agp_nvidia_flush_tlb (device_t dev, int offset)
"TLB flush took more than 3 seconds.\n");
}
+ ag_virtual = (volatile u_int32_t *)sc->gatt->ag_virtual;
+
/* Flush TLB entries. */
for(i = 0; i < 32 + 1; i++)
- temp = sc->gatt->ag_virtual[i * PAGE_SIZE / sizeof(u_int32_t)];
+ temp = ag_virtual[i * PAGE_SIZE / sizeof(u_int32_t)];
for(i = 0; i < 32 + 1; i++)
- temp = sc->gatt->ag_virtual[i * PAGE_SIZE / sizeof(u_int32_t)];
+ temp = ag_virtual[i * PAGE_SIZE / sizeof(u_int32_t)];
return (0);
}
OpenPOWER on IntegriCloud