[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[patch] ATI Radeon AGP support



Hi all,

Here's a patch to add AGP support for a few ATI Radeon chipsets (maybe
more later, this was adapted from FreeBSD):

RS100: Radeon IGP320(M)
RS200: Radeon IGP330(M)/IGP340(M)
RS250: Radeon Mobility 7000 IGP
RS300: Radeon 9100 IGP

Since I don't have any ATI hardware, please try this diff out if you
do.  You should see a line in dmesg telling you that your ATI card has
an AGP aperture.  If you can, please send me both a dmesg from before
and after this patch.

If you subsequently start X.org using the radeon(4) driver, you should
be able to verify if the hardware acceleration works properly.  Whether
this works or not :), please mail me the resulting Xorg.log file.

Cheers,
Dimitry

diff -urNd sys.orig/arch/i386/conf/files.i386 sys/arch/i386/conf/files.i386
--- sys.orig/arch/i386/conf/files.i386	Sat Mar  4 17:27:03 2006
+++ sys/arch/i386/conf/files.i386	Sun Mar 12 20:42:00 2006
@@ -100,6 +100,7 @@
 file	arch/i386/pci/agp_machdep.c		pciagp
 file	dev/pci/agp_ali.c			pciagp
 file	dev/pci/agp_amd.c			pciagp
+file	dev/pci/agp_ati.c			pciagp
 file	dev/pci/agp_i810.c			pciagp
 file	dev/pci/agp_intel.c			pciagp
 file	dev/pci/agp_sis.c			pciagp
diff -urNd sys.orig/arch/i386/pci/agp_machdep.c sys/arch/i386/pci/agp_machdep.c
--- sys.orig/arch/i386/pci/agp_machdep.c	Sat Feb 11 22:15:21 2006
+++ sys/arch/i386/pci/agp_machdep.c	Sun Mar 12 13:34:57 2006
@@ -39,6 +39,13 @@
 const struct agp_product agp_products[] = {
 	{ PCI_VENDOR_ALI, -1, agp_ali_attach },
 	{ PCI_VENDOR_AMD, -1, agp_amd_attach },
+	{ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_RS100_AGP, agp_ati_attach },
+	{ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_RS200_AGP, agp_ati_attach },
+	{ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_RS250_AGP, agp_ati_attach },
+	{ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_RS300_100_HB, agp_ati_attach },
+	{ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_RS300_133_HB, agp_ati_attach },
+	{ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_RS300_166_HB, agp_ati_attach },
+	{ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_RADEON_IGP9100_HB, agp_ati_attach },
 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82810_GC, agp_i810_attach },
 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82810_DC100_GC, agp_i810_attach },
 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82810E_GC, agp_i810_attach },
