summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerome Glisse <jglisse@redhat.com>2011-10-27 13:23:21 -0400
committerJerome Glisse <jglisse@redhat.com>2011-10-27 13:23:21 -0400
commitd667313dbea67c4b2067e4220bd7fa1f81f6e1bb (patch)
tree359cd425e4c7ecefee2deafe064d4bf51ce21d8f
parentdf6292fb9cbb927505d864367734649016cf39f4 (diff)
revenge: r600 supportHEADmaster
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile.in9
-rw-r--r--src/revenge_detect.c65
-rw-r--r--src/revenge_detect.h16
-rw-r--r--src/revenge_dump.c11
-rw-r--r--src/revenge_dump_r600.c129
-rw-r--r--src/revenge_main.c44
-rw-r--r--src/revenge_main.h4
-rw-r--r--src/revenge_memory.h1
-rw-r--r--src/revenge_memory_r600.c136
10 files changed, 395 insertions, 22 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index aef80f0..5ffb090 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -62,12 +62,14 @@ revenge_SOURCES = \
revenge_detect.c \
revenge_detect.h \
revenge_dump.c \
+ revenge_dump_r600.c \
revenge_dump.h \
revenge_dump_misc.c \
revenge_dump_misc.h \
revenge_main.c \
revenge_main.h \
revenge_memory.c \
+ revenge_memory_r600.c \
revenge_memory.h \
revenge_register.c \
revenge_register.h \
diff --git a/src/Makefile.in b/src/Makefile.in
index b0a1f9f..ff345fb 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -60,8 +60,9 @@ am_revenge_OBJECTS = gl_alpha_test.$(OBJEXT) gl_blend.$(OBJEXT) \
gl_texture_mag_filter.$(OBJEXT) \
gl_texture_min_filter.$(OBJEXT) gl_texture_wrap_s.$(OBJEXT) \
gl_texture_wrap_t.$(OBJEXT) revenge_detect.$(OBJEXT) \
- revenge_dump.$(OBJEXT) revenge_dump_misc.$(OBJEXT) \
- revenge_main.$(OBJEXT) revenge_memory.$(OBJEXT) \
+ revenge_dump.$(OBJEXT) revenge_dump_r600.$(OBJEXT) \
+ revenge_dump_misc.$(OBJEXT) revenge_main.$(OBJEXT) \
+ revenge_memory.$(OBJEXT) revenge_memory_r600.$(OBJEXT) \
revenge_register.$(OBJEXT) revenge_test.$(OBJEXT)
revenge_OBJECTS = $(am_revenge_OBJECTS)
revenge_LDADD = $(LDADD)
@@ -247,12 +248,14 @@ revenge_SOURCES = \
revenge_detect.c \
revenge_detect.h \
revenge_dump.c \
+ revenge_dump_r600.c \
revenge_dump.h \
revenge_dump_misc.c \
revenge_dump_misc.h \
revenge_main.c \
revenge_main.h \
revenge_memory.c \
+ revenge_memory_r600.c \
revenge_memory.h \
revenge_register.c \
revenge_register.h \
@@ -371,8 +374,10 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/revenge_detect.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/revenge_dump.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/revenge_dump_misc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/revenge_dump_r600.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/revenge_main.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/revenge_memory.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/revenge_memory_r600.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/revenge_register.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/revenge_test.Po@am__quote@
diff --git a/src/revenge_detect.c b/src/revenge_detect.c
index 02bec9b..046dfd7 100644
--- a/src/revenge_detect.c
+++ b/src/revenge_detect.c
@@ -32,13 +32,14 @@
unsigned int agp_addr = 0;
unsigned int agp_len = 0;
-unsigned int fb_addr = 0;
-unsigned int fb_len = 0;
+unsigned long fb_addr = 0;
+unsigned long fb_len = 0;
+unsigned long fb_addr_gpu = 0;
-unsigned int pcigart_addr = 0;
-unsigned int pcigart_end = 0;
-unsigned int pcigart_len = 0;
-unsigned int pcigart_start = 0;
+unsigned long pcigart_addr = 0;
+unsigned long pcigart_end = 0;
+unsigned long pcigart_len = 0;
+unsigned long pcigart_start = 0;
char reg_device_name[BUFSIZ];
unsigned int reg_addr = 0;
@@ -131,11 +132,29 @@ detect_fb_aperture (void)
if (option_debug)
{
- printf ("%s: fb_addr = 0x%08x fb_len = 0x%08x\n", __func__, fb_addr,
+ printf ("%s: fb_addr = 0x%016lx fb_len = 0x%016lx\n", __func__, fb_addr,
fb_len);
}
}
+#define R600_MC_VM_FB_LOCATION 0x2180
+void detect_r600_fb_aperture (void)
+{
+ fb_addr_gpu = (register_read(R600_MC_VM_FB_LOCATION) & 0xffff) << 24;
+ if (option_debug) {
+ printf("%s: fb_addr = 0x%016lx fb_len = 0x%016lx\n", __func__, fb_addr, fb_len);
+ }
+}
+
+#define EG_MC_VM_FB_LOCATION 0x2024
+void detect_evergreen_fb_aperture (void)
+{
+ fb_addr_gpu = (register_read(EG_MC_VM_FB_LOCATION) & 0xffff) << 24;
+ if (option_debug) {
+ printf("%s: fb_addr = 0x%016lx fb_len = 0x%016lx\n", __func__, fb_addr, fb_len);
+ }
+}
+
void
detect_pciegart_aperture (void)
{
@@ -147,7 +166,7 @@ detect_pciegart_aperture (void)
if (option_debug)
{
printf
- ("%s: pcigart_addr = 0x%08x pcigart_len = 0x%08x pcigart_start = 0x%08x pcigart_end = 0x%08x\n",
+ ("%s: pcigart_addr = 0x%016lx pcigart_len = 0x%016lx pcigart_start = 0x%016lx pcigart_end = 0x%016lx\n",
__func__, pcigart_addr, pcigart_len, pcigart_start, pcigart_end);
}
}
@@ -165,11 +184,30 @@ detect_rs690gart_aperture (void)
if (option_debug)
{
printf
- ("%s: pcigart_addr = 0x%08x pcigart_len = 0x%08x pcigart_start = 0x%08x pcigart_end = 0x%08x\n",
+ ("%s: pcigart_addr = 0x%016lx pcigart_len = 0x%016lx pcigart_start = 0x%016lx pcigart_end = 0x%016lx\n",
__func__, pcigart_addr, pcigart_len, pcigart_start, pcigart_end);
}
}
+#define VM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x1574
+#define VM_CONTEXT0_PAGE_TABLE_START_ADDR 0x1594
+#define VM_CONTEXT0_PAGE_TABLE_END_ADDR 0x15B4
+
+void
+detect_r600_aperture (void)
+{
+ pcigart_addr = register_read(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR) << 12;
+ pcigart_start = register_read(VM_CONTEXT0_PAGE_TABLE_START_ADDR) << 12;
+ pcigart_end = register_read(VM_CONTEXT0_PAGE_TABLE_END_ADDR) << 12;
+ pcigart_len = pcigart_end - pcigart_start;
+ pcigart_addr -= fb_addr_gpu;
+
+ if (option_debug) {
+ printf("%s: pcigart_addr = 0x%016lx pcigart_len = 0x%016lx pcigart_start = 0x%016lx pcigart_end = 0x%016lx\n",
+ __func__, pcigart_addr, pcigart_len, pcigart_start, pcigart_end);
+ }
+}
+
void
detect_igpgart_aperture (void)
{
@@ -185,7 +223,7 @@ detect_igpgart_aperture (void)
if (option_debug)
{
printf
- ("%s: pcigart_addr = 0x%08x pcigart_len = 0x%08x pcigart_start = 0x%08x pcigart_end = 0x%08x\n",
+ ("%s: pcigart_addr = 0x%08lx pcigart_len = 0x%08lx pcigart_start = 0x%08lx pcigart_end = 0x%08lx\n",
__func__, pcigart_addr, pcigart_len, pcigart_start, pcigart_end);
}
}
@@ -247,6 +285,11 @@ detect_reg_aperture (void)
get_conf_long (pci_config,
PCI_BASE_ADDRESS_0 + (4 * i));
+fprintf(stderr, "[%d] 0x%lX %d\n", i, pdev->base_addr[i], pdev->size[i]);
+ if (pdev->size[i] > (4 * 1024 * 1024)) {
+ fb_addr = pdev->base_addr[i] & PCI_ADDR_MEM_MASK;
+ fb_len = pdev->size[i];
+ }
if (!(flag & PCI_BASE_ADDRESS_SPACE_IO))
{
addr = pdev->base_addr[i] & PCI_ADDR_MEM_MASK;
@@ -254,7 +297,7 @@ detect_reg_aperture (void)
device_id = pdev->device_id;
if (!(flag & PCI_BASE_ADDRESS_MEM_PREFETCH)
- && len == 64 * 1024)
+ && len >= 64 * 1024 && i == 2)
{
reg_addr = (unsigned int) addr;
reg_len = (unsigned int) len;
diff --git a/src/revenge_detect.h b/src/revenge_detect.h
index 31d71f9..831b957 100644
--- a/src/revenge_detect.h
+++ b/src/revenge_detect.h
@@ -25,12 +25,13 @@
extern unsigned int agp_addr;
extern unsigned int agp_len;
-extern unsigned int fb_addr;
-extern unsigned int fb_len;
-extern unsigned int pcigart_addr;
-extern unsigned int pcigart_end;
-extern unsigned int pcigart_len;
-extern unsigned int pcigart_start;
+extern unsigned long fb_addr;
+extern unsigned long fb_len;
+extern unsigned long fb_addr_gpu;
+extern unsigned long pcigart_addr;
+extern unsigned long pcigart_end;
+extern unsigned long pcigart_len;
+extern unsigned long pcigart_start;
extern char reg_device_name[BUFSIZ];
extern unsigned int reg_addr;
extern unsigned int reg_device_id;
@@ -38,8 +39,11 @@ extern unsigned int reg_len;
extern int gl_max_texture_units;
void detect_agp_aperture (void);
void detect_fb_aperture (void);
+void detect_r600_fb_aperture (void);
+void detect_evergreen_fb_aperture (void);
void detect_pciegart_aperture (void);
void detect_rs690gart_aperture (void);
+void detect_r600_aperture (void);
void detect_igpgart_aperture (void);
void detect_reg_aperture (void);
void detect_max_texture_units (void);
diff --git a/src/revenge_dump.c b/src/revenge_dump.c
index 853c14e..841e898 100644
--- a/src/revenge_dump.c
+++ b/src/revenge_dump.c
@@ -228,9 +228,16 @@ dump_ib (void)
}
}
+void dump_r600_rb_pre(void);
+void dump_r600_rb_post(void);
+
void
dump_rb_pre (void)
{
+ if (option_interface >= INTERFACE_R600) {
+ dump_r600_rb_pre();
+ return;
+ }
ib_num = 0;
rb_addr = register_read (RADEON_CP_RB_BASE);
rb_head = register_read (RADEON_CP_RB_RPTR);
@@ -249,6 +256,10 @@ dump_rb_post (void)
char buf[BUFSIZ];
unsigned int *rb_mem_map;
+ if (option_interface >= INTERFACE_R600) {
+ dump_r600_rb_post();
+ return;
+ }
rb_tail = register_read (RADEON_CP_RB_RPTR);
if (option_debug)
diff --git a/src/revenge_dump_r600.c b/src/revenge_dump_r600.c
new file mode 100644
index 0000000..3061716
--- /dev/null
+++ b/src/revenge_dump_r600.c
@@ -0,0 +1,129 @@
+/*
+ * $Id$
+ * Copyright (C) 2007 Oliver McFadden <omcfadde@gmail.com>
+ * Copyright (C) 2011 Red Hat
+ *
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <revenge_detect.h>
+#include <revenge_main.h>
+#include <revenge_memory.h>
+#include <revenge_register.h>
+
+#define CP_RB_BASE 0xC100
+#define CP_RB_RPTR 0x8700
+#define CP_RB_WPTR 0xC114
+#define CP_RB_CNTL 0xC104
+
+//static unsigned int ib_addr = 0, ib_size = 0;
+static unsigned ib_num = 0;
+static unsigned int rb_addr = 0, rb_head = 0, rb_size = 0, rb_tail = 0, rb_mask = 0;
+
+static void dump_ib(void);
+
+static void dump_packets(unsigned int head,
+ unsigned int tail,
+ unsigned int *mem_map,
+ char *name)
+{
+ FILE *file;
+ unsigned packet_type, packet_cnt;
+ unsigned i;
+
+ if (!(file = fopen(name, "w"))) {
+ fprintf(stderr, "%s: %s:%d: %s\n", program_invocation_short_name,
+ __FILE__, __LINE__, strerror (errno));
+ exit(EXIT_FAILURE);
+ }
+
+ while (head != tail) {
+ assert(mem_map[head]);
+ packet_type = (mem_map[head] >> 30) & 0x3;
+ packet_cnt = (mem_map[head] >> 16) & 0x3fff;
+ switch (packet_type) {
+ case 0:
+ fprintf(file, "PKT0 cnt %d\n", packet_cnt);
+ break;
+ case 2:
+ fprintf(file, "PKT2 cnt %d\n", packet_cnt);
+ packet_cnt = 0;
+ break;
+ case 3:
+ fprintf(file, "PKT3 cnt %d\n", packet_cnt);
+ break;
+ case 1:
+ default:
+ fprintf(stderr, "invalid packet type\n");
+ exit(EXIT_FAILURE);
+ }
+ for (i = 0; i <= packet_cnt; i++) {
+ fprintf(file, "%08x\n", mem_map[(head + i) & rb_mask]);
+ }
+ head += packet_cnt + 1;
+ head &= rb_mask;
+ }
+ fclose(file);
+}
+
+static void dump_ib(void)
+{
+}
+
+void dump_r600_rb_pre(void)
+{
+ unsigned rb_bufsz;
+
+ ib_num = 0;
+ rb_addr = register_read(CP_RB_BASE);
+ rb_head = register_read(CP_RB_RPTR);
+ rb_bufsz = register_read(CP_RB_CNTL) & 0x3f;
+ if (rb_bufsz < 2) {
+ rb_bufsz = 2;
+ }
+ if (rb_bufsz > 20) {
+ rb_bufsz = 20;
+ }
+ rb_size = (1 << rb_bufsz);
+ rb_mask = rb_size - 1;
+
+ if (option_debug) {
+ printf("%s: rb_addr = 0x%08x rb_head = 0x%08x rb_size = 0x%08x\n",
+ __func__, rb_addr, rb_head, rb_size);
+ }
+}
+
+void dump_r600_rb_post(void)
+{
+ char buf[BUFSIZ];
+ unsigned int *rb_mem_map;
+
+ rb_tail = register_read(CP_RB_RPTR);
+
+ if (option_debug) {
+ printf("%s: rb_tail = 0x%08x (%d)\n", __func__, rb_tail,
+ rb_tail - rb_head);
+ }
+
+ snprintf(buf, BUFSIZ, "rb.txt");
+ rb_mem_map = memory_r600_read(rb_addr, rb_size << 2);
+ dump_packets(rb_head, rb_tail, rb_mem_map, buf);
+ free (rb_mem_map);
+}
diff --git a/src/revenge_main.c b/src/revenge_main.c
index 06e8279..cde18f5 100644
--- a/src/revenge_main.c
+++ b/src/revenge_main.c
@@ -104,6 +104,8 @@ static struct option long_options[] = {
{"pci", no_argument, &option_interface, INTERFACE_PCI},
{"pci-e", no_argument, &option_interface, INTERFACE_PCI_E},
{"rs690", no_argument, &option_interface, INTERFACE_RS690},
+ {"r600", no_argument, &option_interface, INTERFACE_R600},
+ {"evergreen", no_argument, &option_interface, INTERFACE_EVERGREEN},
{"verbose", no_argument, &option_verbose, 1},
{0, 0, 0, 0},
};
@@ -113,6 +115,7 @@ unsigned int *agp_mem_map = NULL;
unsigned int *fb_mem_map = NULL;
unsigned int *pcigart_mem_map = NULL;
unsigned int *reg_mem_map = NULL;
+uint64_t *pcigart_r600_mem_map = NULL;
int
main (int argc, char **argv)
@@ -177,17 +180,38 @@ main (int argc, char **argv)
__FILE__, __LINE__, strerror (errno));
exit (EXIT_FAILURE);
}
+fprintf(stderr, "%s %d\n", __func__, __LINE__);
- detect_fb_aperture ();
+ switch (option_interface) {
+ case INTERFACE_AGP:
+ case INTERFACE_IGP:
+ case INTERFACE_PCI:
+ case INTERFACE_PCI_E:
+ case INTERFACE_RS690:
+ detect_fb_aperture ();
+ break;
+ case INTERFACE_R600:
+ detect_r600_fb_aperture ();
+ break;
+ case INTERFACE_EVERGREEN:
+ detect_evergreen_fb_aperture ();
+ break;
+ default:
+fprintf(stderr, "%s %d\n", __func__, __LINE__);
+ assert (0);
+ break;
+ }
+fprintf(stderr, "%s %d\n", __func__, __LINE__);
if ((fb_mem_map =
mmap (NULL, fb_len, PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd,
fb_addr)) == MAP_FAILED)
{
- fprintf (stderr, "%s: %s:%d: %s\n", program_invocation_short_name,
- __FILE__, __LINE__, strerror (errno));
+ fprintf (stderr, "%s: %s:%d: %s 0x%lX 0x%lX\n", program_invocation_short_name,
+ __FILE__, __LINE__, strerror (errno), fb_addr, fb_len);
exit (EXIT_FAILURE);
}
+fprintf(stderr, "%s %d\n", __func__, __LINE__);
switch (option_interface)
{
case INTERFACE_AGP:
@@ -224,6 +248,11 @@ main (int argc, char **argv)
exit (EXIT_FAILURE);
}
break;
+ case INTERFACE_EVERGREEN:
+ case INTERFACE_R600:
+ detect_r600_aperture();
+ pcigart_r600_mem_map = (void *)(((char*)fb_mem_map) + pcigart_addr);
+ break;
case INTERFACE_RS690:
detect_rs690gart_aperture ();
if ((pcigart_mem_map =
@@ -239,10 +268,12 @@ main (int argc, char **argv)
assert (0);
break;
}
+fprintf(stderr, "%s %d\n", __func__, __LINE__);
snprintf (buf, BUFSIZ, "%1$s-%2$s-%3$04x-%4$04x", PACKAGE_NAME,
PACKAGE_VERSION, reg_device_id, revenge_rand);
+fprintf(stderr, "%s %d\n", __func__, __LINE__);
if (mkdir (buf, 0777) < 0)
{
if (errno != EEXIST)
@@ -260,9 +291,13 @@ main (int argc, char **argv)
exit (EXIT_FAILURE);
}
+fprintf(stderr, "%s %d\n", __func__, __LINE__);
opengl_open ();
+fprintf(stderr, "%s %d\n", __func__, __LINE__);
test ();
+fprintf(stderr, "%s %d\n", __func__, __LINE__);
opengl_close ();
+fprintf(stderr, "%s %d\n", __func__, __LINE__);
if (munmap (reg_mem_map, reg_len) < 0)
{
@@ -303,6 +338,7 @@ main (int argc, char **argv)
assert (0);
break;
}
+fprintf(stderr, "%s %d\n", __func__, __LINE__);
if (close (mem_fd) < 0)
{
@@ -310,6 +346,7 @@ main (int argc, char **argv)
__FILE__, __LINE__, strerror (errno));
exit (EXIT_FAILURE);
}
+fprintf(stderr, "%s %d\n", __func__, __LINE__);
if (chdir ("..") < 0)
{
@@ -317,6 +354,7 @@ main (int argc, char **argv)
__FILE__, __LINE__, strerror (errno));
exit (EXIT_FAILURE);
}
+fprintf(stderr, "%s %d\n", __func__, __LINE__);
snprintf (buf, BUFSIZ,
"tar -cjf %1$s-%2$s-%3$04x-%4$04x.tar.bz2 %1$s-%2$s-%3$04x-%4$04x/",
diff --git a/src/revenge_main.h b/src/revenge_main.h
index f6b92a7..de3af6a 100644
--- a/src/revenge_main.h
+++ b/src/revenge_main.h
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <stdint.h>
/* {{{ */
@@ -145,6 +146,8 @@ enum interface_t
INTERFACE_PCI,
INTERFACE_PCI_E,
INTERFACE_RS690,
+ INTERFACE_R600,
+ INTERFACE_EVERGREEN,
};
extern int option_debug;
@@ -156,6 +159,7 @@ extern int mem_fd;
extern unsigned int *agp_mem_map;
extern unsigned int *fb_mem_map;
extern unsigned int *pcigart_mem_map;
+extern uint64_t *pcigart_r600_mem_map;
extern unsigned int *reg_mem_map;
int main (int argc, char **argv);
diff --git a/src/revenge_memory.h b/src/revenge_memory.h
index c14dd54..79a4e48 100644
--- a/src/revenge_memory.h
+++ b/src/revenge_memory.h
@@ -24,5 +24,6 @@
#include <stdlib.h>
void *memory_read (unsigned int addr, unsigned int size);
+void *memory_r600_read(unsigned int addr, unsigned int size);
#endif
diff --git a/src/revenge_memory_r600.c b/src/revenge_memory_r600.c
new file mode 100644
index 0000000..1196a1b
--- /dev/null
+++ b/src/revenge_memory_r600.c
@@ -0,0 +1,136 @@
+/*
+ * $Id$
+ * Copyright (C) 2007 Oliver McFadden <omcfadde@gmail.com>
+ * Copyright (C) 2011 Red Hat
+ *
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include <revenge_detect.h>
+#include <revenge_main.h>
+
+#define round_up(x, y) (((x) + (y) - 1) & ~((y) - 1))
+#define round_down(x, y) ((x) & ~((y) - 1))
+
+static unsigned long memory_virt_to_phys(unsigned long virt_addr)
+{
+ unsigned page_num;
+ unsigned long phys_addr;
+
+ page_num = (virt_addr - pcigart_start) / ATI_PCIGART_PAGE_SIZE;
+
+ switch (option_interface) {
+ case INTERFACE_EVERGREEN:
+ case INTERFACE_R600:
+ phys_addr = pcigart_r600_mem_map[page_num] & 0xFFFFFFFFFFFFF000ULL;
+ break;
+ case INTERFACE_PCI_E:
+ case INTERFACE_PCI:
+ case INTERFACE_IGP:
+ case INTERFACE_RS690:
+ default:
+ assert (0);
+ break;
+ }
+
+ if (option_debug && option_verbose) {
+ printf("%s: virt_addr = 0x%016lx page_num = 0x%08x phys_addr = 0x%016lx\n",
+ __func__, virt_addr, page_num, phys_addr);
+ }
+
+ return phys_addr;
+}
+
+static void *memory_read_pcigart(unsigned int addr, unsigned int size)
+{
+ unsigned int addr_mod;
+ unsigned int buf_size;
+ unsigned int start_page_addr, end_page_addr;
+ void *dest;
+ void *mem_map, *mem_map_ptr;
+ void *page_mem_map;
+
+ addr_mod = addr % ATI_PCIGART_PAGE_SIZE;
+ buf_size = round_up (addr_mod + size, ATI_PCIGART_PAGE_SIZE);
+
+ start_page_addr = round_down (addr, ATI_PCIGART_PAGE_SIZE);
+ end_page_addr = start_page_addr + buf_size;
+
+ if (!(mem_map = malloc(buf_size))) {
+ fprintf(stderr, "%s: %s:%d: %s\n", program_invocation_short_name,
+ __FILE__, __LINE__, strerror (errno));
+ exit(EXIT_FAILURE);
+ }
+
+ if (option_debug && option_verbose) {
+ printf("%s: addr = 0x%08x size = 0x%08x start_page_addr = 0x%08x end_page_addr = 0x%08x\n",
+ __func__, addr, size, start_page_addr, end_page_addr);
+ }
+
+ for (mem_map_ptr = mem_map; start_page_addr < end_page_addr;
+ start_page_addr += ATI_PCIGART_PAGE_SIZE, mem_map_ptr += ATI_PCIGART_PAGE_SIZE) {
+ if ((page_mem_map = mmap(NULL, ATI_PCIGART_PAGE_SIZE, PROT_READ | PROT_WRITE,
+ MAP_SHARED, mem_fd, memory_virt_to_phys(start_page_addr))) == MAP_FAILED) {
+ fprintf (stderr, "%s: %s:%d: %s\n", program_invocation_short_name,
+ __FILE__, __LINE__, strerror (errno));
+ exit (EXIT_FAILURE);
+ }
+ memcpy(mem_map_ptr, page_mem_map, ATI_PCIGART_PAGE_SIZE);
+ if (munmap (page_mem_map, ATI_PCIGART_PAGE_SIZE) < 0) {
+ fprintf(stderr, "%s: %s:%d: %s\n", program_invocation_short_name,
+ __FILE__, __LINE__, strerror (errno));
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (!(dest = malloc(size))) {
+ fprintf(stderr, "%s: %s:%d: %s\n", program_invocation_short_name,
+ __FILE__, __LINE__, strerror (errno));
+ exit(EXIT_FAILURE);
+ }
+ memcpy (dest, mem_map + addr_mod, size);
+ free (mem_map);
+
+ return dest;
+}
+
+void *memory_r600_read(unsigned int addr, unsigned int size)
+{
+ void *mem_map;
+
+ switch (option_interface) {
+ case INTERFACE_EVERGREEN:
+ case INTERFACE_R600:
+ mem_map = memory_read_pcigart(addr, size);
+ break;
+ case INTERFACE_PCI_E:
+ case INTERFACE_PCI:
+ case INTERFACE_AGP:
+ case INTERFACE_IGP:
+ case INTERFACE_RS690:
+ default:
+ assert (0);
+ break;
+ }
+
+ return mem_map;
+}