[PATCH] AMD64 On-CPU GART support + more
Jung-uk Kim
jkim at niksun.com
Mon Jun 14 20:48:53 GMT 2004
Since the latest DRM is imported, I made my AMD64 on-CPU GART[1]
working (patch attached). This driver has some ugliness because of
its nature: driver is for AGP bridge but directly touches north
bridge registers (of multiple north bridges if you have multiple
CPUs). Ideally we can attach child driver here for each bridge but
it is just a part of its functions so that I didn't want to create a
full-blown driver. The second ugliness comes from the agp_sis.c and
agp_via.c. They fall back to 'generic host to PCI bridge' if it is
not supported but it finds a bridge. I believe this has to be
removed. The kludge is 'AGP_AMD64_GART' in kernel configuration.
This kludge can be removed when the 'fallback' match/probe is
removed. For now, 'AGP_AMD64_GART' is required to test this driver.
If anyone is interested, please cleanup/fix them. :-(
It's tested with Via K8T800 (both FreeBSD/i386 and FreeBSD/amd64) but
it should work with other bridges/tunnels. XFree86 snapshot (after
Mesa 6.1 import) + DRI snapshot worked fine with MGA 400 and Radeon
RV280 in FreeBSD/i386. In FreeBSD/amd64, MGA 400 works but Radeon
RV280 doesn't work but I believe it's DRM/DRI's problem, i. e.,
Radeon SAREA handles.
Cheers,
Jung-uk Kim
[1] BIOS and Kernel Developer's Guide for AMD Athlon? 64 and AMD
Opteron(tm) Processors (3.6.12-15)
http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/26094.PDF
* PS: I think the current agp_via.c doesn't support K8T800 or other
AGP v3 bridges correctly. If anyone is interested, let me know. ;-)
-------------- next part --------------
--- src/sys/conf/files.amd64.orig Mon May 24 08:08:56 2004
+++ src/sys/conf/files.amd64 Mon Jun 14 16:05:45 2004
@@ -133,6 +133,7 @@
kern/link_elf_obj.c standard
pci/agp_ali.c optional agp
pci/agp_amd.c optional agp
+pci/agp_amd64.c optional agp
pci/agp_i810.c optional agp
pci/agp_intel.c optional agp
pci/agp_sis.c optional agp
--- src/sys/conf/files.i386.orig Wed May 26 03:43:40 2004
+++ src/sys/conf/files.i386 Mon Jun 14 16:05:45 2004
@@ -411,6 +411,7 @@
libkern/umoddi3.c standard
pci/agp_ali.c optional agp
pci/agp_amd.c optional agp
+pci/agp_amd64.c optional agp
pci/agp_i810.c optional agp
pci/agp_intel.c optional agp
pci/agp_nvidia.c optional agp
--- src/sys/conf/options.amd64.orig Sat Mar 13 17:16:34 2004
+++ src/sys/conf/options.amd64 Mon Jun 14 16:05:45 2004
@@ -54,3 +54,6 @@
IA32
NO_MIXED_MODE
DEV_ATPIC opt_atpic.h
+
+# agp options
+AGP_AMD64_GART opt_agp.h
--- src/sys/conf/options.i386.orig Sun Mar 14 18:03:56 2004
+++ src/sys/conf/options.i386 Mon Jun 14 16:05:45 2004
@@ -161,3 +161,6 @@
# Device options
DEV_APIC opt_apic.h
DEV_NPX opt_npx.h
+
+# agp options
+AGP_AMD64_GART opt_agp.h
--- src/sys/modules/Makefile.orig Mon May 17 10:22:40 2004
+++ src/sys/modules/Makefile Mon Jun 14 16:06:00 2004
@@ -377,6 +377,8 @@
.endif
.if ${MACHINE_ARCH} == "amd64"
+_agp= agp
+_drm= drm
#_ndis= ndis
.endif
--- src/sys/modules/agp/Makefile.orig Sat Aug 23 14:00:31 2003
+++ src/sys/modules/agp/Makefile Mon Jun 14 16:05:45 2004
@@ -6,10 +6,13 @@
SRCS= agp.c agp_if.c
.if ${MACHINE_ARCH} == "i386"
SRCS+= agp_i810.c agp_intel.c agp_via.c agp_sis.c agp_ali.c agp_amd.c \
- agp_nvidia.c
+ agp_amd64.c agp_nvidia.c opt_agp.h
.endif
.if ${MACHINE_ARCH} == "alpha"
SRCS+= agp_amd.c
+.endif
+.if ${MACHINE_ARCH} == "amd64"
+SRCS+= agp_amd64.c opt_agp.h
.endif
SRCS+= device_if.h bus_if.h agp_if.h pci_if.h
SRCS+= opt_bdg.h opt_bus.h
--- src/sys/pci/agp.c.orig Sun May 30 16:00:40 2004
+++ src/sys/pci/agp.c Mon Jun 14 16:05:45 2004
@@ -87,7 +87,7 @@
void
agp_flush_cache()
{
-#ifdef __i386__
+#if defined(__i386__) || defined(__amd64__)
wbinvd();
#endif
#ifdef __alpha__
--- src/sys/pci/agp_amd64.c.orig Mon Jun 7 23:42:04 2004
+++ src/sys/pci/agp_amd64.c Mon Jun 14 16:05:45 2004
@@ -0,0 +1,315 @@
+/*-
+ * Copyright (c) 2004 Jung-uk Kim
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_bus.h"
+#include "opt_agp.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <pci/agppriv.h>
+#include <pci/agpreg.h>
+
+#include <vm/vm.h>
+#include <vm/vm_object.h>
+#include <vm/pmap.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+/* XXX */
+extern void pci_cfgregwrite(int, int, int, int, uint32_t, int);
+extern uint32_t pci_cfgregread(int, int, int, int, int);
+
+MALLOC_DECLARE(M_AGP);
+
+#define AMD64_MAX_MCTRL 8
+
+struct agp_amd64_softc {
+ struct agp_softc agp;
+ uint32_t initial_aperture; /* aperture size at startup */
+ struct agp_gatt *gatt;
+ int mctrl[AMD64_MAX_MCTRL];
+ int n_mctrl;
+};
+
+static const char*
+agp_amd64_match(device_t dev)
+{
+ if (pci_get_class(dev) != PCIC_BRIDGE
+ || pci_get_subclass(dev) != PCIS_BRIDGE_HOST)
+ return NULL;
+
+ if (agp_find_caps(dev) == 0)
+ return NULL;
+
+#ifdef AGP_AMD64_GART
+ switch (pci_get_devid(dev)) {
+ case 0x74541022:
+ return ("AMD 8151 AGP graphics tunnel");
+ case 0x10221039:
+ return ("SiS 755 host to AGP bridge");
+ case 0x02041106:
+ return ("VIA 8380 host to PCI bridge");
+ case 0x31881106:
+ return ("VIA 8385 host to PCI bridge");
+ };
+#endif
+
+ return NULL;
+}
+
+static int
+agp_amd64_probe(device_t dev)
+{
+ const char *desc;
+
+ if (resource_disabled("agp", device_get_unit(dev)))
+ return (ENXIO);
+ desc = agp_amd64_match(dev);
+ if (desc) {
+ device_verbose(dev);
+ device_set_desc(dev, desc);
+ return 0;
+ }
+
+ return ENXIO;
+}
+
+static int
+agp_amd64_attach(device_t dev)
+{
+ struct agp_amd64_softc *sc = device_get_softc(dev);
+ struct agp_gatt *gatt;
+ int i, n, error;
+
+ for (i = 0, n = 0; i < PCI_SLOTMAX && n < AMD64_MAX_MCTRL; i++)
+ if (pci_cfgregread(0, i, 3, 0, 4) == 0x11031022) {
+ sc->mctrl[n] = i;
+ n++;
+ }
+
+ if (n == 0)
+ return ENXIO;
+
+ sc->n_mctrl = n;
+
+ if (bootverbose)
+ printf("AMD64: %d Misc. Control unit(s) found.\n",
+ sc->n_mctrl);
+
+ error = agp_generic_attach(dev);
+ if (error)
+ return error;
+
+ sc->initial_aperture = AGP_GET_APERTURE(dev);
+
+ for (;;) {
+ gatt = agp_alloc_gatt(dev);
+ if (gatt)
+ break;
+
+ /*
+ * Probably contigmalloc failure. Try reducing the
+ * aperture so that the gatt size reduces.
+ */
+ if (AGP_SET_APERTURE(dev, AGP_GET_APERTURE(dev) / 2)) {
+ agp_generic_detach(dev);
+ return ENOMEM;
+ }
+ }
+ sc->gatt = gatt;
+
+ /* Install the gatt and enable aperture. */
+ for (i = 0; i < sc->n_mctrl; i++) {
+ pci_cfgregwrite(0, sc->mctrl[i], 3, AGP_AMD64_ATTBASE,
+ (uint32_t)(gatt->ag_physical >> 8) & AGP_AMD64_ATTBASE_MASK,
+ 4);
+ pci_cfgregwrite(0, sc->mctrl[i], 3, AGP_AMD64_APCTRL,
+ (pci_cfgregread(0, sc->mctrl[i], 3, AGP_AMD64_APCTRL, 4) |
+ AGP_AMD64_APCTRL_GARTEN) &
+ ~(AGP_AMD64_APCTRL_DISGARTCPU | AGP_AMD64_APCTRL_DISGARTIO),
+ 4);
+ }
+
+ agp_flush_cache();
+
+ return 0;
+}
+
+static int
+agp_amd64_detach(device_t dev)
+{
+ struct agp_amd64_softc *sc = device_get_softc(dev);
+ int i, error;
+
+ error = agp_generic_detach(dev);
+ if (error)
+ return error;
+
+ for (i = 0; i < sc->n_mctrl; i++)
+ pci_cfgregwrite(0, sc->mctrl[i], 3, AGP_AMD64_APCTRL,
+ pci_cfgregread(0, sc->mctrl[i], 3, AGP_AMD64_APCTRL, 4) &
+ ~AGP_AMD64_APCTRL_GARTEN, 4);
+
+ AGP_SET_APERTURE(dev, sc->initial_aperture);
+ agp_free_gatt(sc->gatt);
+
+ return 0;
+}
+
+static uint32_t agp_amd64_table[] = {
+ 0x02000000, /* 32 MB */
+ 0x04000000, /* 64 MB */
+ 0x08000000, /* 128 MB */
+ 0x10000000, /* 256 MB */
+ 0x20000000, /* 512 MB */
+ 0x40000000, /* 1024 MB */
+ 0x80000000, /* 2048 MB */
+};
+
+#define AGP_AMD64_TABLE_SIZE \
+ (sizeof(agp_amd64_table) / sizeof(agp_amd64_table[0]))
+
+static uint32_t
+agp_amd64_get_aperture(device_t dev)
+{
+ struct agp_amd64_softc *sc = device_get_softc(dev);
+ uint32_t i;
+
+ i = (pci_cfgregread(0, sc->mctrl[0], 3, AGP_AMD64_APCTRL, 4) &
+ AGP_AMD64_APCTRL_SIZE_MASK) >> 1;
+
+ if (i >= AGP_AMD64_TABLE_SIZE)
+ return 0;
+
+ return (agp_amd64_table[i]);
+}
+
+static int
+agp_amd64_set_aperture(device_t dev, uint32_t aperture)
+{
+ struct agp_amd64_softc *sc = device_get_softc(dev);
+ uint32_t i;
+ int j;
+
+ for (i = 0; i < AGP_AMD64_TABLE_SIZE; i++)
+ if (agp_amd64_table[i] == aperture)
+ break;
+ if (i == AGP_AMD64_TABLE_SIZE)
+ return EINVAL;
+
+ for (j = 0; j < sc->n_mctrl; j++)
+ pci_cfgregwrite(0, sc->mctrl[j], 3, AGP_AMD64_APCTRL,
+ (pci_cfgregread(0, sc->mctrl[j], 3, AGP_AMD64_APCTRL, 4) &
+ ~(AGP_AMD64_APCTRL_SIZE_MASK)) | (i << 1), 4);
+
+ return 0;
+}
+
+static int
+agp_amd64_bind_page(device_t dev, int offset, vm_offset_t physical)
+{
+ struct agp_amd64_softc *sc = device_get_softc(dev);
+
+ if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ return EINVAL;
+
+ sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical;
+ return 0;
+}
+
+static int
+agp_amd64_unbind_page(device_t dev, int offset)
+{
+ struct agp_amd64_softc *sc = device_get_softc(dev);
+
+ if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ return EINVAL;
+
+ sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0;
+ return 0;
+}
+
+static void
+agp_amd64_flush_tlb(device_t dev)
+{
+ struct agp_amd64_softc *sc = device_get_softc(dev);
+ int i;
+
+ for (i = 0; i < sc->n_mctrl; i++)
+ pci_cfgregwrite(0, sc->mctrl[i], 3, AGP_AMD64_CACHECTRL,
+ pci_cfgregread(0, sc->mctrl[i], 3, AGP_AMD64_CACHECTRL, 4) |
+ AGP_AMD64_CACHECTRL_INVGART, 4);
+}
+
+static device_method_t agp_amd64_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, agp_amd64_probe),
+ DEVMETHOD(device_attach, agp_amd64_attach),
+ DEVMETHOD(device_detach, agp_amd64_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ /* AGP interface */
+ DEVMETHOD(agp_get_aperture, agp_amd64_get_aperture),
+ DEVMETHOD(agp_set_aperture, agp_amd64_set_aperture),
+ DEVMETHOD(agp_bind_page, agp_amd64_bind_page),
+ DEVMETHOD(agp_unbind_page, agp_amd64_unbind_page),
+ DEVMETHOD(agp_flush_tlb, agp_amd64_flush_tlb),
+ DEVMETHOD(agp_enable, agp_generic_enable),
+ DEVMETHOD(agp_alloc_memory, agp_generic_alloc_memory),
+ DEVMETHOD(agp_free_memory, agp_generic_free_memory),
+ DEVMETHOD(agp_bind_memory, agp_generic_bind_memory),
+ DEVMETHOD(agp_unbind_memory, agp_generic_unbind_memory),
+
+ { 0, 0 }
+};
+
+static driver_t agp_amd64_driver = {
+ "agp",
+ agp_amd64_methods,
+ sizeof(struct agp_amd64_softc),
+};
+
+static devclass_t agp_devclass;
+
+DRIVER_MODULE(agp_amd64, pci, agp_amd64_driver, agp_devclass, 0, 0);
+MODULE_DEPEND(agp_amd64, agp, 1, 1, 1);
+MODULE_DEPEND(agp_amd64, pci, 1, 1, 1);
--- src/sys/pci/agp_sis.c.orig Sun May 30 16:00:40 2004
+++ src/sys/pci/agp_sis.c Mon Jun 14 16:05:45 2004
@@ -28,6 +28,7 @@
__FBSDID("$FreeBSD: src/sys/pci/agp_sis.c,v 1.13 2004/05/30 20:00:40 phk Exp $");
#include "opt_bus.h"
+#include "opt_agp.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -105,6 +106,10 @@
return ("SiS 746 host to AGP bridge");
case 0x07601039:
return ("SiS 760 host to AGP bridge");
+#ifdef AGP_AMD64_GART
+ case 0x10221039:
+ return NULL;
+#endif
};
if (pci_get_vendor(dev) == 0x1039)
--- src/sys/pci/agp_via.c.orig Mon Jun 14 16:09:52 2004
+++ src/sys/pci/agp_via.c Mon Jun 14 16:09:07 2004
@@ -88,7 +88,11 @@
case 0x06911106:
return ("VIA 82C691 (Apollo Pro) host to PCI bridge");
case 0x31881106:
+#ifdef AGP_AMD64_GART
+ return NULL;
+#else
return ("VIA 8385 host to PCI bridge");
+#endif
};
if (pci_get_vendor(dev) == 0x1106)
--- src/sys/pci/agpreg.h.orig Thu May 13 16:05:42 2004
+++ src/sys/pci/agpreg.h Mon Jun 14 16:05:45 2004
@@ -244,4 +244,21 @@
#define AGP_NVIDIA_3_APBASE 0x50
#define AGP_NVIDIA_3_APLIMIT 0x54
+/*
+ * AMD64 GART registers
+ */
+#define AGP_AMD64_APCTRL 0x90
+#define AGP_AMD64_APBASE 0x94
+#define AGP_AMD64_ATTBASE 0x98
+#define AGP_AMD64_CACHECTRL 0x9c
+#define AGP_AMD64_APCTRL_GARTEN 0x00000001
+#define AGP_AMD64_APCTRL_SIZE_MASK 0x0000000e
+#define AGP_AMD64_APCTRL_DISGARTCPU 0x00000010
+#define AGP_AMD64_APCTRL_DISGARTIO 0x00000020
+#define AGP_AMD64_APCTRL_DISWLKPRB 0x00000040
+#define AGP_AMD64_APBASE_MASK 0x00007fff
+#define AGP_AMD64_ATTBASE_MASK 0xfffffff0
+#define AGP_AMD64_CACHECTRL_INVGART 0x00000001
+#define AGP_AMD64_CACHECTRL_PTEERR 0x00000002
+
#endif /* !_PCI_AGPREG_H_ */
More information about the freebsd-amd64
mailing list