diff -urNd sys.orig/dev/pci/agp_ati.c sys/dev/pci/agp_ati.c
--- sys.orig/dev/pci/agp_ati.c	Thu Jan  1 01:00:00 1970
+++ sys/dev/pci/agp_ati.c	Sun Mar 12 20:36:01 2006
@@ -0,0 +1,299 @@
+/*	$OpenBSD$	*/
+
+/*-
+ * Copyright (c) 2005 Eric Anholt
+ * 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.
+ *
+ * Based on reading the Linux 2.6.8.1 driver by Dave Jones.
+ *
+ *	$FreeBSD: src/sys/pci/agp_ati.c,v 1.2 2005/12/20 21:12:26 jhb Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+#include <sys/agpio.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcidevs.h>
+#include <dev/pci/agpvar.h>
+#include <dev/pci/agpreg.h>
+#include <dev/pci/vga_pcivar.h>
+
+#include <machine/bus.h>
+
+#define READ4(off)	bus_space_read_4(asc->bst, asc->bsh, off)
+#define WRITE4(off,v)	bus_space_write_4(asc->bst, asc->bsh, off, v)
+
+struct agp_ati_gatt {
+	bus_dmamap_t	ag_dmamap;
+	bus_dma_segment_t ag_dmaseg;
+	int		ag_nseg;
+	u_int32_t	ag_entries;
+	u_int32_t      *ag_vdir;	/* virtual address of page dir */
+	bus_addr_t	ag_pdir;	/* bus address of page dir */
+	u_int32_t      *ag_virtual;	/* virtual address of gatt */
+	bus_addr_t	ag_physical;	/* bus address of gatt */
+	size_t		ag_size;
+};
+
+struct agp_ati_softc {
+	bus_space_tag_t	bst;
+	bus_space_handle_t bsh;
+	u_int32_t	initial_aperture;
+	u_int32_t	apsize_reg;
+	struct agp_ati_gatt *gatt;
+};
+
+static u_int32_t agp_ati_get_aperture(struct vga_pci_softc *);
+static int agp_ati_set_aperture(struct vga_pci_softc *, u_int32_t);
+static int agp_ati_bind_page(struct vga_pci_softc *sc, off_t, bus_addr_t);
+static int agp_ati_unbind_page(struct vga_pci_softc *sc, off_t);
+static void agp_ati_flush_tlb(struct vga_pci_softc *sc);
+
+struct agp_methods agp_ati_methods = {
+	agp_ati_get_aperture,
+	agp_ati_set_aperture,
+	agp_ati_bind_page,
+	agp_ati_unbind_page,
+	agp_ati_flush_tlb,
+	agp_generic_enable,
+	agp_generic_alloc_memory,
+	agp_generic_free_memory,
+	agp_generic_bind_memory,
+	agp_generic_unbind_memory
+};
+
+static struct agp_ati_gatt *
+agp_ati_alloc_gatt(struct vga_pci_softc *sc)
+{
+	struct agp_ati_gatt *gatt;
+	u_int32_t entries;
+	size_t size;
+	caddr_t vdir;
+	pcireg_t apbase_offset;
+	int i;
+
+	gatt = malloc(sizeof *gatt, M_DEVBUF, M_NOWAIT);
+	if (gatt == NULL)
+		return (NULL);
+
+	/* Alloc the page directory (pointers to each page of the GATT)
+	 * and GATT (pointers to pages of AGP memory) */
+	entries = AGP_GET_APERTURE(sc) >> AGP_PAGE_SHIFT;
+	size = AGP_PAGE_SIZE + entries * sizeof(u_int32_t);
+	if (agp_alloc_dmamem(sc->sc_dmat, size, 0, &gatt->ag_dmamap, &vdir,
+	    &gatt->ag_pdir, &gatt->ag_dmaseg, 1, &gatt->ag_nseg) != 0) {
+		printf("failed to allocate GATT\n");
+		free(gatt, M_DEVBUF);
+		return (NULL);
+	}
+
+	gatt->ag_vdir = (u_int32_t *)vdir;
+	gatt->ag_entries = entries;
+	gatt->ag_virtual = (u_int32_t *)(vdir + AGP_PAGE_SIZE);
+	gatt->ag_physical = gatt->ag_pdir + AGP_PAGE_SIZE;
+	gatt->ag_size = size;
+
+	memset(gatt->ag_vdir, 0, size);
+
+	apbase_offset = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_APBASE) >> 22;
+	/* Fill in the pagedir's pointers to GATT pages */
+	for (i = 0; i < gatt->ag_entries / 1024; i++) {
+		bus_addr_t pa = gatt->ag_physical + i * AGP_PAGE_SIZE;
+		gatt->ag_vdir[apbase_offset + i] = pa | 1;
+	}
+
+	/*
+	 * Make sure the chipset can see everything.
+	 */
+	agp_flush_cache();
+
+	return (gatt);
+}
+
+#if 0
+static void
+agp_ati_free_gatt(struct vga_pci_softc *sc, struct agp_ati_gatt *gatt)
+{
+	agp_free_dmamem(sc->sc_dmat, gatt->ag_size, gatt->ag_dmamap,
+	    (caddr_t)gatt->ag_virtual, &gatt->ag_dmaseg, gatt->ag_nseg);
+	free(gatt, M_DEVBUF);
+}
+#endif
+
+int
+agp_ati_attach(struct vga_pci_softc *sc, struct pci_attach_args *pa, struct pci_attach_args *pchb_pa)
+{
+	struct agp_ati_softc *asc;
+	int error;
+	pcireg_t reg;
+	u_int32_t agpmode_reg;
+
+	asc = malloc(sizeof *asc, M_DEVBUF, M_NOWAIT);
+	if (asc == NULL) {
+		printf(": can't allocate chipset-specific softc\n");
+		return (ENOMEM);
+	}
+	memset(asc, 0, sizeof *asc);
+	sc->sc_methods = &agp_ati_methods;
+	sc->sc_chipc = asc;
+
+	switch (PCI_PRODUCT(pa->pa_id)) {
+	case PCI_PRODUCT_ATI_RS100_AGP:
+	case PCI_PRODUCT_ATI_RS200_AGP:
+	case PCI_PRODUCT_ATI_RS250_AGP:
+		asc->apsize_reg = ATI_RS100_APSIZE;
+		agpmode_reg = ATI_RS100_IG_AGPMODE;
+		break;
+	case PCI_PRODUCT_ATI_RS300_100_HB:
+	case PCI_PRODUCT_ATI_RS300_133_HB:
+	case PCI_PRODUCT_ATI_RS300_166_HB:
+	case PCI_PRODUCT_ATI_RADEON_IGP9100_HB:
+		asc->apsize_reg = ATI_RS300_APSIZE;
+		agpmode_reg = ATI_RS300_IG_AGPMODE;
+		break;
+	default:
+		printf(": unknown product id %#x\n", PCI_PRODUCT(pa->pa_id));
+		free(asc, M_DEVBUF);
+		sc->sc_chipc = NULL;
+		return (EINVAL);
+	};
+
+	error = pci_mapreg_map(pa, ATI_GART_MMADDR, PCI_MAPREG_TYPE_MEM, 0,
+	    &asc->bst, &asc->bsh, NULL, NULL, 0);
+	if (error != 0) {
+		printf(": can't map mmadr registers\n");
+		free(asc, M_DEVBUF);
+		sc->sc_chipc = NULL;
+		return (error);
+	}
+
+	asc->initial_aperture = AGP_GET_APERTURE(sc);
+
+	for (;;) {
+		asc->gatt = agp_ati_alloc_gatt(sc);
+		if (asc->gatt != NULL)
+			break;
+
+		/*
+		 * Probably contigmalloc failure. Try reducing the
+		 * aperture so that the gatt size reduces.
+		 */
+		if (AGP_SET_APERTURE(sc, AGP_GET_APERTURE(sc) / 2)) {
+			printf(": failed to set aperture\n");
+			free(asc, M_DEVBUF);
+			sc->sc_chipc = NULL;
+			return (ENOMEM);
+		}
+	}
+
+	reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, asc->apsize_reg);
+	pci_conf_write(sc->sc_pc, sc->sc_pcitag, asc->apsize_reg, reg | 1);
+
+	pci_conf_write(sc->sc_pc, sc->sc_pcitag, agpmode_reg, 0x20000);
+
+	WRITE4(ATI_GART_FEATURE_ID, 0x00060000);
+
+	reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, 4); /* XXX: Magic reg# */
+	pci_conf_write(sc->sc_pc, sc->sc_pcitag, 4, reg | (1 << 14));
+
+	WRITE4(ATI_GART_BASE, asc->gatt->ag_pdir);
+
+	AGP_FLUSH_TLB(sc);
+
+	return (0);
+}
+
+static u_int32_t
+agp_ati_get_aperture(struct vga_pci_softc *sc)
+{
+	struct agp_ati_softc *asc = sc->sc_chipc;
+	pcireg_t size_value;
+
+	size_value = pci_conf_read(sc->sc_pc, sc->sc_pcitag, asc->apsize_reg);
+
+	size_value = (size_value & 0x0000000e) >> 1;
+	size_value = (32 * 1024 * 1024) << size_value;
+
+	return (size_value);
+}
+
+static int
+agp_ati_set_aperture(struct vga_pci_softc *sc, u_int32_t aperture)
+{
+	struct agp_ati_softc *asc = sc->sc_chipc;
+	pcireg_t size_value;
+
+	size_value = pci_conf_read(sc->sc_pc, sc->sc_pcitag, asc->apsize_reg);
+
+	size_value &= ~0x0000000e;
+	size_value |= (ffs(aperture / (32 * 1024 * 1024)) - 1) << 1;
+
+	pci_conf_write(sc->sc_pc, sc->sc_pcitag, asc->apsize_reg, size_value);
+
+	return (0);
+}
+
+static int
+agp_ati_bind_page(struct vga_pci_softc *sc, off_t offset, bus_addr_t physical)
+{
+	struct agp_ati_softc *asc = sc->sc_chipc;
+
+	if (offset < 0 || offset >= (asc->gatt->ag_entries << AGP_PAGE_SHIFT))
+		return EINVAL;
+
+	asc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical | 1;
+
+	return (0);
+}
+
+static int
+agp_ati_unbind_page(struct vga_pci_softc *sc, off_t offset)
+{
+	struct agp_ati_softc *asc = sc->sc_chipc;
+
+	if (offset < 0 || offset >= (asc->gatt->ag_entries << AGP_PAGE_SHIFT))
+		return (EINVAL);
+
+	asc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0;
+
+	return (0);
+}
+
+static void
+agp_ati_flush_tlb(struct vga_pci_softc *sc)
+{
+	struct agp_ati_softc *asc = sc->sc_chipc;
+
+	/* Set the cache invalidate bit and wait for the chipset to clear */
+	WRITE4(ATI_GART_CACHE_CNTRL, 1);
+	(void)READ4(ATI_GART_CACHE_CNTRL);
+}
+
diff -urNd sys.orig/dev/pci/agpreg.h sys/dev/pci/agpreg.h
--- sys.orig/dev/pci/agpreg.h	Sat Feb 11 22:15:21 2006
+++ sys/dev/pci/agpreg.h	Sun Mar 12 20:41:17 2006
@@ -203,4 +203,16 @@
 #define AGP_I915_MSAC_GMASIZE_128	0x02
 #define AGP_I915_MSAC_GMASIZE_256	0x00
 
