Logo Search packages:      
Sourcecode: radeontool version File versions  Download package

radeontool.c

 
/* Radeontool   v1.4
 * by Frederick Dean <software@fdd.com>
 * Copyright 2002-2004 Frederick Dean
 * Use hereby granted under the zlib license.
 *
 * Warning: I do not have the Radeon documents, so this was engineered from 
 * the radeon_reg.h header file.  
 *
 * USE RADEONTOOL AT YOUR OWN RISK
 *
 * Thanks to Deepak Chawla, Erno Kuusela, Rolf Offermanns, and Soos Peter
 * for patches.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <fnmatch.h>
#include <pciaccess.h>

#include "radeon_reg.h"

int debug;
int skip;

/* *radeon_cntl_mem is mapped to the actual device's memory mapped control area. */
/* Not the address but what it points to is volatile. */
struct pci_device *avivo_device = NULL;
unsigned char * volatile radeon_cntl_mem;
unsigned int ctrl_region, fb_region;
unsigned char * volatile fb_mem;
unsigned char * volatile ctrl_mem;
static void radeon_rom_legacy_mmio_table(unsigned char *bios, int offset);
static void fatal(char *why)
{
    fprintf(stderr,why);
    pci_system_cleanup();
    exit(-1);
}

static unsigned int radeon_get(unsigned long offset, const char *name)
{
    unsigned int value;
    if(debug) 
        printf("reading %s (%lx) is ",name,offset);
    if(radeon_cntl_mem == NULL) {
        printf("internal error\n");
      exit(-2);
    };
#ifdef __powerpc__
    __asm__ __volatile__ ("lwbrx %0,%1,%2\n\t"
                    "eieio"
                    : "=r" (value)
                    : "b" (radeon_cntl_mem), "r"(offset),
                    "m" (*((volatile unsigned int *)radeon_cntl_mem+offset)));
#else
    value = *(unsigned int * volatile)(radeon_cntl_mem+offset);  
#endif
    if(debug) 
        printf("%08x\n",value);
    return value;
}
static void radeon_set(unsigned long offset, const char *name, unsigned int value)
{
    if(debug) 
        printf("writing %s (%lx) -> %08x\n",name,offset,value);
    if(radeon_cntl_mem == NULL) {
        printf("internal error\n");
      exit(-2);
    };
#ifdef __powerpc__
    __asm__ __volatile__ ("stwbrx %1,%2,%3\n\t"
                    "eieio"
                    : "=m" (*((volatile unsigned int *)radeon_cntl_mem+offset))
                    : "r"(value), "b"(radeon_cntl_mem), "r"(offset));
#else
    *(unsigned int * volatile)(radeon_cntl_mem+offset) = value;  
#endif
}

static unsigned int radeon_get_indexed(unsigned long index_offset,
                                       unsigned long data_offset,
                                       unsigned long offset,
                               const char *name,
                               unsigned long index_mask)
{
    unsigned int temp = offset;
    if (index_mask) {
      temp = radeon_get(index_offset, "index");
      temp &= ~index_mask;
      temp += offset;
    }
    radeon_set(index_offset, "index", temp);
    return radeon_get(data_offset, name);
}

static void radeon_set_indexed(unsigned long index_offset,
                               unsigned long data_offset, unsigned long offset,
                               const char *name, unsigned int value)
{
    radeon_set(index_offset, "index", offset);
    radeon_set(data_offset, name, value);
}

static unsigned int radeon_get_clk(unsigned long offset, const char *name)
{
    return radeon_get_indexed(RADEON_CLOCK_CNTL_INDEX,
                        RADEON_CLOCK_CNTL_DATA,
                              offset, name, 0x3f);
}

static void radeon_set_clk(unsigned long offset, const char *name,
                          unsigned int value)
{
    return radeon_set_indexed(RADEON_CLOCK_CNTL_INDEX, RADEON_CLOCK_CNTL_DATA,
                              offset | RADEON_PLL_WR_EN, name, value);
}

static unsigned int radeon_get_mcind(unsigned long offset, const char *name)
{
  return radeon_get_indexed(0x1f8, 0x1fc, offset, name, 0x3f);
}

static void radeon_set_mcind(unsigned long offset, const char *name,
                       unsigned int value)
{
  return radeon_set_indexed(0x1f8, 0x1fc, offset | (1 << 8), name, value);
}

static void usage(void)
{
    printf("usage: radeontool [options] [command]\n");
    printf("         --debug            - show a little debug info\n");
    printf("         --skip=1           - use the second radeon card\n");
    printf("         dac [on|off]       - power down the external video outputs (%s)\n",
         (radeon_get(RADEON_DAC_CNTL,"RADEON_DAC_CNTL")&RADEON_DAC_PDWN)?"off":"on");
    printf("         light [on|off]     - power down the backlight (%s)\n",
         (radeon_get(RADEON_LVDS_GEN_CNTL,"RADEON_LVDS_GEN_CNTL")&RADEON_LVDS_ON)?"on":"off");
    printf("         stretch [on|off|vert|horiz|auto|manual]   - stretching for resolution mismatch \n");
    printf("         regs               - show a listing of some random registers\n");
    printf("         regmatch <pattern> - show registers matching wildcard pattern\n");
    printf("         regset <pattern> <value> - set registers matching wildcard pattern\n");
    exit(-1);
}

void radeon_cmd_regs(void)
{
#define SHOW_REG(r) printf("%s\t%08x\n", #r, radeon_get(r, #r))
#define SHOW_CLK_REG(r) printf("%s\t%08x\n", #r, radeon_get_indexed(RADEON_CLOCK_CNTL_INDEX, RADEON_CLOCK_CNTL_DATA, (r), #r, 0x3f))      
      SHOW_REG(RADEON_DAC_CNTL);
      SHOW_REG(RADEON_DAC_EXT_CNTL);
      SHOW_REG(RADEON_DAC_MACRO_CNTL);
      SHOW_REG(RADEON_DAC_CNTL2);
      SHOW_REG(RADEON_TV_DAC_CNTL);
      SHOW_REG(RADEON_DISP_OUTPUT_CNTL);
      SHOW_REG(RADEON_CONFIG_MEMSIZE);
      SHOW_REG(RADEON_AUX_SC_CNTL);
      SHOW_REG(RADEON_CRTC_EXT_CNTL);
      SHOW_REG(RADEON_CRTC_GEN_CNTL);
      SHOW_REG(RADEON_CRTC2_GEN_CNTL);
      SHOW_REG(RADEON_DEVICE_ID);
      SHOW_REG(RADEON_DISP_MISC_CNTL);
      SHOW_REG(RADEON_GPIO_MONID);
      SHOW_REG(RADEON_GPIO_MONIDB);
      SHOW_REG(RADEON_GPIO_CRT2_DDC);
      SHOW_REG(RADEON_GPIO_DVI_DDC);
      SHOW_REG(RADEON_GPIO_VGA_DDC);
      SHOW_REG(RADEON_LVDS_GEN_CNTL);
      SHOW_REG(RADEON_LVDS_PLL_CNTL);
      SHOW_REG(RADEON_FP_GEN_CNTL);
      SHOW_REG(RADEON_FP2_GEN_CNTL);
      SHOW_CLK_REG(RADEON_PIXCLKS_CNTL);
      SHOW_REG(RADEON_MEM_TIMING_CNTL);
      SHOW_REG(RADEON_TMDS_PLL_CNTL);
      SHOW_REG(RADEON_TMDS_TRANSMITTER_CNTL);
}

