diff options
Diffstat (limited to 'src/revenge_dump.c')
-rw-r--r-- | src/revenge_dump.c | 366 |
1 files changed, 366 insertions, 0 deletions
diff --git a/src/revenge_dump.c b/src/revenge_dump.c new file mode 100644 index 0000000..459c295 --- /dev/null +++ b/src/revenge_dump.c @@ -0,0 +1,366 @@ +/* + * $Id$ + * Copyright (C) 2007 Oliver McFadden <z3ro.geek@gmail.com> + * + * 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 2 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#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> + +static unsigned int ib_addr = 0, ib_num = 0, ib_size = 0; +static unsigned int rb_addr = 0, rb_head = 0, rb_size = 0, rb_tail = 0; +static unsigned int tx_addr = 0, tx_width = 0, tx_height = 0; + +static void dump_ib (unsigned int ib_addr, unsigned int ib_size); + +static void +dump_tx (unsigned int tx_addr, unsigned int tx_width, unsigned int tx_height) +{ + if (option_debug) + { + printf ("%s: tx_addr = 0x%08x tx_width = 0x%08x tx_height = 0x%08x\n", + __func__, tx_addr, tx_width, tx_height); + } +} + +static void +dump_reg (unsigned int key, unsigned int val) +{ + int i; + + if (option_debug) + { + printf ("%s: key = 0x%04x val = 0x%08x\n", __func__, key, val); + } + + if (key == RADEON_CP_IB_BASE) + { + ib_addr = val; + } + + if (key == RADEON_CP_IB_BUFSZ) + { + ib_size = val; + dump_ib (ib_addr, ib_size); + ib_addr = ib_size = 0; + } + + for (i = 0; i < gl_max_texture_units; i++) + { + if (key == R300_TX_SIZE_0 + (i << 2)) + { + tx_width = + (val >> R300_TX_WIDTHMASK_SHIFT) & R300_TX_WIDTHMASK_MASK; + tx_height = + (val >> R300_TX_HEIGHTMASK_SHIFT) & R300_TX_HEIGHTMASK_MASK; + } + + if (key == R300_TX_OFFSET_0 + (i << 2)) + { + tx_addr = (val >> R300_TXO_OFFSET_SHIFT) & R300_TXO_OFFSET_MASK; + dump_tx (tx_addr, tx_width, tx_height); + tx_addr = tx_width = tx_height = 0; + } + } +} + +static int +dump_packet0 (unsigned int packet_type, unsigned int packet_cnt, + unsigned int packet_bit15, unsigned int packet_reg, + unsigned int *mem_map, FILE * file) +{ + int i; + unsigned int reg; + unsigned int proc; + + if (option_debug) + { + printf ("%s: type = %d cnt = %d bit15 = %d reg = 0x%04x\n", __func__, + packet_type, packet_cnt, packet_bit15, packet_reg); + } + + proc = packet_cnt + 1; + + for (i = 0; i < proc; i++) + { + fprintf (file, "%08x\n", mem_map[i]); + reg = packet_bit15 ? packet_reg : packet_reg + (i << 2); + dump_reg (reg, mem_map[i]); + } + + return proc; +} + +static int +dump_packet2 (unsigned int packet_type, unsigned int packet_cnt, + unsigned int packet_bit15, unsigned int packet_reg, + unsigned int *mem_map, FILE * file) +{ + if (option_debug) + { + printf ("%s: type = %d cnt = %d bit15 = %d reg = 0x%04x\n", __func__, + packet_type, packet_cnt, packet_bit15, packet_reg); + } + + return 0; +} + +static int +dump_packet3 (unsigned int packet_type, unsigned int packet_cnt, + unsigned int packet_opcode, unsigned int *mem_map, FILE * file) +{ + int i; + unsigned int proc; + + if (option_debug) + { + printf ("%s: type = %d cnt = %d opcode = 0x%02x\n", __func__, + packet_type, packet_cnt, packet_opcode); + } + + proc = packet_cnt + 1; + + for (i = 0; i < proc; i++) + { + fprintf (file, "%08x\n", mem_map[i]); + if (option_debug) + { + printf ("%s: 0x%08x\n", __func__, mem_map[i]); + } + } + + return proc; +} + +static void +dump_packets (unsigned int head, unsigned int tail, unsigned int *mem_map, + char *name) +{ + FILE *file; + int i; + unsigned int packet_type, packet_cnt, packet_bit15, packet_reg, + packet_opcode; + unsigned int proc; + + /* + * (gdb) p/t 0x3 << 30 + * $1 = 11000000000000000000000000000000 + * (gdb) p/t 0x3 << 30 | 0x3fff << 16 + * $2 = 11111111111111110000000000000000 + * (gdb) p/t 0x3 << 30 | 0x3fff << 16 | 1 << 15 + * $3 = 11111111111111111000000000000000 + * (gdb) p/t 0x3 << 30 | 0x3fff << 16 | 1 << 15 | 0x1fff + * $4 = 11111111111111111001111111111111 + */ + + if (!(file = fopen (name, "w"))) + { + fprintf (stderr, "%s: %s\n", program_invocation_short_name, + strerror (errno)); + exit (EXIT_FAILURE); + } + + assert (tail >= head); + + for (i = head; i < tail; i += proc + 1) + { + assert (mem_map[i]); + + packet_type = (mem_map[i] >> 30) & 0x3; + packet_cnt = (mem_map[i] >> 16) & 0x3fff; + packet_bit15 = (mem_map[i] >> 15) & 0x1; + packet_reg = ((mem_map[i] >> 0) & 0x1fff) << 2; + + packet_opcode = (mem_map[i] >> 8) & 0xff; + + fprintf (file, "%08x\n", mem_map[i]); + + switch (packet_type) + { + case 0x0: + proc = + dump_packet0 (packet_type, packet_cnt, packet_bit15, packet_reg, + &mem_map[i + 1], file); + break; + case 0x2: + proc = + dump_packet2 (packet_type, packet_cnt, packet_bit15, packet_reg, + &mem_map[i + 1], file); + break; + case 0x3: + proc = + dump_packet3 (packet_type, packet_cnt, packet_opcode, + &mem_map[i + 1], file); + break; + default: + assert (0); + break; + } + } + + assert (i - tail <= 1); + + fclose (file); +} + +static void +dump_ib (unsigned int ib_addr, unsigned int ib_size) +{ + char buf[BUFSIZ]; + unsigned int *ib_mem_map; + + if (!option_disable_ib) + { + if (option_debug) + { + printf ("%s: ib_addr = 0x%08x ib_size = 0x%08x\n", __func__, + ib_addr, ib_size); + } + + snprintf (buf, BUFSIZ, "ib_%04d.txt", ib_num); + ib_mem_map = memory_read (ib_addr, ib_size * 4); + dump_packets (0, ib_size, ib_mem_map, buf); + free (ib_mem_map); + ib_num++; + } +} + +void +dump_rb_pre (void) +{ + ib_num = 0; + rb_addr = register_read (RADEON_CP_RB_BASE); + rb_head = register_read (RADEON_CP_RB_RPTR); + rb_size = (1 << ((register_read (RADEON_CP_RB_CNTL) & 0xff) + 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_rb_post (void) +{ + char buf[BUFSIZ]; + unsigned int *rb_mem_map; + + rb_tail = register_read (RADEON_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_read (rb_addr, rb_size * 4); + dump_packets (rb_head, rb_tail, rb_mem_map, buf); + free (rb_mem_map); +} + +void +dump_device_id (void) +{ + FILE *file; + + if (!(file = fopen ("device_id.txt", "w"))) + { + fprintf (stderr, "%s: %s\n", program_invocation_short_name, + strerror (errno)); + exit (EXIT_FAILURE); + } + + fprintf (file, "%04x\n", reg_device_id); + + fclose (file); +} + +void +dump_device_name (void) +{ + FILE *file; + + if (!(file = fopen ("device_name.txt", "w"))) + { + fprintf (stderr, "%s: %s\n", program_invocation_short_name, + strerror (errno)); + exit (EXIT_FAILURE); + } + + fprintf (file, "%s\n", reg_device_name); + + fclose (file); +} + +void +dump_fglrx_version (void) +{ + system + ("fglrxinfo | sed -n 's/.*(\\([^)]*\\)).*/\\1/p' > fglrx_version.txt"); +} + +void +dump_fglrxinfo (void) +{ + system ("fglrxinfo -v > fglrxinfo.txt"); +} + +void +dump_interface (void) +{ + FILE *file; + + if (!(file = fopen ("interface.txt", "w"))) + { + fprintf (stderr, "%s: %s\n", program_invocation_short_name, + strerror (errno)); + exit (EXIT_FAILURE); + } + + switch (option_interface) + { + case IF_PCIE: + fprintf (file, "PCI-E\n"); + break; + case IF_AGP: + fprintf (file, "AGP\n"); + break; + case IF_IGP: + fprintf (file, "IGP\n"); + break; + default: + assert (0); + break; + } + + fclose (file); +} + +void +dump_lspci (void) +{ + system ("lspci -v > lspci.txt"); +} |