+/*
+ * ATI IGP registers
+ */
+#define ATI_GART_MMADDR		0x14
+#define ATI_RS100_APSIZE	0xac
+#define ATI_RS100_IG_AGPMODE	0xb0
+#define ATI_RS300_APSIZE	0xf8
+#define ATI_RS300_IG_AGPMODE	0xfc
+#define ATI_GART_FEATURE_ID	0x00
+#define ATI_GART_BASE		0x04
+#define ATI_GART_CACHE_CNTRL	0x0c
+
 #endif /* !_PCI_AGPREG_H_ */
diff -urNd sys.orig/dev/pci/agpvar.h sys/dev/pci/agpvar.h
--- sys.orig/dev/pci/agpvar.h	Fri Mar 10 22:52:02 2006
+++ sys/dev/pci/agpvar.h	Sun Mar 12 20:41:35 2006
@@ -110,6 +107,8 @@
 int	agp_ali_attach(struct vga_pci_softc *, struct pci_attach_args *,
 	    struct pci_attach_args *);
 int	agp_amd_attach(struct vga_pci_softc *, struct pci_attach_args *,
+	    struct pci_attach_args *);
+int	agp_ati_attach(struct vga_pci_softc *, struct pci_attach_args *,
 	    struct pci_attach_args *);
 int	agp_i810_attach(struct vga_pci_softc *, struct pci_attach_args *,
 	    struct pci_attach_args *);