#define REGLIST(r) { "", #r, radeon_get, radeon_set, RADEON_ ## r }
#define REGLIST_CLK(r) { "CL: ", #r, radeon_get_clk, radeon_set_clk, RADEON_ ## r }
static struct {
    const char *type;
    const char *name;
    unsigned int (*get)(unsigned long, const char *);
    void (*set)(unsigned long, const char *, unsigned int);
    unsigned address;
} reg_list[] = {
      REGLIST(ADAPTER_ID),
      REGLIST(AGP_BASE),
      REGLIST(AGP_CNTL),
      REGLIST(AGP_COMMAND),
      REGLIST(AGP_STATUS),
      REGLIST(AMCGPIO_A_REG),
      REGLIST(AMCGPIO_EN_REG),
      REGLIST(AMCGPIO_MASK),
      REGLIST(AMCGPIO_Y_REG),
      REGLIST(ATTRDR),
      REGLIST(ATTRDW),
      REGLIST(ATTRX),
      REGLIST(AUX_SC_CNTL),
      REGLIST(AUX1_SC_BOTTOM),
      REGLIST(AUX1_SC_LEFT),
      REGLIST(AUX1_SC_RIGHT),
      REGLIST(AUX1_SC_TOP),
      REGLIST(AUX2_SC_BOTTOM),
      REGLIST(AUX2_SC_LEFT),
      REGLIST(AUX2_SC_RIGHT),
      REGLIST(AUX2_SC_TOP),
      REGLIST(AUX3_SC_BOTTOM),
      REGLIST(AUX3_SC_LEFT),
      REGLIST(AUX3_SC_RIGHT),
      REGLIST(AUX3_SC_TOP),
      REGLIST(AUX_WINDOW_HORZ_CNTL),
      REGLIST(AUX_WINDOW_VERT_CNTL),
      REGLIST(BASE_CODE),
      REGLIST(BIOS_0_SCRATCH),
      REGLIST(BIOS_1_SCRATCH),
      REGLIST(BIOS_2_SCRATCH),
      REGLIST(BIOS_3_SCRATCH),
      REGLIST(BIOS_4_SCRATCH),
      REGLIST(BIOS_5_SCRATCH),
      REGLIST(BIOS_6_SCRATCH),
      REGLIST(BIOS_7_SCRATCH),
      REGLIST(BIOS_ROM),
      REGLIST(BIST),
      REGLIST(BUS_CNTL),
      REGLIST(BUS_CNTL1),
      REGLIST(CACHE_CNTL),
      REGLIST(CACHE_LINE),
      REGLIST(CAP0_TRIG_CNTL),
      REGLIST(CAP1_TRIG_CNTL),
      REGLIST(CAPABILITIES_ID),
      REGLIST(CAPABILITIES_PTR),
      REGLIST(CLOCK_CNTL_DATA),
      REGLIST(CLOCK_CNTL_INDEX),
      REGLIST(CLR_CMP_CLR_3D),
      REGLIST(CLR_CMP_CLR_DST),
      REGLIST(CLR_CMP_CLR_SRC),
      REGLIST(CLR_CMP_CNTL),
      REGLIST(CLR_CMP_MASK),
      REGLIST(CLR_CMP_MASK_3D),
      REGLIST(COMMAND),
      REGLIST(COMPOSITE_SHADOW_ID),
      REGLIST(CONFIG_APER_0_BASE),
      REGLIST(CONFIG_APER_1_BASE),
      REGLIST(CONFIG_APER_SIZE),
      REGLIST(CONFIG_BONDS),
      REGLIST(CONFIG_CNTL),
      REGLIST(CONFIG_MEMSIZE),
      REGLIST(CONFIG_MEMSIZE_EMBEDDED),
      REGLIST(CONFIG_REG_1_BASE),
      REGLIST(CONFIG_REG_APER_SIZE),
      REGLIST(CONFIG_XSTRAP),
      REGLIST(CONSTANT_COLOR_C),
      REGLIST(CRC_CMDFIFO_ADDR),
      REGLIST(CRC_CMDFIFO_DOUT),
      REGLIST(CRTC_CRNT_FRAME),
      REGLIST(CRTC_DEBUG),
      REGLIST(CRTC_EXT_CNTL),
      REGLIST(CRTC_EXT_CNTL_DPMS_BYTE),
      REGLIST(CRTC_GEN_CNTL),
      REGLIST(CRTC2_GEN_CNTL),
      REGLIST(CRTC_GUI_TRIG_VLINE),
      REGLIST(CRTC_H_SYNC_STRT_WID),
      REGLIST(CRTC2_H_SYNC_STRT_WID),
      REGLIST(CRTC_H_TOTAL_DISP),
      REGLIST(CRTC2_H_TOTAL_DISP),
      REGLIST(CRTC_OFFSET),
      REGLIST(CRTC2_OFFSET),
      REGLIST(CRTC_OFFSET_CNTL),
      REGLIST(CRTC2_OFFSET_CNTL),
      REGLIST(CRTC_PITCH),
      REGLIST(CRTC2_PITCH),
      REGLIST(CRTC_STATUS),
      REGLIST(CRTC_V_SYNC_STRT_WID),
      REGLIST(CRTC2_V_SYNC_STRT_WID),
      REGLIST(CRTC_V_TOTAL_DISP),
      REGLIST(CRTC2_V_TOTAL_DISP),
      REGLIST(CRTC_VLINE_CRNT_VLINE),
      REGLIST(CRTC2_CRNT_FRAME),
      REGLIST(CRTC2_DEBUG),
      REGLIST(CRTC2_GUI_TRIG_VLINE),
      REGLIST(CRTC2_STATUS),
      REGLIST(CRTC2_VLINE_CRNT_VLINE),
      REGLIST(CRTC8_DATA),
      REGLIST(CRTC8_IDX),
      REGLIST(CUR_CLR0),
      REGLIST(CUR_CLR1),
      REGLIST(CUR_HORZ_VERT_OFF),
      REGLIST(CUR_HORZ_VERT_POSN),
      REGLIST(CUR_OFFSET),
      REGLIST(CUR2_CLR0),
      REGLIST(CUR2_CLR1),
      REGLIST(CUR2_HORZ_VERT_OFF),
      REGLIST(CUR2_HORZ_VERT_POSN),
      REGLIST(CUR2_OFFSET),
      REGLIST(DAC_CNTL),
      REGLIST(DAC_CNTL2),
      REGLIST(DAC_EXT_CNTL),
      REGLIST(DAC_MACRO_CNTL),
      REGLIST(TV_DAC_CNTL),
      REGLIST(DISP_OUTPUT_CNTL),
      REGLIST(DAC_CRC_SIG),
      REGLIST(DAC_DATA),
      REGLIST(DAC_MASK),
      REGLIST(DAC_R_INDEX),
      REGLIST(DAC_W_INDEX),
      REGLIST(DDA_CONFIG),
      REGLIST(DDA_ON_OFF),
      REGLIST(DEFAULT_OFFSET),
      REGLIST(DEFAULT_PITCH),
      REGLIST(DEFAULT_SC_BOTTOM_RIGHT),
      REGLIST(DESTINATION_3D_CLR_CMP_VAL),
      REGLIST(DESTINATION_3D_CLR_CMP_MSK),
      REGLIST(DEVICE_ID),
      REGLIST(DISP_MISC_CNTL),
      REGLIST(DP_BRUSH_BKGD_CLR),
      REGLIST(DP_BRUSH_FRGD_CLR),
      REGLIST(DP_CNTL),
      REGLIST(DP_CNTL_XDIR_YDIR_YMAJOR),
      REGLIST(DP_DATATYPE),
      REGLIST(DP_GUI_MASTER_CNTL),
      REGLIST(DP_GUI_MASTER_CNTL_C),
      REGLIST(DP_MIX),
      REGLIST(DP_SRC_BKGD_CLR),
      REGLIST(DP_SRC_FRGD_CLR),
      REGLIST(DP_WRITE_MASK),
      REGLIST(DST_BRES_DEC),
      REGLIST(DST_BRES_ERR),
      REGLIST(DST_BRES_INC),
      REGLIST(DST_BRES_LNTH),
      REGLIST(DST_BRES_LNTH_SUB),
      REGLIST(DST_HEIGHT),
      REGLIST(DST_HEIGHT_WIDTH),
      REGLIST(DST_HEIGHT_WIDTH_8),
      REGLIST(DST_HEIGHT_WIDTH_BW),
      REGLIST(DST_HEIGHT_Y),
      REGLIST(DST_LINE_START),
      REGLIST(DST_LINE_END),
      REGLIST(DST_LINE_PATCOUNT),
      REGLIST(DST_OFFSET),
      REGLIST(DST_PITCH),
      REGLIST(DST_PITCH_OFFSET),
      REGLIST(DST_PITCH_OFFSET_C),
      REGLIST(DST_WIDTH),
      REGLIST(DST_WIDTH_HEIGHT),
      REGLIST(DST_WIDTH_X),
      REGLIST(DST_WIDTH_X_INCY),
      REGLIST(DST_X),
      REGLIST(DST_X_SUB),
      REGLIST(DST_X_Y),
      REGLIST(DST_Y),
      REGLIST(DST_Y_SUB),
      REGLIST(DST_Y_X),
      REGLIST(FLUSH_1),
      REGLIST(FLUSH_2),
      REGLIST(FLUSH_3),
      REGLIST(FLUSH_4),
      REGLIST(FLUSH_5),
      REGLIST(FLUSH_6),
      REGLIST(FLUSH_7),
      REGLIST(FOG_3D_TABLE_START),
      REGLIST(FOG_3D_TABLE_END),
      REGLIST(FOG_3D_TABLE_DENSITY),
      REGLIST(FOG_TABLE_INDEX),
      REGLIST(FOG_TABLE_DATA),
      REGLIST(FP_CRTC_H_TOTAL_DISP),
      REGLIST(FP_CRTC_V_TOTAL_DISP),
      REGLIST(FP_CRTC2_H_TOTAL_DISP),
      REGLIST(FP_CRTC2_V_TOTAL_DISP),
      REGLIST(FP_GEN_CNTL),
      REGLIST(FP2_GEN_CNTL),
      REGLIST(FP_H_SYNC_STRT_WID),
      REGLIST(FP_H2_SYNC_STRT_WID),
      REGLIST(FP_HORZ_STRETCH),
      REGLIST(FP_HORZ2_STRETCH),
      REGLIST(FP_V_SYNC_STRT_WID),
      REGLIST(FP_VERT_STRETCH),
      REGLIST(FP_V2_SYNC_STRT_WID),
      REGLIST(FP_VERT2_STRETCH),
      REGLIST(FW_CNTL),
      REGLIST(FW_STATUS),
      REGLIST(GEN_INT_CNTL),
      REGLIST(GEN_INT_STATUS),
      REGLIST(GENENB),
      REGLIST(GENFC_RD),
      REGLIST(GENFC_WT),
      REGLIST(GENMO_RD),
      REGLIST(GENMO_WT),
      REGLIST(GENS0),
      REGLIST(GENS1),
      REGLIST(GPIO_MONID),
      REGLIST(GPIO_MONIDB),
      REGLIST(GPIO_CRT2_DDC),
      REGLIST(GPIO_DVI_DDC),
      REGLIST(GPIO_VGA_DDC),
      REGLIST(GRPH8_DATA),
      REGLIST(GRPH8_IDX),
      REGLIST(GUI_DEBUG0),
      REGLIST(GUI_DEBUG1),
      REGLIST(GUI_DEBUG2),
      REGLIST(GUI_DEBUG3),
      REGLIST(GUI_DEBUG4),
      REGLIST(GUI_DEBUG5),
      REGLIST(GUI_DEBUG6),
      REGLIST(GUI_SCRATCH_REG0),
      REGLIST(GUI_SCRATCH_REG1),
      REGLIST(GUI_SCRATCH_REG2),
      REGLIST(GUI_SCRATCH_REG3),
      REGLIST(GUI_SCRATCH_REG4),
      REGLIST(GUI_SCRATCH_REG5),
      REGLIST(HEADER),
      REGLIST(HOST_DATA0),
      REGLIST(HOST_DATA1),
      REGLIST(HOST_DATA2),
      REGLIST(HOST_DATA3),
      REGLIST(HOST_DATA4),
      REGLIST(HOST_DATA5),
      REGLIST(HOST_DATA6),
      REGLIST(HOST_DATA7),
      REGLIST(HOST_DATA_LAST),
      REGLIST(HOST_PATH_CNTL),
      REGLIST(HW_DEBUG),
      REGLIST(HW_DEBUG2),
      REGLIST(I2C_CNTL_1),
      REGLIST(DVI_I2C_CNTL_1),
      REGLIST(INTERRUPT_LINE),
      REGLIST(INTERRUPT_PIN),
      REGLIST(IO_BASE),
      REGLIST(LATENCY),
      REGLIST(LEAD_BRES_DEC),
      REGLIST(LEAD_BRES_LNTH),
      REGLIST(LEAD_BRES_LNTH_SUB),
      REGLIST(LVDS_GEN_CNTL),
      REGLIST(MAX_LATENCY),
      REGLIST(MC_AGP_LOCATION),
      REGLIST(MC_FB_LOCATION),
      REGLIST(MC_STATUS),
      REGLIST(MDGPIO_A_REG),
      REGLIST(MDGPIO_EN_REG),
      REGLIST(MDGPIO_MASK),
      REGLIST(MDGPIO_Y_REG),
      REGLIST(MEM_ADDR_CONFIG),
      REGLIST(MEM_BASE),
      REGLIST(MEM_CNTL),
      REGLIST(MEM_INIT_LAT_TIMER),
      REGLIST(MEM_INTF_CNTL),
      REGLIST(MEM_SDRAM_MODE_REG),
      REGLIST(MEM_STR_CNTL),
      REGLIST(MEM_TIMING_CNTL),
      REGLIST(MC_CNTL),
      REGLIST(MC_ARB_CNTL),
      REGLIST(MEM_VGA_RP_SEL),
      REGLIST(MEM_VGA_WP_SEL),
      REGLIST(MIN_GRANT),
      REGLIST(MM_DATA),
      REGLIST(MM_INDEX),
      REGLIST(MPP_TB_CONFIG),
      REGLIST(MPP_GP_CONFIG),
      REGLIST(N_VIF_COUNT),
      REGLIST(NB_TOM),
      REGLIST(OV0_SCALE_CNTL),
      REGLIST(OVR_CLR),
      REGLIST(OVR_WID_LEFT_RIGHT),
      REGLIST(OVR_WID_TOP_BOTTOM),
      REGLIST(OV0_Y_X_START),
      REGLIST(OV0_Y_X_END),
      REGLIST(OV0_EXCLUSIVE_HORZ),
      REGLIST(OV0_EXCLUSIVE_VERT),
      REGLIST(OV0_REG_LOAD_CNTL),
      REGLIST(OV0_SCALE_CNTL),
      REGLIST(OV0_V_INC),
      REGLIST(OV0_P1_V_ACCUM_INIT),
      REGLIST(OV0_P23_V_ACCUM_INIT),
      REGLIST(OV0_P1_BLANK_LINES_AT_TOP),
      REGLIST(OV0_P23_BLANK_LINES_AT_TOP),
      REGLIST(OV0_VID_BUF0_BASE_ADRS),
      REGLIST(OV0_VID_BUF1_BASE_ADRS),
      REGLIST(OV0_VID_BUF2_BASE_ADRS),
      REGLIST(OV0_VID_BUF3_BASE_ADRS),
      REGLIST(OV0_VID_BUF4_BASE_ADRS),
      REGLIST(OV0_VID_BUF5_BASE_ADRS),
      REGLIST(OV0_VID_BUF_PITCH0_VALUE),
      REGLIST(OV0_VID_BUF_PITCH1_VALUE),
      REGLIST(OV0_AUTO_FLIP_CNTL),
      REGLIST(OV0_DEINTERLACE_PATTERN),
      REGLIST(OV0_H_INC),
      REGLIST(OV0_STEP_BY),
      REGLIST(OV0_P1_H_ACCUM_INIT),
      REGLIST(OV0_P23_H_ACCUM_INIT),
      REGLIST(OV0_P1_X_START_END),
      REGLIST(OV0_P2_X_START_END),
      REGLIST(OV0_P3_X_START_END),
      REGLIST(OV0_FILTER_CNTL),
      REGLIST(OV0_FOUR_TAP_COEF_0),
      REGLIST(OV0_FOUR_TAP_COEF_1),
      REGLIST(OV0_FOUR_TAP_COEF_2),
      REGLIST(OV0_FOUR_TAP_COEF_3),
      REGLIST(OV0_FOUR_TAP_COEF_4),
      REGLIST(OV0_COLOUR_CNTL),
      REGLIST(OV0_VIDEO_KEY_CLR_LOW),
      REGLIST(OV0_VIDEO_KEY_CLR_HIGH),
      REGLIST(OV0_GRAPHICS_KEY_CLR_LOW),
      REGLIST(OV0_GRAPHICS_KEY_CLR_HIGH),
      REGLIST(OV0_KEY_CNTL),
      REGLIST(OV0_TEST),
      REGLIST(PALETTE_DATA),
      REGLIST(PALETTE_30_DATA),
      REGLIST(PALETTE_INDEX),
      REGLIST(PCI_GART_PAGE),
      REGLIST_CLK(PIXCLKS_CNTL),
      REGLIST_CLK(VCLK_ECP_CNTL),
      REGLIST_CLK(PPLL_DIV_0),
      REGLIST_CLK(PPLL_CNTL),
      REGLIST_CLK(CLK_PIN_CNTL),
      REGLIST_CLK(SCLK_CNTL),
      REGLIST_CLK(PWRMAN_MISC),
      REGLIST_CLK(SS_INT_CNTL),
      REGLIST(PLANE_3D_MASK_C),
      REGLIST(PMI_CAP_ID),
      REGLIST(PMI_DATA),
      REGLIST(PMI_NXT_CAP_PTR),
      REGLIST(PMI_PMC_REG),
      REGLIST(PMI_PMCSR_REG),
      REGLIST(PMI_REGISTER),
      REGLIST(PWR_MNGMT_CNTL_STATUS),
      REGLIST(DSTCACHE_MODE),
      REGLIST(RBBM_SOFT_RESET),
      REGLIST(RBBM_STATUS),
      REGLIST(RB2D_DSTCACHE_CTLSTAT),
      REGLIST(RB2D_DSTCACHE_MODE),
      REGLIST(REG_BASE),
      REGLIST(REGPROG_INF),
      REGLIST(REVISION_ID),
      REGLIST(SC_BOTTOM),
      REGLIST(SC_BOTTOM_RIGHT),
      REGLIST(SC_BOTTOM_RIGHT_C),
      REGLIST(SC_LEFT),
      REGLIST(SC_RIGHT),
      REGLIST(SC_TOP),
      REGLIST(SC_TOP_LEFT),
      REGLIST(SC_TOP_LEFT_C),
      REGLIST(SDRAM_MODE_REG),
      REGLIST(SEQ8_DATA),
      REGLIST(SEQ8_IDX),
      REGLIST(SNAPSHOT_F_COUNT),
      REGLIST(SNAPSHOT_VH_COUNTS),
      REGLIST(SNAPSHOT_VIF_COUNT),
      REGLIST(SRC_OFFSET),
      REGLIST(SRC_PITCH),
      REGLIST(SRC_PITCH_OFFSET),
      REGLIST(SRC_SC_BOTTOM),
      REGLIST(SRC_SC_BOTTOM_RIGHT),
      REGLIST(SRC_SC_RIGHT),
      REGLIST(SRC_X),
      REGLIST(SRC_X_Y),
      REGLIST(SRC_Y),
      REGLIST(SRC_Y_X),
      REGLIST(STATUS),
      REGLIST(SUBPIC_CNTL),
      REGLIST(SUB_CLASS),
      REGLIST(SURFACE_CNTL),
      REGLIST(SURFACE0_INFO),
      REGLIST(SURFACE0_LOWER_BOUND),
      REGLIST(SURFACE0_UPPER_BOUND),
      REGLIST(SURFACE1_INFO),
      REGLIST(SURFACE1_LOWER_BOUND),
      REGLIST(SURFACE1_UPPER_BOUND),
      REGLIST(SURFACE2_INFO),
      REGLIST(SURFACE2_LOWER_BOUND),
      REGLIST(SURFACE2_UPPER_BOUND),
      REGLIST(SURFACE3_INFO),
      REGLIST(SURFACE3_LOWER_BOUND),
      REGLIST(SURFACE3_UPPER_BOUND),
      REGLIST(SURFACE4_INFO),
      REGLIST(SURFACE4_LOWER_BOUND),
      REGLIST(SURFACE4_UPPER_BOUND),
      REGLIST(SURFACE5_INFO),
      REGLIST(SURFACE5_LOWER_BOUND),
      REGLIST(SURFACE5_UPPER_BOUND),
      REGLIST(SURFACE6_INFO),
      REGLIST(SURFACE6_LOWER_BOUND),
      REGLIST(SURFACE6_UPPER_BOUND),
      REGLIST(SURFACE7_INFO),
      REGLIST(SURFACE7_LOWER_BOUND),
      REGLIST(SURFACE7_UPPER_BOUND),
      REGLIST(SW_SEMAPHORE),
      REGLIST(TEST_DEBUG_CNTL),
      REGLIST(TEST_DEBUG_MUX),
      REGLIST(TEST_DEBUG_OUT),
      REGLIST(TMDS_CRC),
      REGLIST(TRAIL_BRES_DEC),
      REGLIST(TRAIL_BRES_ERR),
      REGLIST(TRAIL_BRES_INC),
      REGLIST(TRAIL_X),
      REGLIST(TRAIL_X_SUB),
      REGLIST(PIXCLKS_CNTL),
      REGLIST(VENDOR_ID),
      REGLIST(VGA_DDA_CONFIG),
      REGLIST(VGA_DDA_ON_OFF),
      REGLIST(VID_BUFFER_CONTROL),
      REGLIST(VIDEOMUX_CNTL),
      REGLIST(VIPH_CONTROL),
      REGLIST(WAIT_UNTIL),
      REGLIST(RB3D_BLENDCNTL),
      REGLIST(RB3D_CNTL),
      REGLIST(RB3D_COLOROFFSET),
      REGLIST(RB3D_COLORPITCH),
      REGLIST(RB3D_DEPTHOFFSET),
      REGLIST(RB3D_DEPTHPITCH),
      REGLIST(RB3D_PLANEMASK),
      REGLIST(RB3D_ROPCNTL),
      REGLIST(RB3D_STENCILREFMASK),
      REGLIST(RB3D_ZSTENCILCNTL),
      REGLIST(RB3D_DSTCACHE_MODE),
      REGLIST(RE_LINE_PATTERN),
      REGLIST(RE_LINE_STATE),
      REGLIST(RE_MISC),
      REGLIST(RE_SOLID_COLOR),
      REGLIST(RE_TOP_LEFT),
      REGLIST(RE_WIDTH_HEIGHT),
      REGLIST(SE_CNTL_STATUS),
      REGLIST(LVDS_PLL_CNTL),
      REGLIST(TMDS_PLL_CNTL),
      REGLIST(TMDS_TRANSMITTER_CNTL),
      REGLIST(ISYNC_CNTL),
      REGLIST(TV_MASTER_CNTL),
      REGLIST(TV_PRE_DAC_MUX_CNTL),
      REGLIST(TV_RGB_CNTL),
      REGLIST(TV_SYNC_CNTL),
      REGLIST(TV_HTOTAL),
      REGLIST(TV_HDISP),
      REGLIST(TV_HSTART),
      REGLIST(TV_HCOUNT),
      REGLIST(TV_VTOTAL),
      REGLIST(TV_VDISP),
      REGLIST(TV_VCOUNT),
      REGLIST(TV_FTOTAL),
      REGLIST(TV_FCOUNT),
      REGLIST(TV_FRESTART),
      REGLIST(TV_HRESTART),
      REGLIST(TV_VRESTART),
      REGLIST(TV_VSCALER_CNTL1),
      REGLIST(TV_TIMING_CNTL),
      REGLIST(TV_VSCALER_CNTL2),
      REGLIST(TV_Y_FALL_CNTL),
      REGLIST(TV_Y_RISE_CNTL),
      REGLIST(TV_Y_SAW_TOOTH_CNTL),
      REGLIST(TV_UPSAMP_AND_GAIN_CNTL),
      REGLIST(TV_GAIN_LIMIT_SETTINGS),
      REGLIST(TV_LINEAR_GAIN_SETTINGS),
      REGLIST(TV_MODULATOR_CNTL1),
      REGLIST(TV_MODULATOR_CNTL2),
      REGLIST(TV_CRC_CNTL),
      REGLIST(TV_UV_ADR),
      REGLIST(GPIOPAD_A),
      REGLIST(RS480_UNK_e30),
      REGLIST(RS480_UNK_e34),
      REGLIST(RS480_UNK_e38),
      REGLIST(RS480_UNK_e3c),
};

