/*
 * cc -lpciaccess dumpio.c -o dumpio
 */
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <pciaccess.h>

#define A(reg) (*(unsigned *)(map_base + (reg)))

#define RADEON_CRTC_H_TOTAL_DISP            0x0200
#define RADEON_CRTC_H_SYNC_STRT_WID         0x0204
#define RADEON_CRTC_V_TOTAL_DISP            0x0208
#define RADEON_CRTC_V_SYNC_STRT_WID         0x020c
#define RADEON_CRTC_OFFSET                  0x0224
#define RADEON_CRTC_OFFSET_CNTL             0x0228
#define RADEON_CRTC_PITCH                   0x022c
#define RADEON_DISP_MERGE_CNTL              0x0d60
#define RADEON_CRTC_MORE_CNTL               0x027c
#define RADEON_CRTC_VLINE_CRNT_VLINE        0x0210
#define RADEON_CRTC_CRNT_FRAME              0x0214
#define RADEON_CRTC_GUI_TRIG_VLINE          0x0218
#define RADEON_CRTC_STATUS                  0x005c

main(int argc, char **argv)
{
    void *map_base;
    struct pci_device *dev;
    struct pci_id_match match;
    struct pci_device_iterator *iter;

    if (pci_system_init()) {
	printf("pci_system_init: %s\n", strerror(errno)); exit(-1);
    }
    match.vendor_id = 0x1002;
    match.device_id = PCI_MATCH_ANY;
    match.subvendor_id = PCI_MATCH_ANY;
    match.subdevice_id = PCI_MATCH_ANY;
    match.device_class = 0;
    match.device_class_mask = 0;
    if (!(iter = pci_id_match_iterator_create(&match))) {
	printf("pci_id_match_iterator_create: %s\n", strerror(errno)); exit(-1);
    }
    while (1) {
	if (!(dev = pci_device_next(iter))) {
	    printf("device not found\n"); exit(-1);
	}
	if (dev->device_id == 0x5834
#if 0
         || dev->device_id == 0x5d44 
#endif
				     ) {
	    break;
	}
    }
    if (pci_device_probe(dev)) {
	printf("pci_device_probe: %s\n", strerror(errno)); exit(-1);
    }
    printf("phys_base: 0x%08llx phys_len: 0x%08llx\n", dev->regions[2].base_addr, dev->regions[2].size);
    if (pci_device_map_range(dev, dev->regions[2].base_addr, 
                             dev->regions[2].size, 1, &map_base)) {
        printf("pci_device_map_range: %s\n", strerror(errno)); exit(-1);
    }

    printf("\n");
    printf("RADEON_CRTC_H_TOTAL_DISP        ==> 0x%08x\n", A(RADEON_CRTC_H_TOTAL_DISP));
    printf("RADEON_CRTC_H_SYNC_STRT_WID     ==> 0x%08x\n", A(RADEON_CRTC_H_SYNC_STRT_WID));
    printf("RADEON_CRTC_V_TOTAL_DISP        ==> 0x%08x\n", A(RADEON_CRTC_V_TOTAL_DISP));
    printf("RADEON_CRTC_V_SYNC_STRT_WID     ==> 0x%08x\n", A(RADEON_CRTC_V_SYNC_STRT_WID));
    printf("RADEON_CRTC_OFFSET              ==> 0x%08x\n", A(RADEON_CRTC_OFFSET));
    printf("RADEON_CRTC_OFFSET_CNTL         ==> 0x%08x\n", A(RADEON_CRTC_OFFSET_CNTL));
    printf("RADEON_CRTC_PITCH               ==> 0x%08x\n", A(RADEON_CRTC_PITCH));
    printf("RADEON_DISP_MERGE_CNTL          ==> 0x%08x\n", A(RADEON_DISP_MERGE_CNTL));
    printf("RADEON_CRTC_MORE_CNTL           ==> 0x%08x\n", A(RADEON_CRTC_MORE_CNTL));
    printf("RADEON_CRTC_VLINE_CRNT_VLINE    ==> 0x%08x\n", A(RADEON_CRTC_VLINE_CRNT_VLINE) >> 16);
    printf("RADEON_CRTC_CRNT_FRAME          ==> 0x%08x\n", A(RADEON_CRTC_CRNT_FRAME));
    printf("RADEON_CRTC_STATUS              ==> 0x%08x\n", A(RADEON_CRTC_STATUS));
    printf("RADEON_CRTC_GUI_TRIG_VLINE      ==> 0x%08x\n", A(RADEON_CRTC_GUI_TRIG_VLINE));

}

