From cd7e9610083fb288a1e9f23608cb1c5fa19700da Mon Sep 17 00:00:00 2001 From: anholt Date: Fri, 16 Sep 2005 22:59:47 +0000 Subject: 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 , Robin Schoonover , Jason Henson --- sys/dev/agp/agp_nvidia.c | 31 ++++++++++++++++++++----------- sys/pci/agp_nvidia.c | 31 ++++++++++++++++++++----------- 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); } -- cgit v1.1