void radeon_reg_match(const char *pattern)
{
    int i;
    unsigned long address;
    unsigned int value;

    if (pattern[0] == '0' && pattern[1] == 'x') {
        address = strtol(&(pattern[2]), NULL, 16);
        value = radeon_get(address, pattern);
        printf("%s\t0x%08x (%d)\n", pattern, value, value);
    }
    else if (pattern[0] == 'C' && pattern[1] == 'L' && pattern[2] == ':') {
        address = strtol(&(pattern[3]), NULL, 16);
        value = radeon_get_clk(address, pattern);
        printf("%s\t0x%08x (%d)\n", pattern, value, value);
    }
    else if (pattern[0] == 'M' && pattern[1] == 'C' && pattern[2] == ':') {
        address = strtol(&(pattern[3]), NULL, 16);
        value = radeon_get_mcind(address, pattern);
        printf("%s\t0x%08x (%d)\n", pattern, value, value);
    }
    else {
        for (i = 0; i < sizeof(reg_list) / sizeof(reg_list[0]); i++) {
            if (fnmatch(pattern, reg_list[i].name, 0) == 0) {
                value = reg_list[i].get(reg_list[i].address, reg_list[i].name);
                printf("%s (%s%04x)\t0x%08x (%d)\n", reg_list[i].name,
                       reg_list[i].type, reg_list[i].address, value, value);
            }
        }
      for (i = 0; i < 0x2f; i++) {
        value = radeon_get_mcind(i, "MC");
        printf("MC: 0x%02x\t0x%08x\n", i, value);
      }
    }
}

void set_reg(const char *name, const char *type, unsigned long address,
             unsigned int value,
             unsigned int (*get)(unsigned long, const char *),
             void (*set)(unsigned long, const char *, unsigned int))
{
    unsigned int readback;

    readback = get(address, name);
    printf("OLD: %s (%s%04lx)\t0x%08x (%d)\n", name, type, address,
           readback, readback);
    set(address, name, value);
    readback = get(address, name);
    printf("NEW: %s (%s%04lx)\t0x%08x (%d)\n", name, type, address,
           readback, readback);
}

void radeon_reg_set(const char *inname, unsigned int value)
{
    int i;
    unsigned long address;

    if (inname[0] == '0' && inname[1] == 'x') {
        address = strtol(&(inname[2]), NULL, 16);
        set_reg(inname, "", address, value, radeon_get, radeon_set);
    }
    else if (inname[0] == 'C' && inname[1] == 'L' && inname[2] == ':') {
        address = strtol(&(inname[3]), NULL, 16);
        set_reg(inname, "CL: ", address, value, radeon_get_clk, radeon_set_clk);
    }
    else {
        for (i = 0; i < sizeof(reg_list) / sizeof(reg_list[0]); i++) {
            if (fnmatch(inname, reg_list[i].name, 0) == 0) {
                set_reg(reg_list[i].name, reg_list[i].type, reg_list[i].address,
                        value, reg_list[i].get, reg_list[i].set);
            }
        }
    }
}

void radeon_cmd_bits(void)
{
    unsigned int dac_cntl;

    dac_cntl = radeon_get(RADEON_DAC_CNTL,"RADEON_DAC_CNTL");  
    printf("RADEON_DAC_CNTL=%08x (",dac_cntl);  
    if(dac_cntl & RADEON_DAC_RANGE_CNTL)
        printf("range_cntl ");  
    if(dac_cntl & RADEON_DAC_BLANKING)
        printf("blanking ");  
    if(dac_cntl & RADEON_DAC_8BIT_EN)
        printf("8bit_en ");  
    if(dac_cntl & RADEON_DAC_VGA_ADR_EN)
        printf("vga_adr_en ");  
    if(dac_cntl & RADEON_DAC_PDWN)
        printf("pdwn ");  
    printf(")\n");  
}

void radeon_cmd_dac(char *param)
{
    unsigned long dac_cntl;

    dac_cntl = radeon_get(RADEON_DAC_CNTL,"RADEON_DAC_CNTL");
    if(param == NULL) {
        printf("The radeon external DAC looks %s\n",(dac_cntl&(RADEON_DAC_PDWN))?"off":"on");
        exit (-1);
    } else if(strcmp(param,"off") == 0) {
        dac_cntl |= RADEON_DAC_PDWN;
    } else if(strcmp(param,"on") == 0) {
        dac_cntl &= ~ RADEON_DAC_PDWN;
    } else {
        usage();      
    };
    radeon_set(RADEON_DAC_CNTL,"RADEON_DAC_CNTL",dac_cntl);
}

void radeon_cmd_light(char *param)
{
    unsigned long lvds_gen_cntl;

    lvds_gen_cntl = radeon_get(RADEON_LVDS_GEN_CNTL,"RADEON_LVDS_GEN_CNTL");
    if(param == NULL) {
        printf("The radeon backlight looks %s\n",(lvds_gen_cntl&(RADEON_LVDS_ON))?"on":"off");
        exit (-1);
    } else if(strcmp(param,"on") == 0) {
        lvds_gen_cntl |= RADEON_LVDS_ON;
    } else if(strcmp(param,"off") == 0) {
        lvds_gen_cntl &= ~ RADEON_LVDS_ON;
    } else {
        usage();      
    };
    radeon_set(RADEON_LVDS_GEN_CNTL,"RADEON_LVDS_GEN_CNTL",lvds_gen_cntl);
}

void radeon_cmd_stretch(char *param)
{
    unsigned long fp_vert_stretch,fp_horz_stretch;

    fp_vert_stretch = radeon_get(RADEON_FP_VERT_STRETCH,"RADEON_FP_VERT_STRETCH");
    fp_horz_stretch = radeon_get(RADEON_FP_HORZ_STRETCH,"RADEON_FP_HORZ_STRETCH");
    if(param == NULL) {
        printf("The horizontal stretching looks %s\n",(fp_horz_stretch&(RADEON_HORZ_STRETCH_ENABLE))?"on":"off");
        printf("The vertical stretching looks %s\n",(fp_vert_stretch&(RADEON_VERT_STRETCH_ENABLE))?"on":"off");
        exit (-1);
    } else if(strncmp(param,"ver",3) == 0) {
        fp_horz_stretch &= ~ RADEON_HORZ_STRETCH_ENABLE;
        fp_vert_stretch |= RADEON_VERT_STRETCH_ENABLE;
    } else if(strncmp(param,"hor",3) == 0) {
        fp_horz_stretch |= RADEON_HORZ_STRETCH_ENABLE;
        fp_vert_stretch &= ~ RADEON_VERT_STRETCH_ENABLE;
    } else if(strcmp(param,"on") == 0) {
        fp_horz_stretch |= RADEON_HORZ_STRETCH_ENABLE;
        fp_vert_stretch |= RADEON_VERT_STRETCH_ENABLE;
    } else if(strcmp(param,"auto") == 0) {
        fp_horz_stretch |= RADEON_HORZ_AUTO_RATIO;
        fp_horz_stretch |= RADEON_HORZ_AUTO_RATIO_INC;
        fp_horz_stretch |= RADEON_HORZ_STRETCH_ENABLE;
        fp_vert_stretch |= RADEON_VERT_AUTO_RATIO_EN;
        fp_vert_stretch |= RADEON_VERT_STRETCH_ENABLE;
    } else if(strcmp(param,"manual") == 0) {
        fp_horz_stretch &= ~ RADEON_HORZ_AUTO_RATIO;
        fp_horz_stretch &= ~ RADEON_HORZ_AUTO_RATIO_INC;
        fp_horz_stretch |= RADEON_HORZ_STRETCH_ENABLE;
        fp_vert_stretch &= ~ RADEON_VERT_AUTO_RATIO_EN;
        fp_vert_stretch |= RADEON_VERT_STRETCH_ENABLE;
    } else if(strcmp(param,"off") == 0) {
        fp_horz_stretch &= ~ RADEON_HORZ_STRETCH_ENABLE;
        fp_vert_stretch &= ~ RADEON_VERT_STRETCH_ENABLE;
    } else {
        usage();      
    };
    radeon_set(RADEON_FP_HORZ_STRETCH,"RADEON_FP_HORZ_STRETCH",fp_horz_stretch);
    radeon_set(RADEON_FP_VERT_STRETCH,"RADEON_FP_VERT_STRETCH",fp_vert_stretch);
}