diff -urNd sys.orig/dev/pci/pcidevs sys/dev/pci/pcidevs
--- sys.orig/dev/pci/pcidevs	Sat Mar 11 03:08:58 2006
+++ sys/dev/pci/pcidevs	Sun Mar 12 20:45:49 2006
@@ -846,7 +846,9 @@
 product ATI MACH64_VT		0x5654	Mach64 VT
 product ATI MACH64_VU		0x5655	Mach64 VU
 product ATI MACH64_VV		0x5656	Mach64 VV
-product ATI RS300_HB		0x5831	RS300 Host
+product ATI RS300_100_HB	0x5830	RS300_100 Host
+product ATI RS300_133_HB	0x5831	RS300_133 Host
+product ATI RS300_166_HB	0x5832	RS300_166 Host
 product ATI RADEON_IGP9100_HB	0x5833	Radeon IGP 9100 Host
 product ATI RADEON_IGP9100	0x5835	Radeon Mobility IGP 9100
 product ATI RADEON_IGP9100_AGP	0x5838	Radeon IGP 9100 AGP
@@ -886,6 +888,7 @@
 product ATI RS200_PCI		0x7010	RS200 PCI
 product ATI RS100_AGP		0xcab0	RS100 AGP
 product ATI RS200_AGP		0xcab2	RS200 AGP
