diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/agp/agp_amd.c | 58 | ||||
-rw-r--r-- | sys/dev/agp/agpreg.h | 1 | ||||
-rw-r--r-- | sys/pci/agp_amd.c | 58 | ||||
-rw-r--r-- | sys/pci/agpreg.h | 1 |
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 |