/* Here we fork() and exec() the lspci command to look for the Radeon hardware address. */
static void map_radeon_cntl_mem(void)
{
    struct pci_slot_match match;
    struct pci_device_iterator *iter;
    struct pci_device *device;
    int i = 0;

    if (pci_system_init() != 0)
        fatal("failed to initialise libpciaccess\n");

    match.domain = PCI_MATCH_ANY;
    match.bus = PCI_MATCH_ANY;
    match.dev = PCI_MATCH_ANY;

    match.func = 0;
    match.match_data = 0;
    iter = pci_slot_match_iterator_create(&match);

    while ((device = pci_device_next(iter))) {
        pci_device_probe(device);
        if (device->vendor_id == 0x1002 &&
            (device->device_class & 0x00ffff00) == 0x00030000) {
            if (debug) {
                printf("Found card %x:%x (%x)\n", device->vendor_id,
                       device->device_id, device->device_class);
                switch (device->device_id) {
                    case 0x7240:
                        printf("  r580 [Radeon X1900 (PCIE, G5 PowerMac)]\n");
                        break;
                    case 0x724b:
                        printf("  r580 [Radeon X1900 GT]\n");
                        break;
                    case 0x5e4b:
                        printf("  rv410 [Radeon X700 Pro (PCIE)]\n");
                        break;
                    default:
                        printf("  (unknown card)\n");
                        break;
                }
            }

            for (i = 0; i < 6; i++) {
                if (device->regions[i].size == 64 * 1024)
                    ctrl_region = i;
                else if (device->regions[i].size >= 128 * 1024 * 1024)
                    fb_region = i;
            }
            avivo_device = device;
            if(skip-- == 0) {
                break;
            }
        }
    }

    if (!avivo_device)
        fatal("cannot find Radeon device\n");

    if (pci_device_map_region(avivo_device, ctrl_region, 1) != 0)
        fatal("mapping ctrl region\n");
    ctrl_mem = avivo_device->regions[ctrl_region].memory;

    if (pci_device_map_region(avivo_device, fb_region, 1) != 0)
        fatal("mapping fb region\n");
    fb_mem = avivo_device->regions[fb_region].memory;

    pci_iterator_destroy(iter);

    if (debug)
        printf("Radeon found. Base control address is %lx; "
               "base framebuffer address is %lx.\n",
               (unsigned long) ctrl_mem, (unsigned long) fb_mem);

    radeon_cntl_mem = ctrl_mem;
}

#ifdef __powerpc__
#define __swab16(x) \
({ \
        unsigned short __x = (x); \
        ((unsigned short)( \
                (((unsigned short)(__x) & (unsigned short)0x00ffU) << 8) | \
                (((unsigned short)(__x) & (unsigned short)0xff00U) >> 8) )); \
})
#define __swab32(x) \
({ \
      unsigned int __x = (x); \
      ((unsigned int)( \
            (((unsigned int)(__x) & (unsigned int)0x000000ffUL) << 24) | \
            (((unsigned int)(__x) & (unsigned int)0x0000ff00UL) <<  8) | \
            (((unsigned int)(__x) & (unsigned int)0x00ff0000UL) >>  8) | \
            (((unsigned int)(__x) & (unsigned int)0xff000000UL) >> 24) )); \
})
#define BIOS16(offset)  __swab16(*((unsigned short *)(bios + (offset))))
#define BIOS32(offset)  __swab32(*((unsigned int *)(bios + (offset))))
#else
#define BIOS16(offset)  (*((unsigned short *)(bios + (offset))))
#define BIOS32(offset)  (*((unsigned int *)(bios + (offset))))
#endif
#define BIOS8(offset)   (*((unsigned char *)(bios + (offset))))

struct nametable_entry
{
      unsigned int value;
      const char *name;
};

const char *radeon_valname(const struct nametable_entry *table, unsigned int value)
{
      static char ret_buf[256];
      while(table->name) {
            if (table->value == value)
                  return table->name;
            table++;
      }
      sprintf(ret_buf, "<unknown val %d>", value);
      return ret_buf;
}

static struct nametable_entry hdr_type_name[] = {
      { 2, "Rage128 & Pro"},
      { 3, "Rage M3"},
      { 4, "Radeon"},
      { 36, "ATOM" },
      { 0, NULL}
};

static void radeon_rom_legacy_clocks(unsigned char *bios, int hdr)
{
      int pll_info_block = BIOS16(hdr + 0x30);
      int rev;

      if (pll_info_block == 0) {
            printf("No clock info block in BIOS\n");
            return;
      }
      rev = BIOS8(pll_info_block);
      printf("revision %d\n", rev);

      printf("Clock info block:\n");
      printf("  SCLK   : %f\n", BIOS16(pll_info_block + 0x0a) / 100.0);
      printf("  MCLK   : %f\n", BIOS16(pll_info_block + 0x08) / 100.0);
      printf("  RefClk : %f\n", BIOS16(pll_info_block + 0x0e) / 100.0);
      printf("  RefDiv : %d\n", BIOS16(pll_info_block + 0x10));
      printf("  VCO Min: %f\n", BIOS32(pll_info_block + 0x12) / 100.0);
      printf("  VCO Max: %f\n", BIOS32(pll_info_block + 0x16) / 100.0);

      if (rev > 9) {
          printf("  VCO in Min: %f\n", BIOS32(pll_info_block + 0x36) / 100.0);
          printf("  VCO in Max: %f\n", BIOS32(pll_info_block + 0x3a) / 100.0);
          printf("  VCO out Min: %f\n", BIOS32(pll_info_block + 0x3e) / 100.0);
          printf("  VCO out Max: %f\n", BIOS32(pll_info_block + 0x42) / 100.0);
      }

      printf("  SPLL RefClk  : %f\n", BIOS16(pll_info_block + 0x1a) / 100.0);
      printf("  SPLL ref div  : %d\n", BIOS16(pll_info_block + 0x1c));
      printf("  VCO Min: %f\n", BIOS32(pll_info_block + 0x1e) / 100.0);
      printf("  VCO Max: %f\n", BIOS32(pll_info_block + 0x22) / 100.0);

      printf("  MPLL RefClk  : %f\n", BIOS16(pll_info_block + 0x26) / 100.0);
      printf("  MPLL ref div  : %d\n", BIOS16(pll_info_block + 0x28));
      printf("  VCO Min: %f\n", BIOS32(pll_info_block + 0x2a) / 100.0);
      printf("  VCO Max: %f\n", BIOS32(pll_info_block + 0x2e) / 100.0);

      printf("\n");
}

static void radeon_rom_atom_clocks(unsigned char *bios, int master)
{

      int pll_info_block = BIOS16(master + 12);

      if (pll_info_block == 0) {
        printf("No clock info block in BIOS\n");
      }

      printf("Clock info block:\n");
      printf("  SCLK    : %f\n", BIOS32(pll_info_block + 8) / 100.0);
      printf("  MCLK    : %f\n", BIOS32(pll_info_block + 12) / 100.0);
      printf("  RefClk  : %f\n", BIOS16(pll_info_block + 82) / 100.0);
      printf("  PPLL in Min: %f\n", BIOS16(pll_info_block + 74) / 100.0);
      printf("  PPLL in Max: %f\n", BIOS16(pll_info_block + 76) / 100.0);
      printf("  PPLL out Min: %f\n", BIOS16(pll_info_block + 78) / 100.0);
      printf("  PPLL out Max: %f\n", BIOS32(pll_info_block + 32) / 100.0);
}


static struct nametable_entry lconn_type_name[] = {
      { 0, "None"},
      { 1, "Proprietary"},
      { 2, "VGA"},
      { 3, "DVI-I"},
      { 4, "DVI-D"},
      { 5, "CTV"},
      { 6, "STV"},
      { 7, "Unsupported"},
      { 0, NULL}
};

static struct nametable_entry lddc_type_name[] = {
      { 0, "None"},
      { 1, "MONID"},
      { 2, "DVI"},
      { 3, "VGA"},
      { 4, "CRT2"},
      { 0, NULL}
};

static struct nametable_entry ldac_type_name[] = {
      { 0, "CRT"},
      { 1, "TV"},
      { 2, "External"},
      { 0, NULL}
};

static void radeon_rom_legacy_connectors(unsigned char *bios, int hdr)
{
      int offset = BIOS16(hdr + 0x50);
      int i, entry, tmp, chips, entries;

      if (offset == 0) {
            printf("No connector table in BIOS\n");
            return;
      }

      printf("Connector table:\n");

#if 0
      printf("  raw: %02x %02x %02x %02x %02x %02x %02x %02x\n",
             BIOS8(offset+0), BIOS8(offset+1), BIOS8(offset+2),
             BIOS8(offset+3), BIOS8(offset+4), BIOS8(offset+5),
             BIOS8(offset+6), BIOS8(offset+7));
#endif


      chips = BIOS8(offset) >> 4; 
      printf("  Table revision %d for %d chip(s)\n",
             BIOS8(offset) & 0xf, chips);
      if (chips > 1)
            printf("  Only 1 chip supported for now !\n");
      entries = BIOS8(offset + 1) & 0xf;
      printf("  Table for chip %d has %d connector(s):\n",
             BIOS8(offset + 1) >> 4, entries);
      for (i = 0; i < entries; i++) {
            entry = offset + 2 + i*2;

            /* End of table */
            if (!BIOS16(entry)) {
                  if (i < entries)
                        printf("    <table early termination !>\n");
                  break;
            }

            /* Read table entry, check connector type */
            tmp = BIOS16(entry);
            printf("    %08x  ", tmp);
            printf("Type:%s", radeon_valname(lconn_type_name,
                                     (tmp >> 12) & 0xf));
            if (((tmp >> 8) & 0xf) == 5) {
                printf(", DDC:0x%x", BIOS8(entry+2));
            } else {
                printf(", DDC:%s", radeon_valname(lddc_type_name,
                                          (tmp >> 8) & 0xf));
            }
            printf(", DAC:%s", radeon_valname(ldac_type_name, tmp & 0x3));
            printf(", TMDS:%s", (tmp & 0x10) ? "External" : "Internal");
            printf(", MUX switch:%s", (tmp & 0x20) ? "yes" : "no");



            printf("\n");
      }
      printf("\n");
}

static struct nametable_entry atomconn_type_name[] = {
      { 0, "None"},
      { 1, "VGA"},
      { 2, "DVI-I"},
      { 3, "DVI-D"},
      { 4, "DVI-A"},
      { 5, "STV"},
      { 6, "CTV"},
      { 7, "LVDS"},
      { 8, "Digital"},
      { 9, "SCART"},
      { 10, "HDMI A"},
      { 11, "HDMI B"},
      { 14, "Special DIN"},
      { 15, "Unsupported"},
      { 0, NULL}
};

static void radeon_rom_atom_connectors(unsigned char *bios, int master)
{
      int offset = BIOS16(master + 22);
      int tmp, i, tmp0;
      int crtc, dac, connector, ddc=0;

      if (offset == 0) {
            printf("No connector table in BIOS\n");
            return;
      }

      tmp = BIOS16(offset + 4);
      printf("Connector table:\n");
      for (i=0; i<16; i++) {
            if (tmp & (1<<i)) {
                switch (i) {
                case 0:
                  printf("CRT1 ");
                  break;
                case 1:
                  printf("LCD1 ");
                  break;
                case 2:
                  printf("TV1 ");
                  break;
                case 3:
                  printf("DFP1 ");
                  break;
                case 4:
                  printf("CRT2 ");
                  break;
                case 5:
                  printf("LCD2 ");
                  break;
                case 6:
                  printf("TV2 ");
                  break;
                case 7:
                  printf("DFP2 ");
                  break;
                case 8:
                  printf("CV ");
                  break;
                case 9:
                  printf("DFP3 ");
                  break;
                default:
                  printf("unknown ");
                }

                  int portinfo = BIOS16(offset+6+i*2);

                  crtc = (portinfo >> 8) & 0xf;
                  dac = (portinfo & 0xf) - 1;
                  connector = (portinfo >> 4) & 0xf;

                  printf("output id: %d\n", crtc);

                  tmp0 = BIOS16(master + 24);
                  if (1/*crtc*/) {
                        int gpio = BIOS16(tmp0 + 4 + 27 * crtc) * 4;
                        printf("gpio is %02X\n", gpio);
                        switch(gpio)
                        {
                        case RADEON_GPIO_MONID: ddc = 1; break;
                        case RADEON_GPIO_DVI_DDC: ddc = 2; break;
                        case RADEON_GPIO_VGA_DDC: ddc = 3; break;
                        case RADEON_GPIO_CRT2_DDC: ddc = 4; break;
                        default: ddc=0; break;
                        }
                  }

                  printf("%d:    %08x ", i, portinfo);
                  printf(", Id:%d", crtc);
                  printf(", Type:%s",  radeon_valname(atomconn_type_name, connector));
                  if (1/*crtc*/)
                        printf(", DDC:%s", radeon_valname(lddc_type_name,
                                                  ddc));
                  printf(", DAC:%s",  radeon_valname(ldac_type_name, dac));
                  if (i==3)
                        printf(" TMDS: Internal\n");
                  else if (i==7)
                        printf(" TMDS: External\n");
                  else if (i==9)
                        printf(" TMDS: LVTMA\n");
                  else
                        printf("\n");
                        
            }
      }
}

