summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorcokane <cokane@FreeBSD.org>2001-12-07 05:41:26 +0000
committercokane <cokane@FreeBSD.org>2001-12-07 05:41:26 +0000
commit9aa8f2242aaf9263e01dbd9fb9be9cd2d1a14c2b (patch)
tree039f0d43434147646316395948539139bee60db5 /sys
parentb476f9be02ed72c3be7d8ef746cf144d9332f552 (diff)
downloadFreeBSD-src-9aa8f2242aaf9263e01dbd9fb9be9cd2d1a14c2b.zip
FreeBSD-src-9aa8f2242aaf9263e01dbd9fb9be9cd2d1a14c2b.tar.gz
This patch will fix the lockups associated with AMD 751,761,762 based AGP
controllers. There still seems to be some issues with the DRI copying code for some adapters, at least it doesn't hang the system now. Input would be appreciated. PR: 32301 Obtained from: Eric Anhlot <eanholt@gladstone.uoregon.edu>, Joe <joeo@nks.net>
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/agp/agp_amd.c58
-rw-r--r--sys/dev/agp/agpreg.h1
-rw-r--r--sys/pci/agp_amd.c58
-rw-r--r--sys/pci/agpreg.h1
4 files changed, 104 insertions, 14 deletions
diff --git a/sys/dev/agp/agp_amd.c b/sys/dev/agp/agp_amd.c
index 6ab062b..df27fca 100644
--- a/sys/dev/agp/agp_amd.c
+++ b/sys/dev/agp/agp_amd.c
@@ -59,9 +59,10 @@ MALLOC_DECLARE(M_AGP);
struct agp_amd_gatt {
u_int32_t ag_entries;
+ u_int32_t *ag_virtual; /* virtual address of gatt */
+ vm_offset_t ag_physical;
u_int32_t *ag_vdir; /* virtual address of page dir */
vm_offset_t ag_pdir; /* physical address of page dir */
- u_int32_t *ag_virtual; /* virtual address of gatt */
};
struct agp_amd_softc {
@@ -79,7 +80,7 @@ agp_amd_alloc_gatt(device_t dev)
u_int32_t apsize = AGP_GET_APERTURE(dev);
u_int32_t entries = apsize >> AGP_PAGE_SHIFT;
struct agp_amd_gatt *gatt;
- int i, npages;
+ int i, npages, pdir_offset;
if (bootverbose)
device_printf(dev,
@@ -93,6 +94,8 @@ agp_amd_alloc_gatt(device_t dev)
/*
* The AMD751 uses a page directory to map a non-contiguous
* gatt so we don't need to use contigmalloc.
+ * Malloc individual gatt pages and map them into the page
+ * directory.
*/
gatt->ag_entries = entries;
gatt->ag_virtual = malloc(entries * sizeof(u_int32_t),
@@ -109,6 +112,8 @@ agp_amd_alloc_gatt(device_t dev)
* Allocate the page directory.
*/
gatt->ag_vdir = malloc(AGP_PAGE_SIZE, M_AGP, M_NOWAIT);
+ bzero(gatt->ag_vdir, AGP_PAGE_SIZE);
+
if (!gatt->ag_vdir) {
if (bootverbose)
device_printf(dev,
@@ -117,22 +122,48 @@ agp_amd_alloc_gatt(device_t dev)
free(gatt, M_AGP);
return 0;
}
- bzero(gatt->ag_vdir, AGP_PAGE_SIZE);
gatt->ag_pdir = vtophys((vm_offset_t) gatt->ag_vdir);
- gatt->ag_pdir = vtophys(gatt->ag_virtual);
+ if(bootverbose)
+ device_printf(dev, "gatt -> ag_pdir %8x\n",
+ (vm_offset_t)gatt->ag_pdir);
+ /*
+ * Allocate the gatt pages
+ */
+ gatt->ag_entries = entries;
+ if(bootverbose)
+ device_printf(dev, "allocating GATT for %d AGP page entries\n",
+ gatt->ag_entries);
+ gatt->ag_virtual = malloc(entries * sizeof(u_int32_t), M_AGP,
+ M_NOWAIT);
+ if(!gatt->ag_virtual) {
+ if(bootverbose)
+ device_printf(dev, "allocation failed\n");
+ free(gatt, M_AGP);
+ return 0;
+ }
+ gatt->ag_physical = vtophys((vm_offset_t) gatt->ag_virtual);
/*
* Map the pages of the GATT into the page directory.
+ *
+ * The GATT page addresses are mapped into the directory offset by
+ * an amount dependent on the base address of the aperture. This
+ * is and offset into the page directory, not an offset added to
+ * the addresses of the gatt pages.
*/
+
+ pdir_offset = pci_read_config(dev, AGP_AMD751_APBASE, 4) >> 22;
+
npages = ((entries * sizeof(u_int32_t) + AGP_PAGE_SIZE - 1)
>> AGP_PAGE_SHIFT);
+
for (i = 0; i < npages; i++) {
vm_offset_t va;
vm_offset_t pa;
va = ((vm_offset_t) gatt->ag_virtual) + i * AGP_PAGE_SIZE;
pa = vtophys(va);
- gatt->ag_vdir[i] = pa | 1;
+ gatt->ag_vdir[i + pdir_offset] = pa | 1;
}
/*
@@ -162,10 +193,16 @@ agp_amd_match(device_t dev)
return NULL;
switch (pci_get_devid(dev)) {
+
case 0x700e1022:
return ("AMD 761 host to AGP bridge");
+
case 0x70061022:
return ("AMD 751 host to AGP bridge");
+
+ case 0x700c1022:
+ return ("AMD 762 host to AGP bridge");
+
};
return NULL;
@@ -304,9 +341,13 @@ agp_amd_set_aperture(device_t dev, u_int32_t aperture)
vas = ffs(aperture / 32*1024*1024) - 1;
+ /*
+ * While the size register is bits 1-3 of APCTRL, bit 0 must be
+ * set for the size value to be 'valid'
+ */
pci_write_config(dev, AGP_AMD751_APCTRL,
- ((pci_read_config(dev, AGP_AMD751_APCTRL, 1) & ~0x06)
- | vas << 1), 1);
+ (((pci_read_config(dev, AGP_AMD751_APCTRL, 1) & ~0x06)
+ | ((vas << 1) | 1))), 1);
return 0;
}
@@ -320,6 +361,9 @@ agp_amd_bind_page(device_t dev, int offset, vm_offset_t physical)
return EINVAL;
sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical | 1;
+
+ /* invalidate the cache */
+ AGP_FLUSH_TLB(dev);
return 0;
}
diff --git a/sys/dev/agp/agpreg.h b/sys/dev/agp/agpreg.h
index 535ae51..13f08e3 100644
--- a/sys/dev/agp/agpreg.h
+++ b/sys/dev/agp/agpreg.h
@@ -89,6 +89,7 @@
/*
* Config offsets for the AMD 751 chipset.
*/
+#define AGP_AMD751_APBASE 0x10
#define AGP_AMD751_REGISTERS 0x14
#define AGP_AMD751_APCTRL 0xac
#define AGP_AMD751_MODECTRL 0xb0
diff --git a/sys/pci/agp_amd.c b/sys/pci/agp_amd.c
index 6ab062b..df27fca 100644
--- a/sys/pci/agp_amd.c
+++ b/sys/pci/agp_amd.c
@@ -59,9 +59,10 @@ MALLOC_DECLARE(M_AGP);
struct agp_amd_gatt {
u_int32_t ag_entries;
+ u_int32_t *ag_virtual; /* virtual address of gatt */
+ vm_offset_t ag_physical;
u_int32_t *ag_vdir; /* virtual address of page dir */
vm_offset_t ag_pdir; /* physical address of page dir */
- u_int32_t *ag_virtual; /* virtual address of gatt */
};
struct agp_amd_softc {
@@ -79,7 +80,7 @@ agp_amd_alloc_gatt(device_t dev)
u_int32_t apsize = AGP_GET_APERTURE(dev);
u_int32_t entries = apsize >> AGP_PAGE_SHIFT;
struct agp_amd_gatt *gatt;
- int i, npages;
+ int i, npages, pdir_offset;
if (bootverbose)
device_printf(dev,
@@ -93,6 +94,8 @@ agp_amd_alloc_gatt(device_t dev)
/*
* The AMD751 uses a page directory to map a non-contiguous
* gatt so we don't need to use contigmalloc.
+ * Malloc individual gatt pages and map them into the page
+ * directory.
*/
gatt->ag_entries = entries;
gatt->ag_virtual = malloc(entries * sizeof(u_int32_t),
@@ -109,6 +112,8 @@ agp_amd_alloc_gatt(device_t dev)
* Allocate the page directory.
*/
gatt->ag_vdir = malloc(AGP_PAGE_SIZE, M_AGP, M_NOWAIT);
+ bzero(gatt->ag_vdir, AGP_PAGE_SIZE);
+
if (!gatt->ag_vdir) {
if (bootverbose)
device_printf(dev,
@@ -117,22 +122,48 @@ agp_amd_alloc_gatt(device_t dev)
free(gatt, M_AGP);
return 0;
}
- bzero(gatt->ag_vdir, AGP_PAGE_SIZE);
gatt->ag_pdir = vtophys((vm_offset_t) gatt->ag_vdir);
- gatt->ag_pdir = vtophys(gatt->ag_virtual);
+ if(bootverbose)
+ device_printf(dev, "gatt -> ag_pdir %8x\n",
+ (vm_offset_t)gatt->ag_pdir);
+ /*
+ * Allocate the gatt pages
+ */
+ gatt->ag_entries = entries;
+ if(bootverbose)
+ device_printf(dev, "allocating GATT for %d AGP page entries\n",
+ gatt->ag_entries);
+ gatt->ag_virtual = malloc(entries * sizeof(u_int32_t), M_AGP,
+ M_NOWAIT);
+ if(!gatt->ag_virtual) {
+ if(bootverbose)
+ device_printf(dev, "allocation failed\n");
+ free(gatt, M_AGP);
+ return 0;
+ }
+ gatt->ag_physical = vtophys((vm_offset_t) gatt->ag_virtual);
/*
* Map the pages of the GATT into the page directory.
+ *
+ * The GATT page addresses are mapped into the directory offset by
+ * an amount dependent on the base address of the aperture. This
+ * is and offset into the page directory, not an offset added to
+ * the addresses of the gatt pages.
*/
+
+ pdir_offset = pci_read_config(dev, AGP_AMD751_APBASE, 4) >> 22;
+
npages = ((entries * sizeof(u_int32_t) + AGP_PAGE_SIZE - 1)
>> AGP_PAGE_SHIFT);
+
for (i = 0; i < npages; i++) {
vm_offset_t va;
vm_offset_t pa;
va = ((vm_offset_t) gatt->ag_virtual) + i * AGP_PAGE_SIZE;
pa = vtophys(va);
- gatt->ag_vdir[i] = pa | 1;
+ gatt->ag_vdir[i + pdir_offset] = pa | 1;
}
/*
@@ -162,10 +193,16 @@ agp_amd_match(device_t dev)
return NULL;
switch (pci_get_devid(dev)) {
+
case 0x700e1022:
return ("AMD 761 host to AGP bridge");
+
case 0x70061022:
return ("AMD 751 host to AGP bridge");
+
+ case 0x700c1022:
+ return ("AMD 762 host to AGP bridge");
+
};
return NULL;
@@ -304,9 +341,13 @@ agp_amd_set_aperture(device_t dev, u_int32_t aperture)
vas = ffs(aperture / 32*1024*1024) - 1;
+ /*
+ * While the size register is bits 1-3 of APCTRL, bit 0 must be
+ * set for the size value to be 'valid'
+ */
pci_write_config(dev, AGP_AMD751_APCTRL,
- ((pci_read_config(dev, AGP_AMD751_APCTRL, 1) & ~0x06)
- | vas << 1), 1);
+ (((pci_read_config(dev, AGP_AMD751_APCTRL, 1) & ~0x06)
+ | ((vas << 1) | 1))), 1);
return 0;
}
@@ -320,6 +361,9 @@ agp_amd_bind_page(device_t dev, int offset, vm_offset_t physical)
return EINVAL;
sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical | 1;
+
+ /* invalidate the cache */
+ AGP_FLUSH_TLB(dev);
return 0;
}
diff --git a/sys/pci/agpreg.h b/sys/pci/agpreg.h
index 535ae51..13f08e3 100644
--- a/sys/pci/agpreg.h
+++ b/sys/pci/agpreg.h
@@ -89,6 +89,7 @@
/*
* Config offsets for the AMD 751 chipset.
*/
+#define AGP_AMD751_APBASE 0x10
#define AGP_AMD751_REGISTERS 0x14
#define AGP_AMD751_APCTRL 0xac
#define AGP_AMD751_MODECTRL 0xb0
OpenPOWER on IntegriCloud