diff options
author | dfr <dfr@FreeBSD.org> | 2000-06-10 17:44:53 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 2000-06-10 17:44:53 +0000 |
commit | 52b31c00bbaa851d76d91e89090c45135cf24174 (patch) | |
tree | 598ef00e6b366a21e85f5528d5393bad5d59b0b2 /sys/dev | |
parent | 7946f9a6632feedb8b99ff54ccdfff624d81330b (diff) | |
download | FreeBSD-src-52b31c00bbaa851d76d91e89090c45135cf24174.zip FreeBSD-src-52b31c00bbaa851d76d91e89090c45135cf24174.tar.gz |
Fix the AMD 751 AGP minidriver so that it works with my test code.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/agp/agp.c | 6 | ||||
-rw-r--r-- | sys/dev/agp/agp_amd.c | 108 | ||||
-rw-r--r-- | sys/dev/agp/agppriv.h | 1 | ||||
-rw-r--r-- | sys/dev/agp/agpreg.h | 5 |
4 files changed, 112 insertions, 8 deletions
diff --git a/sys/dev/agp/agp.c b/sys/dev/agp/agp.c index e1d6583..0916e70 100644 --- a/sys/dev/agp/agp.c +++ b/sys/dev/agp/agp.c @@ -90,9 +90,13 @@ static devclass_t agp_devclass; /* Helper functions for implementing chipset mini drivers. */ +void +agp_flush_cache() +{ #ifdef __i386__ -#define agp_flush_cache() wbinvd() + wbinvd(); #endif +} u_int8_t agp_find_caps(device_t dev) diff --git a/sys/dev/agp/agp_amd.c b/sys/dev/agp/agp_amd.c index 112918a..16125fb 100644 --- a/sys/dev/agp/agp_amd.c +++ b/sys/dev/agp/agp_amd.c @@ -49,20 +49,107 @@ #include <machine/resource.h> #include <sys/rman.h> +MALLOC_DECLARE(M_AGP); + #define READ2(off) bus_space_read_2(sc->bst, sc->bsh, off) #define READ4(off) bus_space_read_4(sc->bst, sc->bsh, off) #define WRITE2(off,v) bus_space_write_2(sc->bst, sc->bsh, off, v) #define WRITE4(off,v) bus_space_write_4(sc->bst, sc->bsh, off, v) +struct agp_amd_gatt { + u_int32_t ag_entries; + 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 { struct agp_softc agp; struct resource *regs; /* memory mapped control registers */ bus_space_tag_t bst; /* bus_space tag */ bus_space_handle_t bsh; /* bus_space handle */ u_int32_t initial_aperture; /* aperture size at startup */ - struct agp_gatt *gatt; + struct agp_amd_gatt *gatt; }; +static struct agp_amd_gatt * +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; + + if (bootverbose) + device_printf(dev, + "allocating GATT for aperture of size %dM\n", + apsize / (1024*1024)); + + gatt = malloc(sizeof(struct agp_amd_gatt), M_AGP, M_NOWAIT); + if (!gatt) + return 0; + + /* + * The AMD751 uses a page directory to map a non-contiguous + * gatt so we don't need to use contigmalloc. + */ + gatt->ag_entries = 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; + } + bzero(gatt->ag_virtual, entries * sizeof(u_int32_t)); + + /* + * Allocate the page directory. + */ + gatt->ag_vdir = malloc(AGP_PAGE_SIZE, M_AGP, M_NOWAIT); + if (!gatt->ag_vdir) { + if (bootverbose) + device_printf(dev, + "failed to allocate page directory\n"); + free(gatt->ag_virtual, M_AGP); + 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); + + /* + * Map the pages of the GATT into the page directory. + */ + 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; + } + + /* + * Make sure the chipset can see everything. + */ + agp_flush_cache(); + + return gatt; +} + +static void +agp_amd_free_gatt(struct agp_amd_gatt *gatt) +{ + free(gatt->ag_virtual, M_AGP); + free(gatt->ag_vdir, M_AGP); + free(gatt, M_AGP); +} + static const char* agp_amd_match(device_t dev) { @@ -100,7 +187,7 @@ static int agp_amd_attach(device_t dev) { struct agp_amd_softc *sc = device_get_softc(dev); - struct agp_gatt *gatt; + struct agp_amd_gatt *gatt; int error, rid; error = agp_generic_attach(dev); @@ -121,7 +208,7 @@ agp_amd_attach(device_t dev) sc->initial_aperture = AGP_GET_APERTURE(dev); for (;;) { - gatt = agp_alloc_gatt(dev); + gatt = agp_amd_alloc_gatt(dev); if (gatt) break; @@ -135,17 +222,24 @@ agp_amd_attach(device_t dev) sc->gatt = gatt; /* Install the gatt. */ - WRITE4(AGP_AMD751_ATTBASE, gatt->ag_physical); + WRITE4(AGP_AMD751_ATTBASE, gatt->ag_pdir); /* Enable synchronisation between host and agp. */ - pci_write_config(dev, AGP_AMD751_MODECTRL, 0x80, 1); + pci_write_config(dev, + AGP_AMD751_MODECTRL, + AGP_AMD751_MODECTRL_SYNEN, 1); + + /* Set indexing mode for two-level and enable page dir cache */ + pci_write_config(dev, + AGP_AMD751_MODECTRL2, + AGP_AMD751_MODECTRL2_GPDCE, 1); /* Enable the TLB and flush */ WRITE2(AGP_AMD751_STATUS, READ2(AGP_AMD751_STATUS) | AGP_AMD751_STATUS_GCE); AGP_FLUSH_TLB(dev); - return agp_generic_attach(dev); + return 0; } static int @@ -166,7 +260,7 @@ agp_amd_detach(device_t dev) /* Put the aperture back the way it started. */ AGP_SET_APERTURE(dev, sc->initial_aperture); - agp_free_gatt(sc->gatt); + agp_amd_free_gatt(sc->gatt); return 0; } diff --git a/sys/dev/agp/agppriv.h b/sys/dev/agp/agppriv.h index 427e68b..59f4d6d 100644 --- a/sys/dev/agp/agppriv.h +++ b/sys/dev/agp/agppriv.h @@ -84,6 +84,7 @@ struct agp_gatt { vm_offset_t ag_physical; }; +void agp_flush_cache(void); u_int8_t agp_find_caps(device_t dev); struct agp_gatt *agp_alloc_gatt(device_t dev); void agp_free_gatt(struct agp_gatt *gatt); diff --git a/sys/dev/agp/agpreg.h b/sys/dev/agp/agpreg.h index 0539325..79dab08 100644 --- a/sys/dev/agp/agpreg.h +++ b/sys/dev/agp/agpreg.h @@ -84,6 +84,11 @@ #define AGP_AMD751_REGISTERS 0x14 #define AGP_AMD751_APCTRL 0xac #define AGP_AMD751_MODECTRL 0xb0 +#define AGP_AMD751_MODECTRL_SYNEN 0x80 +#define AGP_AMD751_MODECTRL2 0xb2 +#define AGP_AMD751_MODECTRL2_G1LM 0x01 +#define AGP_AMD751_MODECTRL2_GPDCE 0x02 +#define AGP_AMD751_MODECTRL2_NGSE 0x08 /* * Memory mapped register offsets for AMD 751 chipset. |