static void radeon_rom_legacy_lcdtable(unsigned char *bios, int hdr)
{
      int offset, i, type_info, extended_offset;
      unsigned int setup;
      char stmp[30];

      offset = BIOS16(hdr + 0x40);
      if (offset == 0) {
            printf("No LCD info table\n");
            return;
      }
      printf("\nLCD info table:\n");
      printf("lcd panel id: %d\n", BIOS8(offset));
      for (i = 0; i < 24; i++)
          stmp[i] = BIOS8(offset+i+1);
      stmp[24] = 0;
      printf("lcd panel id string: %s\n", stmp);
      printf("lcd panel x: %d\n", BIOS16(offset+0x19));
      printf("lcd panel y: %d\n", BIOS16(offset+0x1b));

      type_info = BIOS16(offset+0x1d);
      if (type_info & 0x1)
          printf("color ");
      else
          printf("mono ");

      if (type_info & 0x2)
          printf("single ");
      else
          printf("dual ");

      switch ((type_info & 0xfc) >> 2) {
      case 0:
          printf("STN\n");
          break;
      case 1:
      default:
          printf("TFT\n");
          break;
      case 2:
          printf("active addressed STN\n");
          break;
      case 3:
          printf("EL\n");
          break;
      case 4:
          printf("Plasma\n");
          break;
      }

      printf("lcd panel power delay: %d\n", BIOS16(offset+0x24));

      extended_offset = BIOS16(offset+0x26);
      if (extended_offset) {
        int extended_rev;
            extended_rev = BIOS8(extended_offset);
            printf("lcd panel extended info offset: %x\n", extended_offset);
            printf("lcd extended info rev: %x\n", extended_rev);
            
            printf("SS delay %x step size %x\n", BIOS8(extended_offset+1),
                   BIOS8(extended_offset + 2));

            if (extended_rev > 1) {
                  printf("lcd fake edid id num  bytes %d\n", BIOS8(extended_offset+3));
                  printf("lcd fake edid id num offset 0x%x\n", BIOS16(extended_offset+4));
            }
            if (extended_rev > 2) {
                  printf("lcd LVPVS %x\n", BIOS8(extended_offset+6));
                  printf("lcd PVG/PCP %x\n", BIOS8(extended_offset+7));
                  printf("lcd SSPLL table offset %x\n", BIOS16(extended_offset+8));
            }
            if (extended_rev > 3) {
                  printf("lcd resp time coeff 0x%x\n", BIOS8(extended_offset+10));
            }
            if (extended_rev > 4) {
                  printf("edid low refresh offset 0x%x\n", BIOS16(extended_offset+11));
            }
      }

      printf("lcd panel vcc delay: %d\n", BIOS16(offset+0x2c));
      printf("lcd panel ref div: %d\n", BIOS16(offset+0x2e));
      printf("lcd panel post div: %d\n", BIOS8(offset+0x30));
      printf("lcd panel fb div: %d\n", BIOS16(offset+0x31));
      printf("SS type: %s / %s\n", (BIOS8(offset + 0x33) & 1) ? "center" : "down",
             (BIOS8(offset + 0x33) & (1<<7)) ? "internal" : "external");
      printf("SS percentage %x\n", BIOS16(offset + 0x34));
      printf("lcd panel DIGON to LVDS active: %d\n", BIOS8(offset+0x38) & 0xf);
      printf("lcd panel LVDS active to BLON: %d\n", (BIOS8(offset+0x38) >> 4) & 0xf);
      setup = BIOS32(offset+0x39);
      printf("lcd panel LVDS setup: 0x%x\n", setup);

      if (setup & 0x1)
          printf("888 RGB\n");
      else
          printf("666 RGB\n");

      switch ((setup >> 8) & 0x8) {
      case 0:
          printf("no frame modulation\n");
          break;
      case 1:
          printf("2 levels of grey\n");
          break;
      case 2:
          printf("4 levels of grey\n");
          break;
      default:
          printf("STN panel\n");
          break;
      }

      if ((setup >> 16) & 0x1)
          printf("frame pulse high\n");
      else
          printf("frame pulse low\n");

      if ((setup >> 17) & 0x1)
          printf("line pulse high\n");
      else
          printf("line pulse low\n");

      if ((setup >> 18) & 0x1)
          printf("MOD high\n");
      else
          printf("MOD low\n");

      if ((setup >> 23) & 0x1)
          printf("backlight mod 29 Mhz\n");
      else
          printf("backlight mod 29 Mhz / 3\n");
}

static void radeon_rom_legacy_mobiletable(unsigned char *bios, int hdr)
{
      int offset, rev, i, gpiooffset, blocks, powerplayoffset, lcdddcoffset, tmdspoweroffset;
      unsigned int reg, andmask, ormask;

      offset = BIOS16(hdr + 0x42);
      if (offset == 0) {
            printf("No mobile info table\n");
            return;
      }
      rev = BIOS8(offset);
      printf("mobile table revision: %d\n", rev);

      switch (BIOS8(offset + 0x8) & 0xf) {
      case 1:
          printf("CRT i2c clk=GPIO0, data=GPIO1\n");
          break;
      case 2:
          printf("CRT i2c clk=GPIO4, data=GPIO3\n");
          break;
      default:
          printf("%d\n", BIOS8(offset + 0x8) & 0xf);
          break;
      }

      gpiooffset = BIOS16(offset+0x13);
      if (gpiooffset) {
          printf("gpio table revision: %d\n", BIOS8(gpiooffset));
          blocks = BIOS8(gpiooffset + 0x2);
          printf("gpio blocks: %d\n", blocks);

          for (i = 0; i < blocks; i++) {
            reg = BIOS16(gpiooffset + 3 + (i * 10) + 0);
            andmask = BIOS32(gpiooffset + 3 + (i * 10) + 0x2);
            ormask = BIOS32(gpiooffset + 3 + (i * 10) + 0x6);
            printf("reg: 0x%x, AND: 0x%x, OR: 0x%x\n", reg * 4, andmask, ormask);
          }
      }
      powerplayoffset = BIOS16(offset+0x11);
      if (powerplayoffset) {
          unsigned int powerplay_flags;
          int powerplay_rev = BIOS8(powerplayoffset);
          printf("powerplay table revision: %d\n", powerplay_rev);
          blocks = BIOS8(powerplayoffset+0x2);
          printf("powerplay states: %d\n", blocks);
          for (i = 0; i < blocks; i++) {
            printf("state %d\n", i);
            powerplay_flags = BIOS16(powerplayoffset + 5 + (i * 0x10));
            if (powerplay_flags & 0x1)
                printf("\tMCLK_SRC_SPLL\n");
            else if (powerplay_flags & 0x2)
                printf("\tSCLK_SRC_MPLL\n");
            else
                printf("\tsplit clock\n");
            if (powerplay_flags & 0x4) {
                printf("\tvoltage drop supported\n");
                if (powerplay_flags & 0x8)
                  printf("\tvoltage drop active high\n");
                else
                  printf("\tvoltage drop active low\n");
            }
            if (powerplay_flags & 0x10)
                printf("\tlcd refresh rate change\n");
            if (powerplay_flags & 0x20)
                printf("\tengine clk control enabled\n");
            if (powerplay_flags & 0x40)
                printf("\tmemory clk control enabled\n");
            if (powerplay_flags & 0x80)
                printf("\toverclock mode\n");
            else if (powerplay_rev <= 3)
                printf("\tpowersave mode\n");
            if (powerplay_flags & 0x100)
                printf("\thalf engine clk\n");
            if (powerplay_flags & 0x200)
                printf("\tdynamic voltage control enabled\n");
            if (powerplay_flags & 0x400)
                printf("\tpower state sleep mode enabled\n");
            if (powerplay_flags & 0x800)
                printf("\tpower state load balancing enabled\n");
            if (powerplay_flags & 0x1000)
                printf("\tdefault DC state\n");
            if (powerplay_flags & 0x2000)
                printf("\tdefault DC low state\n");
            if (powerplay_rev > 3) {
                if (powerplay_flags & 0x4000)
                  printf("\tpowersave mode\n");
                if (powerplay_flags & 0x8000)
                  printf("\tthermal diode mode\n");
            }
            printf("\tmclk/sclk: %f/%f\n",
                   BIOS32(powerplayoffset + 5 + (i * 0x10) + 0x2) / 100.0,
                   BIOS32(powerplayoffset + 5 + (i * 0x10) + 0x6) / 100.0);
            switch (BIOS8(powerplayoffset + 5 + (i * 0x10) + 0xa)) {
            case 0:
                printf("\tLCD refresh: 50 Hz\n");
                break;
            case 2:
                printf("\tLCD refresh: 56 Hz\n");
                break;
            case 4:
                printf("\tLCD refresh: 60 Hz\n");
                break;
            case 6:
                printf("\tLCD refresh: 67 Hz\n");
                break;
            case 8:
                printf("\tLCD refresh: 70 Hz\n");
                break;
            case 10:
                printf("\tLCD refresh: 72 Hz\n");
                break;
            case 12:
                printf("\tLCD refresh: 75 Hz\n");
                break;
            case 14:
                printf("\tLCD refresh: 76 Hz\n");
                break;
            case 16:
                printf("\tLCD refresh: 85 Hz\n");
                  break;
            case 18:
                printf("\tLCD refresh: 90 Hz\n");
                break;
            case 20:
                printf("\tLCD refresh: 100 Hz\n");
                break;
            case 22:
                printf("\tLCD refresh: 120 Hz\n");
                break;
            case 24:
                printf("\tLCD refresh: 140 Hz\n");
                break;
            case 26:
                printf("\tLCD refresh: 150 Hz\n");
                break;
            case 28:
                printf("\tLCD refresh: 160 Hz\n");
                break;
            case 30:
                printf("\tLCD refresh: 200 Hz\n");
                break;
            case 1:
                printf("\tLCD refresh: 40 Hz\n");
                break;
            case 3:
                printf("\tLCD refresh: 30 Hz\n");
                break;
            default:
                break;
            }
            if (powerplay_rev < 6) {
                printf("\tvoltage control reg: 0x%x\n", BIOS16(powerplayoffset + 5 + (i * 0x10) + 0xb) * 4);
                printf("\tvoltage control bits: %d\n", BIOS8(powerplayoffset + 5 + (i * 0x10) + 0xd));
            } else {
                int j;
                int entries = BIOS8(powerplayoffset + 5 + (i * 0x10) + 0xb);
                int voltage_table_offset = BIOS16(powerplayoffset + 5 + (i * 0x10) + 0xc);
                if (entries && voltage_table_offset) {
                  printf("\t%d entries in voltage drop table\n", entries);
                  printf("\tvoltage drop table at 0x%x\n", voltage_table_offset);
                  for (j = 0; j < entries; j++) {
                      printf("\t\tvoltage drop register: 0x%x\n",
                           BIOS16(voltage_table_offset) * 4);
                      printf("\t\tvoltage drop register bits: %d\n",
                           BIOS16(voltage_table_offset + 0x2));
                  }
                }
            }
            if (powerplay_rev < 5) {
                if (BIOS16(powerplayoffset + 5 + (i * 0x10) + 0xe))
                  printf("\tpowerplay memory reset table at 0x%x\n",
                         BIOS16(powerplayoffset + 5 + (i * 0x10) + 0xe));
            } else {
                int powerplay_flags2 = BIOS16(powerplayoffset + 5 + (i * 0x10) + 0xe);
                if (powerplay_flags2 & 0x1)
                  printf("\tenable frame modulation w/ 2 level grey\n");
                else if (powerplay_flags2 & 0x2)
                  printf("\tenable frame modulation w/ 4 level grey\n");
                else
                  printf("\tdisable frame modulation\n");
                if (powerplay_flags2 & 0x4)
                  printf("\tenable dynamic half clock\n");
                if (powerplay_flags2 & 0x8)
                  printf("\tenable dynamic clock on static screen\n");
                if (powerplay_flags2 & 0x10)
                  printf("\tenable dynamic clocking in 2D\n");
                if ((powerplay_flags2 & 0xe0) == 0x20)
                  printf("\tdynamic clocking divider: 1/2\n");
                else if ((powerplay_flags2 & 0xe0) == 0x40)
                  printf("\tdynamic clocking divider: 1/3\n");
                else if ((powerplay_flags2 & 0xe0) == 0x60)
                  printf("\tdynamic clocking divider: 1/4\n");
                printf("\tdelay between voltage drop and sclk change: ");
                if ((powerplay_flags2 & 0x700) == 0)
                  printf("no delay\n");
                else if ((powerplay_flags2 & 0x700) == 0x100)
                  printf("33 us\n");
                else if ((powerplay_flags2 & 0x700) == 0x200)
                  printf("66 us\n");
                else if ((powerplay_flags2 & 0x700) == 0x300)
                  printf("99 us\n");
                else if ((powerplay_flags2 & 0x700) == 0x400)
                  printf("132 us\n");
                if (powerplay_rev > 6) {
                  int pcie_lanes;
                  if (powerplay_flags2 & 0x800)
                      printf("\tperformance mode\n");
                  if (powerplay_flags2 & 0x1000)
                      printf("\tvri-brightness required\n");
                  pcie_lanes = BIOS8(powerplayoffset + 5 + (i * 0x10) + 0x10);
                  if (pcie_lanes == 0)
                      pcie_lanes = 16;
                  printf("\t%d pcie lanes\n", pcie_lanes);
                }
            }
          }
      }
      lcdddcoffset = BIOS16(offset+0x15);
      if (lcdddcoffset) {
          int i2cline;
          printf("LCD DDC table revision: %d\n", BIOS8(lcdddcoffset));
          i2cline = BIOS8(lcdddcoffset+0x2);
          printf("LCD DDC table i2c line: %d\n", i2cline);
          if (i2cline > 4) {
            printf("LCD DDC table i2c clock pin mask: 0x%x\n", BIOS32(lcdddcoffset+0x3));
            printf("LCD DDC table i2c data pin mask: 0x%x\n", BIOS32(lcdddcoffset+0x7));
          }
      }
      tmdspoweroffset = BIOS16(offset+0x17);
      if (tmdspoweroffset) {
          int tmdsflags = BIOS8(tmdspoweroffset + 1);
          int ontable_offset = BIOS16(tmdspoweroffset + 2);
          int ontable_rev = BIOS8(ontable_offset);
          int offtable_offset = BIOS16(tmdspoweroffset + 4);
          int offtable_rev = BIOS8(offtable_offset);
          printf("tmds power on/off table at offset: 0x%x\n", tmdspoweroffset);
          printf("tmds power on/off table revision: %d\n", BIOS8(tmdspoweroffset));
          if (tmdsflags & 1)
            printf("external tmds\n");
          else
            printf("internal tmds\n");
          printf("tmds power on table revision: %d\n", ontable_rev);
          if (ontable_rev == 1) {
            // fix me
          } else if (ontable_rev == 2) {
            int j = 4;
            int type;
            int blocks = BIOS8(ontable_offset + 3);
            int start = BIOS16(ontable_offset + j);
            int size = BIOS16(ontable_offset + 1);
            printf("tmds on table size: %d bytes\n", size);
            printf("tmds on table blocks: %d \n", blocks);
            while (blocks > 0) {
                type = (start & 0xe000) >> 13;
                if (type == 0) {
                  unsigned int reg = BIOS16(ontable_offset + j) & 0x1fff;
                  unsigned int val = BIOS32(ontable_offset + j + 2);
                  printf("mmio reg: 0x%x, val: 0x%x\n", reg, val);
                  j += 6;
                } else if (type == 2) {
                  unsigned int reg = BIOS16(ontable_offset + j) & 0x1fff;
                  unsigned int and_mask = BIOS32(ontable_offset + j + 2);
                  unsigned int or_mask = BIOS32(ontable_offset + j + 6);
                  printf("mmio reg: 0x%x, AND mask: 0x%x, OR mask: 0x%x\n",
                         reg * 4, and_mask, or_mask);
                  j += 10;
                } else if (type == 3) {
                  printf("delay %d ms\n", BIOS16(ontable_offset + j + 2));
                  j += 4;
                } else if (type == 4) {
                  printf("delay %d us\n", BIOS16(ontable_offset + j + 2));
                  j += 4;
                } else if (type == 6) {
                  int i2c_slave_addr = BIOS16(ontable_offset + j) & 0xff;
                  int i2c_id = BIOS8(ontable_offset + j + 2);
                  int i2c_reg = BIOS8(ontable_offset + j + 3);
                  int i2c_reg_val = BIOS8(ontable_offset + j + 4);
                  printf("write to i2c addr 0x%x (i2c id %d) reg: 0x%x, val: 0x%x\n",
                         i2c_slave_addr, i2c_id, i2c_reg, i2c_reg_val);
                  j += 5;
                } else
                  break;
                blocks--;;
                start = BIOS16(ontable_offset + j);
            }
          }
          printf("tmds power off table revision: %d\n", offtable_rev);
          if (offtable_rev == 1) {
            // fix me
          } else if (offtable_rev == 2) {
            int j = 4;
            int type;
            int blocks = BIOS8(offtable_offset + 3);
            int start = BIOS16(offtable_offset + j);
            int size = BIOS16(offtable_offset + 1);
            printf("tmds off table size: %d bytes\n", size);
            printf("tmds off table blocks: %d \n", blocks);
            while (blocks > 0) {
                type = (start & 0xe000) >> 13;
                if (type == 0) {
                  unsigned int reg = BIOS16(offtable_offset + j) & 0x1fff;
                  unsigned int val = BIOS32(offtable_offset + j + 2);
                  printf("mmio reg: 0x%x, val: 0x%x\n", reg, val);
                  j += 6;
                } else if (type == 2) {
                  unsigned int reg = BIOS16(offtable_offset + j) & 0x1fff;
                  unsigned int and_mask = BIOS32(offtable_offset + j + 2);
                  unsigned int or_mask = BIOS32(offtable_offset + j + 6);
                  printf("pll reg: 0x%x, AND mask: 0x%x, OR mask: 0x%x\n",
                         reg * 4, and_mask, or_mask);
                  j += 10;
                } else if (type == 3) {
                  printf("delay %d ms\n", BIOS16(offtable_offset + j + 2));
                  j += 4;
                } else if (type == 4) {
                  printf("delay %d us\n", BIOS16(offtable_offset + j + 2));
                  j += 4;
                } else if (type == 6) {
                  int i2c_slave_addr = BIOS16(offtable_offset + j) & 0xff;
                  int i2c_id = BIOS8(offtable_offset + j + 2);
                  int i2c_reg = BIOS8(offtable_offset + j + 3);
                  int i2c_reg_val = BIOS8(offtable_offset + j + 4);
                  printf("write to i2c addr 0x%x (i2c id %d) reg: 0x%x, val: 0x%x\n",
                         i2c_slave_addr, i2c_id, i2c_reg, i2c_reg_val);
                  j += 5;
                } else
                  break;
                blocks--;
                start = BIOS16(offtable_offset + j);
            }
          }
      }
      if (rev > 7) {
            int external_ss_table = BIOS16(offset+0x15);
            if (external_ss_table) {
                  printf("External SS table present %d\n", external_ss_table);
                  printf("revision %d size bytes %d block %d\n", BIOS8(external_ss_table), BIOS8(external_ss_table + 1), BIOS8(external_ss_table + 2));

                  printf("header bytes %d\n", BIOS8(external_ss_table + 3));
            }
            
      }
}