+product ATI RS250_AGP		0xcab3	RS250 AGP
 
 /* Applied Micro Circuits products */
 product AMCIRCUITS S5933	0x4750	S5933 PCI Matchmaker
diff -urNd sys.orig/dev/pci/pcidevs.h sys/dev/pci/pcidevs.h
--- sys.orig/dev/pci/pcidevs.h	Sat Mar 11 03:09:37 2006
+++ sys/dev/pci/pcidevs.h	Sun Mar 12 19:27:21 2006
@@ -851,7 +851,9 @@
 #define	PCI_PRODUCT_ATI_MACH64_VT	0x5654		/* Mach64 VT */
 #define	PCI_PRODUCT_ATI_MACH64_VU	0x5655		/* Mach64 VU */
 #define	PCI_PRODUCT_ATI_MACH64_VV	0x5656		/* Mach64 VV */
-#define	PCI_PRODUCT_ATI_RS300_HB	0x5831		/* RS300 Host */
+#define	PCI_PRODUCT_ATI_RS300_100_HB	0x5830		/* RS300_100 Host */
+#define	PCI_PRODUCT_ATI_RS300_133_HB	0x5831		/* RS300_133 Host */
+#define	PCI_PRODUCT_ATI_RS300_166_HB	0x5832		/* RS300_166 Host */
 #define	PCI_PRODUCT_ATI_RADEON_IGP9100_HB	0x5833		/* Radeon IGP 9100 Host */
 #define	PCI_PRODUCT_ATI_RADEON_IGP9100	0x5835		/* Radeon Mobility IGP 9100 */
 #define	PCI_PRODUCT_ATI_RADEON_IGP9100_AGP	0x5838		/* Radeon IGP 9100 AGP */
@@ -891,6 +893,7 @@
 #define	PCI_PRODUCT_ATI_RS200_PCI	0x7010		/* RS200 PCI */
 #define	PCI_PRODUCT_ATI_RS100_AGP	0xcab0		/* RS100 AGP */
 #define	PCI_PRODUCT_ATI_RS200_AGP	0xcab2		/* RS200 AGP */
+#define	PCI_PRODUCT_ATI_RS250_AGP	0xcab3		/* RS250 AGP */
 
 /* Applied Micro Circuits products */
 #define	PCI_PRODUCT_AMCIRCUITS_S5933	0x4750		/* S5933 PCI Matchmaker */
diff -urNd sys.orig/dev/pci/pcidevs_data.h sys/dev/pci/pcidevs_data.h
--- sys.orig/dev/pci/pcidevs_data.h	Sat Mar 11 03:09:37 2006
+++ sys/dev/pci/pcidevs_data.h	Sun Mar 12 19:27:21 2006
@@ -1955,10 +1955,18 @@
 	    "Mach64 VV",
 	},
 	{
-	    PCI_VENDOR_ATI, PCI_PRODUCT_ATI_RS300_HB,
-	    "RS300 Host",
+	    PCI_VENDOR_ATI, PCI_PRODUCT_ATI_RS300_100_HB,
+	    "RS300_100 Host",
 	},
 	{
+	    PCI_VENDOR_ATI, PCI_PRODUCT_ATI_RS300_133_HB,
+	    "RS300_133 Host",
+	},
+	{
+	    PCI_VENDOR_ATI, PCI_PRODUCT_ATI_RS300_166_HB,
+	    "RS300_166 Host",
+	},
+	{
 	    PCI_VENDOR_ATI, PCI_PRODUCT_ATI_RADEON_IGP9100_HB,
 	    "Radeon IGP 9100 Host",
 	},
@@ -2113,6 +2121,10 @@
 	{
 	    PCI_VENDOR_ATI, PCI_PRODUCT_ATI_RS200_AGP,
 	    "RS200 AGP",
+	},
+	{
+	    PCI_VENDOR_ATI, PCI_PRODUCT_ATI_RS250_AGP,
+	    "RS250 AGP",
 	},
 	{
 	    PCI_VENDOR_AMCIRCUITS, PCI_PRODUCT_AMCIRCUITS_S5933,



Visit your host, monkey.org