[patch] ATI Radeon AGP support

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[patch] ATI Radeon AGP support

dimitry (Bugzilla)
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,

Reply | Threaded
Open this post in threaded view
|

Re: [patch] ATI Radeon AGP support

dimitry (Bugzilla)
Dimitry Andric wrote:
> Here's a patch to add AGP support for a few ATI Radeon chipsets

Please note this is for ATI motherboard chipsets, NOT to support ATI
video cards in general!  For instance, if you plug your ATI card into
an Intel AGP slot, it should already work properly, and you don't need
this diff at all.

You only need this diff if you have onboard ATI chipset hardware, and
specifically those IGPxxx chipsets.  These will mostly be on laptops, I
suppose.

Cheers,
Dimitry