static void radeon_rom_legacy_dfptable(unsigned char *bios, int hdr)
{
      int offset, i, n, rev, stride;

      offset = BIOS16(hdr + 0x34);
      if (offset == 0) {
            printf("No DFP info table\n");
            return;
      }
      rev = BIOS8(offset);
      printf("DFP table revision: %d\n", rev);

      switch(rev) {
      case 3:
            n = BIOS8(offset + 5) + 1;
            if (n > 4)
                  n = 4;
            for (i = 0; i < n; i++) {
                  /* Looks weird ... but that's what is in X.org */
                  printf("  PixClock: %f\t TMDS_PLL_CNTL: %08x\n",
                         BIOS16(offset+i*10+0x10) / 100.0,
                         BIOS32(offset+i*10+0x08));
            }
            break;

      /* revision 4 has some problem as it appears in RV280...
       */
      case 4:
            stride = 0;
            n = BIOS8(offset+ 5) + 1;
            if (n > 4)
                  n = 4;
            for (i = 0; i < n; i++) {
                  printf("  PixClock: %f\t TMDS_PLL_CNTL: %08x\n",
                         BIOS16(offset+stride+0x10) / 100.0,
                         BIOS32(offset+stride+0x08));
                  if (i == 0)
                        stride += 10;
                  else
                        stride += 6;
            }
            break;
      }
}

static void radeon_rom_legacy_crttable(unsigned char *bios, int hdr)
{
      int offset, rev, dac2table, dac2muxreg, bgadjcrt1, dacwhitecrt1, bgadjcrt2, dacadjcrt2, temp;
      
      offset = BIOS16(hdr + 0x60);
      if (offset == 0) {
            printf("No CRT info table\n");
            return;
      }
      rev = BIOS8(offset) & 0x3;
      printf("\nCRT table revision: %d\n", rev);

      printf("\nCRT table size: %d bytes\n", BIOS8(offset+1));

      if (rev == 2) {

          bgadjcrt1 = BIOS8(offset + 0x2);
          dacwhitecrt1 = BIOS8(offset + 0x3);
          printf("crt1: 0x%x, 0x%x\n", bgadjcrt1, dacwhitecrt1);

          bgadjcrt2 = BIOS8(offset + 0x4);
          dacadjcrt2 = BIOS8(offset + 0x5);
          printf("crt2: 0x%x, 0x%x\n", bgadjcrt2, dacadjcrt2);

          dac2table = BIOS16(offset+8); 

      } else {

          bgadjcrt1 = BIOS8(offset + 0x2) & 0xf;
          dacwhitecrt1 = (BIOS8(offset + 0x2) >> 4) & 0xf;
          printf("crt1: 0x%x, 0x%x\n", bgadjcrt1, dacwhitecrt1);

          bgadjcrt2 = BIOS8(offset + 0x3) & 0xf;
          dacadjcrt2 = (BIOS8(offset + 0x3) >> 4) & 0xf;
          printf("crt2: 0x%x, 0x%x\n", bgadjcrt2, dacadjcrt2);

          dac2table = BIOS16(offset + 0x5); 
      }

      printf("reg val 0x%x\n", (bgadjcrt2 << 16) | (dacadjcrt2 << 20));

      if (dac2table) {
          printf("\nDac2 table: 0x%x\n", dac2table);
          printf("revision: %d\n", (BIOS16(dac2table) & 0x3));
          dac2muxreg = BIOS16(dac2table + 0x2);
          printf("\nmux reg: 0x%x\n", dac2muxreg);
          temp = BIOS8(dac2table + 0x4);
          if (temp & 0x80)
            printf("CRT2 active high\n");
          else
            printf("CRT2 active low\n");

          printf("pin detection bits: 0x%x\n", (temp & 0x1f));
          printf("access mode: 0x%x\n", ((temp >> 5) & 0x3));

      }

}

static void radeon_rom_legacy_list_tables_present(unsigned char *bios, int hdr)
{
    int offset;

    offset = BIOS16(hdr + 0xc);
    if (offset) {
      printf("asic init table 1\n");
    }
    offset = BIOS16(hdr + 0x14);
    if (offset) {
      printf("bios support info table\n");
    }
    offset = BIOS16(hdr + 0x2a);
    if (offset) {
      printf("dac programming info table\n");
    }
    offset = BIOS16(hdr + 0x2c);
    if (offset) {
      printf("max color depth info table\n");
    }
    offset = BIOS16(hdr + 0x2e);
    if (offset) {
      printf("crtc info table\n");
    }
    offset = BIOS16(hdr + 0x30);
    if (offset) {
      printf("pll info table\n");
    }
    offset = BIOS16(hdr + 0x32);
    if (offset) {
      printf("TV info table\n");
    }
    offset = BIOS16(hdr + 0x34);
    if (offset) {
      printf("DFP info table\n");
    }
    offset = BIOS16(hdr + 0x36);
    if (offset) {
      printf("HW config info table\n");
    }
    offset = BIOS16(hdr + 0x38);
    if (offset) {
      printf("multimedia info table\n");
    }
    offset = BIOS16(hdr + 0x3e);
    if (offset) {
      printf("tv standard patch table\n");
    }
    offset = BIOS16(hdr + 0x40);
    if (offset) {
      printf("LCD info table\n");
    }
    offset = BIOS16(hdr + 0x42);
    if (offset) {
      printf("Mobile info table\n");
    }
    offset = BIOS16(hdr + 0x46);
    if (offset) {
      printf("pll init info table\n");
    }
    offset = BIOS16(hdr + 0x48);
    if (offset) {
      printf("mem config info table\n");
    }
    offset = BIOS16(hdr + 0x4a);
    if (offset) {
      printf("save mask info table\n");
    }
    offset = BIOS16(hdr + 0x4c);
    if (offset) {
      printf("Hardcoded DFP edid\n");
    }
    offset = BIOS16(hdr + 0x4e);
    if (offset) {
      printf("asic init table 2\n");
    }
    offset = BIOS16(hdr + 0x50);
    if (offset) {
      printf("connector info table\n");
    }
    offset = BIOS16(hdr + 0x52);
    if (offset) {
      printf("dyn clock 1 info table\n");
    }
    offset = BIOS16(hdr + 0x54);
    if (offset) {
      printf("reserved mem info table\n");
    }
    offset = BIOS16(hdr + 0x58);
    if (offset) {
      printf("Ext TMDS info table\n");
    }
    offset = BIOS16(hdr + 0x5a);
    if (offset) {
      printf("mem clock info table\n");
    }
    offset = BIOS16(hdr + 0x5c);
    if (offset) {
      printf("ext DAC info table\n");
    }
    offset = BIOS16(hdr + 0x5e);
    if (offset) {
      printf("misc info table\n");
    }
    offset = BIOS16(hdr + 0x60);
    if (offset) {
      printf("CRT info table\n");
    }
    offset = BIOS16(hdr + 0x62);
    if (offset) {
      printf("integrated system info table\n");
    }
    offset = BIOS16(hdr + 0x64);
    if (offset) {
      printf("Component video info table\n");
    }
    offset = BIOS16(hdr + 0x66);
    if (offset) {
      printf("fan speed info table\n");
    }
    offset = BIOS16(hdr + 0x68);
    if (offset) {
      printf("overdrive info table\n");
    }
    offset = BIOS16(hdr + 0x6a);
    if (offset) {
      printf("OEM info table\n");
    }
    offset = BIOS16(hdr + 0x6c);
    if (offset) {
      printf("dyn clock 2 info table\n");
    }
    offset = BIOS16(hdr + 0x6e);
    if (offset) {
      printf("power connector info table\n");
    }
    offset = BIOS16(hdr + 0x70);
    if (offset) {
      printf("i2c info table\n");
    }
    offset = BIOS16(hdr + 0x72);
    if (offset) {
      printf("object header info table\n\n");
    }
    printf("\n");
}

static void radeon_rom_legacy_biosinfotable(unsigned char *bios, int hdr)
{
    int offset, i;
    char strp[4];

    offset = BIOS16(hdr + 0x14);
    if (offset == 0) {
      printf("bios info table\n");
      return;
    }
    printf("bios info table\n");
    for (i = 0; i < 4; i++)
      strp[i] = BIOS8(offset + i);
    printf("chip type: %s\n", strp);
    for (i = 0; i < 4; i++)
      strp[i] = BIOS32(offset + 4 + i);
    printf("bus type: %s\n", strp);
    for (i = 0; i < 4; i++)
      strp[i] = BIOS32(offset + 8 + i);
    printf("mem type: %s\n", strp);


}

static void radeon_rom_legacy_miscinfotable(unsigned char *bios, int hdr)
{
    int offset, rev, start, size;

    offset = BIOS16(hdr + 0x5e);
    if (offset == 0) {
      printf("No misc info table\n");
      return;
    }
    rev = BIOS8(offset);
    printf("misc info table revision: %d\n", rev);
    if (rev > 0) {
      size = BIOS8(offset + 2);
      printf("misc info table size: %d bytes\n", size);

    }
    start = BIOS8(offset + 1);
    if (start & 0x1)
      printf("dualview supported\n");
    if (rev == 8)
      if (start & 0x8)
          printf("sleep mode enabled in perfomance mode\n");
    if (start & 0x20)
      printf("hypermemory flag\n");
    if (rev == 5) {
      if (start & 0x40)
          printf("sleep mode enabled in perfomance mode\n");
    } else if (rev == 8) {
      if (start & 0x40)
          printf("power state load balancing is enabled in perfomance mode\n");
    }
    if (rev == 6)
      if (start & 0x80)
          printf("WMI thermal method supported\n");
    if (rev > 0) {
        if (BIOS16(offset + 0x3)) {
          printf("asic init table 3 offset: 0x%x\n", BIOS16(offset + 0x3));
          radeon_rom_legacy_mmio_table(bios, BIOS16(offset + 0x3));
      }
      if (BIOS16(offset + 0x5)) {
          printf("asic init table 4 offset: 0x%x\n", BIOS16(offset + 0x5));
          radeon_rom_legacy_mmio_table(bios, BIOS16(offset + 0x5));
      }
      if (BIOS16(offset + 0x7))
          printf("detected mem config table offset: 0x%x\n", BIOS16(offset + 0x7));
      if (rev == 2) {
          if (BIOS16(offset + 0x9))
            printf("asic init table 5 offset: 0x%x\n", BIOS16(offset + 0x9));
          if (BIOS16(offset + 0xb))
            printf("memreset sequence table offset: 0x%x\n", BIOS16(offset + 0xb));
      } else if ((rev == 4) || (rev == 5) || (rev == 6)) {
          if (BIOS16(offset + 0x9))
            printf("pointer to asic init table 5 offset list: 0x%x\n", BIOS16(offset + 0x9));
          if (BIOS16(offset + 0xb))
            printf("pointer to memreset sequence table offset list: 0x%x\n", BIOS16(offset + 0xb));
      }
      if ((rev == 5) || (rev == 6)) {
          if (BIOS16(offset + 0xd))
            printf("mem info table offset: 0x%x\n", BIOS16(offset + 0xd));
          printf("min backlight value: 0x%x\n", BIOS8(offset + 0xf));
      }
      if (rev == 7) {
          if (BIOS16(offset + 0x7))
            printf("pointer to detected mem config table offset list: 0x%x\n", BIOS16(offset + 0x7));
          if (BIOS16(offset + 0x9))
            printf("pointer to asic init table 5 offset list: 0x%x\n", BIOS16(offset + 0x9));
          if (BIOS16(offset + 0xb))
            printf("pointer to memreset sequence table offset list: 0x%x\n", BIOS16(offset + 0xb));
      }
      if (rev >= 6) {
          int flags = BIOS8(offset + 0x10);
          if (flags & 0x1)
            printf("driver controls brightness\n");
          if (flags & 0x2)
            printf("bios controls powerplay\n");
          if (flags & 0x4)
            printf("use new mem reset sequence\n");
          if (flags & 0x8)
            printf("power state load balancing is disabled in performance mode\n");
          if (rev == 9)
            if (flags & 0x40)
                printf("PCIE to PCI bridge present\n");
      }

    }
}

static void radeon_rom_legacy_mmio_table(unsigned char *bios, int offset)
{
      if (!offset)
            return;

      while (BIOS16(offset)) {
            uint16_t cmd = (BIOS16(offset) & 0xe000) >> 13;
            uint32_t addr = BIOS16(offset) & 0x1fff;
            uint32_t val, and_mask, or_mask, tmp;

            offset+=2;
            switch(cmd) {
            case 0:
            case 1:
                  val = BIOS32(offset);
                  offset += 4;
                  printf("write reg %x %x\n", addr, val);
                  break;
            case 2:
            case 3:
                  and_mask = BIOS32(offset);
                  offset += 4;
                  or_mask = BIOS32(offset);
                  offset += 4;
                  printf("write reg %x and %x or %x val\n",
                         addr, and_mask, or_mask);
                  break;
            case 4:
                  val = BIOS16(offset);
                  offset += 2;
                  printf("delay %x\n", val);
                  break;
            case 5:
                  val = BIOS16(offset);
                  offset += 2;
                  switch (addr) {
                  case 8:
                        printf("wait for CLK_PWRMGR CNTL MC busy %x\n", val);
                        break;
                  case 9:
                        printf("wait for MC_STATUS MC idle %x\n", val);
                        break;
                  }
                  break;
            default:
                  printf("unknown\n");
            }
      }
}


static void radeon_rom_legacy_asicinittable(unsigned char *bios, int hdr)
{
      int offset = BIOS16(hdr + 0xc);
      if (offset) {
            printf("asic init table 1\n");
            radeon_rom_legacy_mmio_table(bios, offset);
      }

      offset = BIOS16(hdr + 0x4e);
      if (offset) {
            printf("-----------------\n");
            printf("asic init table 2\n");
            radeon_rom_legacy_mmio_table(bios, offset);
      }
}

static void radeon_rom_legacy_plltable(unsigned char *bios, int offset)
{
      int type, start, i = 0;
      start = BIOS8(offset);
      while (start != 0) {
            type = (start & 0xc0) >> 6;
            if (type == 0) {
                  int reg = BIOS8(offset + i) & 0x3f;
                  unsigned int val = BIOS32(offset + i + 1);
                  printf("pll reg: 0x%x, val: 0x%x\n", reg, val);
                  i += 5;
            } else if (type == 1) {
                  int reg = BIOS8(offset + i) & 0x3f;
                  int byte_offset = BIOS8(offset + i + 1);
                  int and_mask = BIOS8(offset + i + 2);
                  int or_mask  = BIOS8(offset + i + 3);
                  printf("pll reg: 0x%x, byte offset of dword 0x%x, AND mask: 0x%x, OR mask: 0x%x\n",
                         reg, byte_offset, and_mask, or_mask);
                  i += 4;
            } else if (type >= 2) {
                  int cmd = BIOS8(offset + i) & 0x3f;
                  switch (cmd) {
                  case 1:
                        printf("delay 150 us\n");
                        break;
                  case 2:
                        printf("delay 1 ms\n");
                        break;
                  case 3:
                        printf("wait for MC_BUSY = 0 in CLK_PWRMGT_CNTL\n");
                        break;
                  case 4:
                        printf("wait for DLL_READY = 1 in CLK_PWRMGT_CNTL\n");
                        break;
                  case 5:
                        printf("check and set bit 24 in CLK_PWRMGT_CNTL to 0\n");
                        break;
                  default:
                        printf("ass\n");
                        break;
                  }
                  i += 1;
            } else
                  break;
            start = BIOS8(offset + i);
      }
}

static void radeon_rom_legacy_dynclk1table(unsigned char *bios, int hdr)
{
      int offset, type, start, i = 0;

      offset = BIOS16(hdr + 0x52);
      if (offset == 0) {
            printf("No dyn clock 1 info table\n");
            return;
      }
      printf("dyn clock 1 info table\n");
      radeon_rom_legacy_plltable(bios, offset);
}

static void radeon_rom_legacy_pllinittable(unsigned char *bios, int hdr)
{
      int offset, type, start, i = 0;

      offset = BIOS16(hdr + 0x46);
      if (offset == 0) {
            return;
      }
      printf("pll init table %x\n", BIOS8(offset - 1));
      radeon_rom_legacy_plltable(bios, offset);
}
static void radeon_rom_legacy_dynclk2table(unsigned char *bios, int hdr)
{
    int offset, type, start, rev, i = 0;

    offset = BIOS16(hdr + 0x52);
    if (offset == 0) {
      printf("No dyn clock 2 info table\n");
      return;
    }
    rev = BIOS8(offset - 1);
    start = BIOS16(offset);
    printf("dyn clock 2 info table revision %d\n", rev);
    while (start != 0) {
      type = (start & 0xe000) >> 13;
      if (type == 0) {
          unsigned int reg = BIOS16(offset + i) & 0x1fff;
          unsigned int val = BIOS32(offset + i + 2);
          printf("mmio reg: 0x%x, val: 0x%x\n", reg * 4, val);
          i += 6;
      } else if (type == 1) {
          unsigned int reg = BIOS16(offset + i) & 0x1fff;
          unsigned int val = BIOS32(offset + i + 2);
          printf("I/O reg: 0x%x, val: 0x%x\n", reg * 4, val);
          i += 6;
      } else if (type == 2) {
          unsigned int reg = BIOS16(offset + i) & 0x1fff;
          unsigned int and_mask = BIOS32(offset + i + 2);
          unsigned int or_mask = BIOS32(offset + i + 6);
          printf("mmio reg: 0x%x, AND mask: 0x%x, OR mask: 0x%x\n",
               reg * 4, and_mask, or_mask);
          i += 10;
      } else if (type == 3) {
          unsigned int reg = BIOS16(offset + i) & 0x1fff;
          unsigned int and_mask = BIOS32(offset + i + 2);
          unsigned int or_mask = BIOS32(offset + i + 6);
          printf("I/O reg: 0x%x, AND mask: 0x%x, OR mask: 0x%x\n",
               reg * 4, and_mask, or_mask);
          i += 10;
      } else if (type == 4) {
          printf("delay %d us\n", BIOS16(offset + i + 2));
          i += 4;
      } else
          break;
      start = BIOS16(offset + i);
    }
}

static void radeon_rom_legacy_igptable(unsigned char *bios, int hdr)
{
    int offset, rev, fsb;

      offset = BIOS16(hdr + 0x62);
      if (offset == 0) {
            printf("No igp info table\n");
            return;
      }
      rev = BIOS8(offset);
      printf("\nigp table revision: %d\n", rev);

      fsb = BIOS16(offset + 0x2);
      if (rev < 2)
          fsb *= 100;
      printf("FSB: %f Mhz\n", fsb);

      printf("mclk reference frequency: %f Mhz\n", BIOS16(offset + 0x4) / 100.00);
      printf("mclk reference divider: %d \n", BIOS16(offset + 0x6));
      printf("memory refresh period from SPD: %d \n", BIOS8(offset + 0x8));
      if (rev > 0)
          printf("min mclk: %f \n", BIOS16(offset + 0xd) / 100.00);
      if (rev > 1)
          printf("max mclk: %f \n", BIOS16(offset + 0xf) / 100.00);
      if (rev > 2) {
          printf("K8 mclk: %f \n", BIOS16(offset + 0x11));
          printf("K8 sync start delay: %f us\n", BIOS16(offset + 0x13) / 100);
          printf("K8 data return time: %f us\n", BIOS16(offset + 0x15) / 100);
      }
      if (rev > 3) {
          if (BIOS16(offset + 0x17) & 1)
            printf("PCIE lane reserved\n");
          else
            printf("PCIE lane not reserved\n");
      }
}

static void radeon_rom_legacy_componenttv_table(unsigned char *bios, int hdr)
{
    int offset, rev, temp;

      offset = BIOS16(hdr + 0x62);
      if (offset == 0) {
            printf("No component tv info table\n");
            return;
      }
      rev = BIOS8(offset);
      printf("\ncomponent tv table revision: %d\n", rev);

      if (rev < 3) {
          if (BIOS8(offset + 0x2) & 0x4)
            printf("CRT2 Mux used as well to switch to CV\n");
          if (BIOS8(offset + 0x2) & 0x8)
            printf("Low voltage TV/CV MUX control\n");
      } else {
          if (BIOS8(offset + 0x2) & 0x10)
            printf("enable access for i2c D-Connect Support\n");
      }
      printf("GPIO register for detection: 0x%x \n", BIOS16(offset + 0x3));
      temp = BIOS8(offset + 0x5);
      if (temp & 0x80)
          printf("Active high\n");
      else
          printf("Active low\n");
      printf("GPIO TV/HDTV MUX control register: 0x%x \n", BIOS16(offset + 0x6));
      temp = BIOS8(offset + 0x8);
      if (temp & 0x80)
          printf("Active high\n");
      else
          printf("Active low\n");

}

static void radeon_rom_legacy_i2ctable(unsigned char *bios, int hdr)
{
    int offset, rev, size, blocks, i, id, reg, clock, data;

      offset = BIOS16(hdr + 0x70);
      if (offset == 0) {
            printf("No i2c info table\n");
            return;
      }
      rev = BIOS8(offset);
      printf("\ni2c table revision: %d\n", rev);
      size = BIOS8(offset + 1);
      printf("i2c table size: %d\n", size);

      blocks = BIOS8(offset + 2);
      printf("i2c blocks: %d\n", blocks);

      for (i = 0; i < blocks; i++) {
          id = BIOS8(offset + 3 + (i * 5) + 0);
          reg = BIOS16(offset + 3 + (i * 5) + 1);
          clock = BIOS8(offset + 3 + (i * 5) + 3);
          data = BIOS8(offset + 3 + (i * 5) + 4);
          printf("id: %d, reg: 0x%x, clk: %d, data: %d\n", id, reg * 4, clock, data);
      }

}

static void radeon_rom_legacy_tvtable(unsigned char *bios, int hdr)
{
      int offset, rev, refclk, drvstds, biosstds;
      
      offset = BIOS16(hdr + 0x32);
      if (offset == 0) {
            printf("No TV info table\n");
            return;
      }
      rev = BIOS8(offset + 3);
      printf("\nTV table revision: %d\n", rev);


      printf("\nTV table size: %d\n", BIOS16(offset + 4));

      if (BIOS8(offset + 6) == 'T')
          printf("TV out on board\n");
      else
          printf("No TV out on board\n");

      printf("Default Standard: ");
      switch (BIOS8(offset + 7)) {
      case 1:
          printf("NTSC\n");
          break;
      case 2:
          printf("PAL\n");
          break;
      case 3:
          printf("PAL-M\n");
          break;
      case 4:
          printf("PAL-60\n");
          break;
      case 5:
          printf("NTSC-J\n");
          break;
      case 6:
          printf("SCART-PAL\n");
          break;
      default:
          printf("Unknown standard\n");
            break;
      }

      printf("TV Ref Clk: ");
      refclk = BIOS8(offset + 9) >> 2;
      if (refclk == 0)
          printf("29.498928713 MHz\n");
      else if (refclk == 1)
          printf("28.636360000 MHz\n");
      else if (refclk == 2)
          printf("14.318180000 MHz\n");
      else if (refclk == 3)
          printf("27.000000000 MHz\n");

      printf("TV standards supported by driver: ");
      drvstds = BIOS8(offset + 10);
      if (drvstds & 1)
          printf("NTSC ");
      if (drvstds & 2)
          printf("PAL ");
      if (drvstds & 4)
          printf("PAL-M ");
      if (drvstds & 8)
          printf("PAL-60 ");
      if (drvstds & 16)
          printf("NTSC-J ");
      if (drvstds & 32)
          printf("SCART-PAL");
      printf("\n");

      printf("TV standards supported by bios: ");
      biosstds = BIOS8(offset + 11);
      if (biosstds & 1)
          printf("NTSC ");
      if (biosstds & 2)
          printf("PAL ");
      if (biosstds & 4)
          printf("PAL-M ");
      if (biosstds & 8)
          printf("PAL-60 ");
      if (biosstds & 16)
          printf("NTSC-J ");
      if (biosstds & 32)
          printf("SCART-PAL");
      printf("\n");

      if (rev >= 5) {
          int temp, temp2;

          temp = BIOS8(offset + 0xc);
          temp2 = BIOS8(offset + 0xd);
          printf("crt2 ps2: 0x%x, 0x%x\n", temp, temp2);

          temp = BIOS8(offset + 0xe);
          temp2 = BIOS8(offset + 0xf);
          printf("crt2 pal: 0x%x, 0x%x\n", temp, temp2);

          temp = BIOS8(offset + 0x10);
          temp2 = BIOS8(offset + 0x11);
          printf("crt2 ntsc: 0x%x, 0x%x\n", temp, temp2);

          temp = BIOS16(offset + 0x12);
          printf("gpio reg: 0x%x\n", temp);

          temp = BIOS16(offset + 0x14);
          printf("gpio AND mask: 0x%x\n", temp);

          temp = BIOS16(offset + 0x18);
          printf("gpio OR mask: 0x%x\n", temp);

      } else if (rev >= 2) {
          int temp, temp2;

          temp = BIOS8(offset + 0xc) & 0xf;
          temp2 = (BIOS8(offset + 0xc) >> 4) & 0xf;
          printf("crt2 ps2: 0x%x, 0x%x\n", temp, temp2);

          temp = BIOS8(offset + 0xd) & 0xf;
          temp2 = (BIOS8(offset + 0xd) >> 4) & 0xf;
          printf("crt2 pal: 0x%x, 0x%x\n", temp, temp2);

          temp = BIOS8(offset + 0xe) & 0xf;
          temp2 = (BIOS8(offset + 0xe) >> 4) & 0xf;
          printf("crt2 ntsc: 0x%x, 0x%x\n", temp, temp2);

          if (rev > 2) {
            temp = BIOS8(offset + 0x10);
            printf("gpio bit: 0x%x\n", temp);
          }

          if (rev > 3) {
            temp = BIOS16(offset + 0x11);
            printf("gpio reg: 0x%x\n", temp);
          }

      }


}

static void radeon_rom_legacy_exttmdstable(unsigned char *bios, int hdr)
{
      int offset, rev;
      int nr_blocks;
      int table_start;
      unsigned short index;
      unsigned short id;
      offset = BIOS16(hdr + 0x58);
      if (offset == 0) {
            printf("No External TMDS table found\n");
            return;
      }

      rev = BIOS8(offset);

      printf("Found External TMDS Table rev %d\n", rev);

      if (rev == 2)
          printf("single link\n");
      else if (rev == 3)
          printf("dual link\n");

      printf("table size %08x\n", BIOS16(offset+1));


      nr_blocks = BIOS8(offset+3);

      printf("no blocks %08x\n", nr_blocks);

      table_start = offset+4;
      printf("max freq %d, slave i2c %02x i2c %d conn id %d, flags %d\n",
             BIOS16(table_start), BIOS8(table_start+2), BIOS8(table_start+3),
             BIOS8(table_start+4), BIOS8(table_start+5));

      index = table_start+6;
      printf("next short is %04X\n", BIOS16(index)>>13);

      id = BIOS16(index);
      printf("id is %04X %d\n", id, id & 0x1fff);

      while (id != 0xffff) {
             switch(id >> 13) {
             case 0:
                   printf("mm write\n");
                   index += 6;
                   break;
             case 2:
                   printf("mm mask write\n");
                   index += 10;
                   break;
             case 4:
                   printf("delay microsec \n");
                   index += 4;
                   break;
             case 5:
                   printf("pll mask write \n");
                   index += 10;
                   break;
             case 6:
                   printf("i2c write %02X\n", BIOS8(index+2));
                   index += 3;
                   break;
             default:
                   printf("unknown id %d\n", id>>13);
                   return;
             };

             id = BIOS16(index);
             printf("id is %04X %d\n", id, id & 0x1fff);

      }
}

void radeon_rom_legacy_memclktable(unsigned char *bios, int hdr)
{ 
      int offset = BIOS16(hdr + 0x5a);
      int block_rev;
      if (!offset)
            return;

      block_rev = BIOS8(offset);
      while (block_rev != 0xff) {
            printf("mem clock table header %d\n", block_rev);
            if (block_rev == 1) {
                  printf("mem clock min %d ,max %d\n", BIOS16(offset + 1), BIOS16(offset + 3));
                  offset += 5;
            }
            if (block_rev == 2) {
                  printf("pre mem clock reset table %d\n", BIOS16(offset + 1));
                  offset += 3;
            }
            if (block_rev == 3) {
                  printf("pll change table %d\n", BIOS16(offset + 1));
                  offset += 3;
            }
            if (block_rev == 4) {
                  printf("register change table %d\n", BIOS16(offset + 1));
                  offset += 3;
            }
            if (block_rev == 5) {
                  printf("post memory clock reset seq table %d\n", BIOS16(offset + 1));
                  offset += 3;
            }
            if (block_rev == 6) {
                  printf("mc register change table %d\n", BIOS16(offset + 1));
                  offset += 3;
            }
            if (block_rev == 7) {
                  printf("pll pre clock lock table %d\n", BIOS16(offset + 1));
                  offset += 3;
            }
            if (block_rev == 8) {
                  printf("pre clock change table %d\n", BIOS16(offset + 1));
                  offset += 3;
            }
            if (block_rev == 9) {
                  printf("post memory clock reset seq table 2 %d\n", BIOS16(offset + 1));
                  offset += 3;
            }
            block_rev = BIOS8(offset);
      }
}
void radeon_rom_tables(const char * file)
{
#define _64K (64*1024)
      unsigned char bios[_64K];
      int fd, hdr, atom;

      fd = open(file, O_RDONLY);
      if (fd < 0) {
            perror("can't open rom file");
            return;
      }
      memset(bios, 0, _64K);
      read(fd, bios, _64K);
      close(fd);

      if (bios[0] != 0x55 || bios[1] != 0xaa)
            fatal("PCI ROM signature 0x55 0xaa missing");
      hdr = BIOS16(0x48);
      printf("\nBIOS Tables:\n------------\n\n");     
      printf("Header at %x, type: %d [%s]\n", hdr, BIOS8(hdr),
             radeon_valname(hdr_type_name, BIOS8(hdr)));
      printf("OEM ID: %02x %02x\n", BIOS8(hdr+2), BIOS8(hdr+3));
      atom = (BIOS8(hdr+4)   == 'A' &&
            BIOS8(hdr+5) == 'T' &&
            BIOS8(hdr+6) == 'O' &&
            BIOS8(hdr+7) == 'M') ||
            (BIOS8(hdr+4)   == 'M' &&
             BIOS8(hdr+5) == 'O' &&
             BIOS8(hdr+6) == 'T' &&
             BIOS8(hdr+7) == 'A');
      if (atom) {
            int master = BIOS16(hdr+32);
            printf("ATOM BIOS detected !\n\n");
            radeon_rom_atom_clocks(bios, master);
            radeon_rom_atom_connectors(bios, master);
            // add more ...
      } else {
            printf("Legacy BIOS detected !\n");
            printf("BIOS Rev: %x.%x\n\n", BIOS8(hdr+4), BIOS8(hdr+5));
            radeon_rom_legacy_list_tables_present(bios, hdr);
            printf("-------------\n");
            radeon_rom_legacy_asicinittable(bios, hdr);
            printf("-------------\n");
            radeon_rom_legacy_pllinittable(bios, hdr);
            printf("-------------\n");
            radeon_rom_legacy_clocks(bios, hdr);
            printf("-------------\n");
            radeon_rom_legacy_connectors(bios, hdr);
            printf("-------------\n");
            radeon_rom_legacy_dfptable(bios, hdr);
            printf("-------------\n");
            radeon_rom_legacy_exttmdstable(bios, hdr);
            printf("-------------\n");
            radeon_rom_legacy_tvtable(bios, hdr);
            printf("-------------\n");
            radeon_rom_legacy_crttable(bios, hdr);
            printf("-------------\n");
            radeon_rom_legacy_i2ctable(bios, hdr);
            printf("-------------\n");
            radeon_rom_legacy_lcdtable(bios, hdr);
            printf("-------------\n");
            radeon_rom_legacy_mobiletable(bios, hdr);
            printf("-------------\n");
            radeon_rom_legacy_igptable(bios, hdr);
            printf("-------------\n");
            radeon_rom_legacy_componenttv_table(bios, hdr);
            printf("-------------\n");
            radeon_rom_legacy_dynclk1table(bios, hdr);
            printf("-------------\n");
            radeon_rom_legacy_dynclk2table(bios, hdr);
            printf("-------------\n");
            radeon_rom_legacy_miscinfotable(bios, hdr);
                printf("-------------\n");
            radeon_rom_legacy_biosinfotable(bios, hdr);
                printf("-------------\n");
            radeon_rom_legacy_memclktable(bios, hdr);
                printf("-------------\n");
      }
}

int main(int argc,char *argv[]) 
{
    if(argc == 1) {
        map_radeon_cntl_mem();
      usage();
    }
    if(strcmp(argv[1],"--debug") == 0) {
        debug=1;
        argv++; argc--;
    };
    if(argc > 1 && strcmp(argv[1],"--skip=") == 0) {
        skip=atoi(argv[1]+7);
        argv++; argc--;
    };
    map_radeon_cntl_mem();
    if(argc == 2) {
        if(strcmp(argv[1],"regs") == 0) {
            radeon_cmd_regs();
            return 0;
        } else if(strcmp(argv[1],"bits") == 0) {
            radeon_cmd_bits();
            return 0;
        } else if(strcmp(argv[1],"dac") == 0) {
            radeon_cmd_dac(NULL);
            return 0;
        } else if(strcmp(argv[1],"light") == 0) {
            radeon_cmd_light(NULL);
            return 0;
        } else if(strcmp(argv[1],"stretch") == 0) {
            radeon_cmd_stretch(NULL);
            return 0;
        };
    } else if(argc == 3) {
        if(strcmp(argv[1],"dac") == 0) {
            radeon_cmd_dac(argv[2]);
            return 0;
        } else if(strcmp(argv[1],"light") == 0) {
            radeon_cmd_light(argv[2]);
            return 0;
        } else if(strcmp(argv[1],"stretch") == 0) {
            radeon_cmd_stretch(argv[2]);
            return 0;
        } else if(strcmp(argv[1],"regmatch") == 0) {
            radeon_reg_match(argv[2]);
            return 0;
        } else if(strcmp(argv[1],"romtables") == 0) {
            radeon_rom_tables(argv[2]);
            return 0;
      };
    } else if(argc == 4) {
          if(strcmp(argv[1],"regset") == 0) {
                radeon_reg_set(argv[2], strtoul(argv[3], NULL, 0));
                return 0;
          }
    }

    usage();
    return 1;
}




Generated by  Doxygen 1.6.0   Back to index