how to read data from pcie bus

The following three files can be used:
main file:

/* pci_debug.c
 *
 * 6/21/2010 D. W. Hawkins
 *
 * PCI debug registers interface.
 *
 * This tool provides a debug interface for reading and writing
 * to PCI registers via the device base address registers (BARs).
 * The tool uses the PCI resource nodes automatically created
 * by recently Linux kernels.
 *
 * The readline library is used for the command line interface
 * so that up-arrow command recall works. Command-line history
 * is not implemented. Use -lreadline -lcurses when building.
 *
 * ----------------------------------------------------------------
 */
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

/* Readline support */
#include <readline/readline.h>
#include <readline/history.h>
#include "generic_api.h"
#include "pci_utils.h"

void display_help(void);
void parse_command(void);
int process_command(char *cmd);

int handle_reg(char *cmd);
int handle_hbm(char *cmd);
void handle_reg_read(uint64_t addr, uint32_t len);
void handle_hbm_read(uint64_t addr, uint32_t len, uint32_t width);
void handle_hbm_fill(uint64_t addr, uint64_t val, uint64_t len, uint32_t inc, uint32_t width);

int handle_csb(char *cmd);
void handle_csb_read(uint64_t addr, uint32_t len);

/* Usage */
static void show_usage()
{
    
    
    printf("\nUsage: pci_debug -s <device>>\n"\
         "  -h                Help (this message)\n"\
         "  -s <device>       PCIe slot/device (as per lspci)\n\n");
}

int main(int argc, char *argv[])
{
    
    
    printf("//------------------------------\n");
    printf("// PCI_DEBUG start...\n");
    printf("//------------------------------\n\n");

    char *device = 0;
    int opt;
    uint32_t i;

    setbuf(stdout, NULL);

	while ((opt = getopt(argc, argv, "hs:")) != -1) {
    
    
		switch (opt) {
    
    
			case 'h':
				show_usage();
				return -1;
			case 's':
				device = optarg;
				break;
			default:
				show_usage();
				return -1;
		}
	}
	if (device == 0) {
    
    
		//show_usage();
		//return -1;
	}

    if (pci_init(device)) {
    
    
        printf("PCI_DEBUG: ERROR! PCIe device init fail, device=%s\n", device);
        return 1;
    }
	
    /* Display help */
	display_help();

	/* Process commands */
	parse_command();
   
    // Test end
    pci_cleanup();
    printf("//------------------------------\n");
    printf("// PCI_DEBUG finish...\n");
    printf("//------------------------------\n\n");

    return 0;
}

void
parse_command()
{
    
    
	char *line;
	int len;
	int status;

	while(1) {
    
    
		line = readline("PCI> ");
		/* Ctrl-D check */
		if (line == NULL) {
    
    
			printf("\n");
			continue;
		}
		/* Empty line check */
		len = strlen(line);
		if (len == 0) {
    
    
			continue;
		}
		/* Process the line */
		status = process_command(line);
		if (status < 0) {
    
    
			break;
		}

		/* Add it to the history */
		add_history(line);
		free(line);
	}
	return;
}

/*--------------------------------------------------------------------
 * User interface
 *--------------------------------------------------------------------
 */
void
display_help()
{
    
    
	printf("\n");
	printf("  ?                             Help\n");
	printf("  regr addr len                 Display register starting from addr\n");
	printf("  regw addr val                 Change register at addr to val\n");
	printf("  csbr addr len                 Display CSB starting from addr\n");
	printf("  csbw addr val                 Change CSB at addr to val\n");
	printf("  hbmr[width] addr len          Display HBM starting from addr\n");
	printf("                                [width]\n");
	printf("                                  32  - 32-bit access (default)\n");
	printf("                                  64  - 64-bit access (default)\n");
	printf("  hbmw[width] addr val          Change HBM at addr to val\n");
	printf("  hbmf[width] addr val len inc  Fill memory\n");
	printf("                                  addr - start address\n");
	printf("                                  val  - start value\n");
	printf("                                  len  - length (in bytes)\n");
	printf("                                  inc  - increment (defaults to 1)\n");
	printf("  q                             Quit\n");
	printf("\n  Notes:\n");
	printf("    1. addr, len, and val are interpreted as hex values\n");
	printf("       addresses are always byte based\n");
	printf("\n");
}

int process_command(char *cmd)
{
    
    
	if (cmd[0] == '\0') {
    
    
		return 0;
	}
	switch (cmd[0]) {
    
    
		case '?':
			display_help();
			break;
		case 'r':
		case 'R':
			return handle_reg(cmd);
		case 'c':
		case 'C':
			return handle_csb(cmd);
		case 'h':
		case 'H':
			return handle_hbm(cmd);
		case 'q':
		case 'Q':
			return -1;
		default:
			break;
	}
	return 0;
}

int handle_reg(char *cmd)
{
    
    
	uint64_t addr = 0;
	uint32_t len = 0;
    uint64_t val = 0;
	int status;
	int i;

	if (cmd[3] == 'r') {
    
    
		status = sscanf(cmd, "%*s %lx %d", &addr, &len);
		if (status != 2) {
    
    
			printf("Syntax error (use ? for help), %s %d\n", __FILE__, __LINE__);
			/* Don't break out of command processing loop */
			return 0;
		}
        handle_reg_read(addr, len);
	} else if (cmd[3] == 'w') {
    
    
		status = sscanf(cmd, "%*s %lx %lx", &addr, &val);
		if (status != 2) {
    
    
			printf("Syntax error (use ? for help), %s %d\n", __FILE__, __LINE__);
			/* Don't break out of command processing loop */
			return 0;
		}
        reg_write(addr, val);
	} else {
    
    
		printf("Syntax error (use ? for help), %s %d\n", __FILE__, __LINE__);
		/* Don't break out of command processing loop */
		return 0;
    }
	
    printf("\n");
    return 0;
}

void handle_reg_read(uint64_t addr, uint32_t len)
{
    
    
    uint32_t rdata;
    uint32_t i;
    for (i = 0; i < len; i+=4) {
    
    
    	if ((i%16) == 0) {
    
    
    		printf("\n%.8lX: ", addr+i);
    	}
        reg_read(addr+i, &rdata);
    	printf("%.8X ", rdata);
    }
    printf("\n");
}

void handle_csb_read(uint64_t addr, uint32_t len)
{
    
    
    uint32_t rdata;
    uint32_t i;
    for (i = 0; i < len; i+=4) {
    
    
    	if ((i%16) == 0) {
    
    
    		printf("\n%.8lX: ", addr+i);
    	}
        csb_read(addr+i, &rdata);
    	printf("%.8X ", rdata);
    }
    printf("\n");
}

int handle_csb(char *cmd)
{
    
    
	uint64_t addr = 0;
	uint32_t len = 0;
    uint64_t val = 0;
	int status;
	int i;

	if (cmd[3] == 'r') {
    
    
		status = sscanf(cmd, "%*s %lx %d", &addr, &len);
		if (status != 2) {
    
    
			printf("Syntax error (use ? for help), %s %d\n", __FILE__, __LINE__);
			/* Don't break out of command processing loop */
			return 0;
		}
        handle_csb_read(addr, len);
	} else if (cmd[3] == 'w') {
    
    
		status = sscanf(cmd, "%*s %lx %lx", &addr, &val);
		if (status != 2) {
    
    
			printf("Syntax error (use ? for help), %s %d\n", __FILE__, __LINE__);
			/* Don't break out of command processing loop */
			return 0;
		}
        csb_write(addr, val);
	} else {
    
    
		printf("Syntax error (use ? for help), %s %d\n", __FILE__, __LINE__);
		/* Don't break out of command processing loop */
		return 0;
    }
	
    printf("\n");
    return 0;
}

int handle_hbm(char *cmd)
{
    
    
	uint32_t width = 32;
	uint64_t addr = 0;
	uint32_t len = 0;
    uint64_t val = 0;
    uint32_t inc = 1;
	int status;
	int i;
    uint32_t rdata32;
    uint64_t rdata64;

	if (cmd[3] == 'r') {
    
    
        if (cmd[4] == ' ') {
    
    
		    status = sscanf(cmd, "%*s %lx %d", &addr, &len);
		    if (status != 2) {
    
    
		    	printf("Syntax error (use ? for help), %s %d\n", __FILE__, __LINE__);
		    	/* Don't break out of command processing loop */
		    	return 0;
		    }
        } else {
    
    
		    status = sscanf(cmd+4, "%d %lx %d", &width, &addr, &len);
		    if (status != 3) {
    
    
		    	printf("Syntax error (use ? for help), %s %d\n", __FILE__, __LINE__);
		    	/* Don't break out of command processing loop */
		    	return 0;
		    }
        }
        if (width == 32 || width == 64) {
    
    
            handle_hbm_read(addr, len, width);
        } else {
    
    
		    printf("Syntax error (use ? for help), %s %d\n", __FILE__, __LINE__);
		    /* Don't break out of command processing loop */
		    return 0;
        }
	} else if (cmd[3] == 'w') {
    
    
        if (cmd[4] == ' ') {
    
    
		    status = sscanf(cmd, "%*s %lx %lx", &addr, &val);
		    if (status != 2) {
    
    
		    	printf("Syntax error (use ? for help), %s %d\n", __FILE__, __LINE__);
		    	/* Don't break out of command processing loop */
		    	return 0;
		    }
            mem_write32(addr, val);
        } else {
    
    
		    status = sscanf(cmd+4, "%d %lx %lx", &width, &addr, &val);
		    if (status != 3) {
    
    
		    	printf("Syntax error (use ? for help), %s %d\n", __FILE__, __LINE__);
		    	/* Don't break out of command processing loop */
		    	return 0;
		    }
            if (width == 32) {
    
    
                mem_write32(addr, val);
            } else if (width == 64) {
    
    
                mem_write64(addr, val);
            } else {
    
    
		    	printf("Syntax error (use ? for help), %s %d\n", __FILE__, __LINE__);
		    	/* Don't break out of command processing loop */
		    	return 0;
            }
        }
	} else if (cmd[3] == 'f') {
    
    
        if (cmd[4] == ' ') {
    
    
		    status = sscanf(cmd, "%*s %lx %lx %d %x", &addr, &val, &len, &inc);
		    if ((status != 3) && (status != 4)) {
    
    
		    	printf("Syntax error (use ? for help), %s %d\n", __FILE__, __LINE__);
		    	/* Don't break out of command processing loop */
		    	return 0;
		    }
		    if (status == 3) {
    
    
		    	inc = 1;
		    }
        } else {
    
    
		    status = sscanf(cmd+4, "%d %lx %lx %d %x", &width, &addr, &val, &len, &inc);
		    if ((status != 4) && (status != 5)) {
    
    
		    	printf("Syntax error (use ? for help), %s %d\n", __FILE__, __LINE__);
		    	/* Don't break out of command processing loop */
		    	return 0;
		    }
		    if (status == 4) {
    
    
		    	inc = 1;
		    }
        } 
        if (width == 32 || width == 64) {
    
    
            handle_hbm_fill(addr, val, len, inc, width);
        } else {
    
    
		    printf("Syntax error (use ? for help), %s %d\n", __FILE__, __LINE__);
		    /* Don't break out of command processing loop */
		    return 0;
        }
	} else {
    
    
		printf("Syntax error (use ? for help), %s %d\n", __FILE__, __LINE__);
		/* Don't break out of command processing loop */
		return 0;
    }
	
    printf("\n");
    return 0;
}

void handle_hbm_read(uint64_t addr, uint32_t len, uint32_t width)
{
    
    
    uint32_t i;
    uint32_t rdata32;
    uint64_t rdata64;
    if (width == 32) {
    
    
        for (i = 0; i < len; i+=4) {
    
    
        	if ((i%16) == 0) {
    
    
        		printf("\n%.8lX: ", addr+i);
        	}
            mem_read32(addr+i, &rdata32);
        	printf("%.8X ", rdata32);
        }
    } else if (width == 64) {
    
    
        for (i = 0; i < len; i+=8) {
    
    
        	if ((i%16) == 0) {
    
    
        		printf("\n%.8lX: ", addr+i);
        	}
            mem_read64(addr+i, &rdata64);
        	printf("%.8lX ", rdata64);
        }
    }
    printf("\n");
}

void handle_hbm_fill(uint64_t addr, uint64_t val, uint64_t len, uint32_t inc, uint32_t width)
{
    
    
	int i;
    uint32_t wdata32;
    uint64_t wdata64;

	if (width == 32) {
    
    
		for (i = 0; i < len; i+=4) {
    
    
			wdata32 = (uint32_t)(val + i*inc);
            mem_write32(addr+i, wdata32);
		}
    } else if (width == 64) {
    
    
		for (i = 0; i < len; i+=8) {
    
    
			wdata64 = (uint64_t)(val + i*inc);
            mem_write64(addr+i, wdata64);
		}
    }
}

generic_api

#ifndef GENERIC_API_H_
#define GENERIC_API_H_

#ifdef __cplusplus
extern "C" {
    
    
#endif

void reg_write(uint64_t offset, uint32_t wdata);
void reg_read(uint64_t offset, uint32_t *rdata);
void reg_pull(uint64_t offset, uint32_t exp_data);
void mem_write32(uint64_t offset, uint32_t wdata);
void mem_read32(uint64_t offset, uint32_t *rdata);
void mem_write64(uint64_t offset, uint64_t wdata);
void mem_read64(uint64_t offset, uint64_t *rdata);
void csb_write(uint64_t offset, uint32_t wdata);
void csb_read(uint64_t offset, uint32_t *rdata);
//int kmem_alloc(uint32_t size, uint64_t *paddr, void **vaddr);
//int kmem_release(uint32_t id);
int wait_irq(uint32_t vec);

#ifdef __cplusplus
}
#endif

#endif

#include <stdio.h>
#include <stdint.h>

/* Libraries for accessing PCIe devices */
#ifdef __cplusplus
extern "C" {
    
    
#endif

void pci_init(char *device);
void pci_cleanup();
void bar_write(uint32_t idx, uint64_t offset, uint64_t data, uint32_t ndw);
void bar_read(uint32_t idx, uint64_t offset, uint64_t *data, uint32_t ndw);

void pci_cfg_write(uint32_t offset, uint32_t data);
void pci_cfg_read(uint32_t offset, uint32_t *data);
int kmem_reserve(uint32_t size);
int kmem_release(uint32_t id);
uint64_t kmem_get_paddr(uint32_t id);
void* kmem_mmap(uint32_t id, uint32_t size);
int wait_msi_vector(uint32_t vec);

#ifdef __cplusplus
}
#endif

#define REG_BAR     1
#define MEM_BAR     2
#define CSB_BAR     4

void reg_write(uint64_t offset, uint32_t wdata)
{
    
    
    bar_write(REG_BAR, offset, wdata, 0x1);
}

void reg_read(uint64_t offset, uint32_t *rdata)
{
    
    
    uint64_t rdata64;
    bar_read(REG_BAR, offset, &rdata64, 0x1);
    *rdata = 0xFFFFFFFF & rdata64;
}

void reg_pull(uint64_t offset, uint32_t exp_data)
{
    
    
    uint32_t rdata;
    do {
    
    
        reg_read(offset, &rdata);
    } while (rdata != exp_data);
}

void mem_write32(uint64_t offset, uint32_t wdata)
{
    
    
    bar_write(MEM_BAR, offset, wdata, 0x1);
}

void mem_read32(uint64_t offset, uint32_t *rdata)
{
    
    
    uint64_t rdata64;
    bar_read(MEM_BAR, offset, &rdata64, 0x1);
    *rdata = 0xFFFFFFFF & rdata64;
}

void mem_write64(uint64_t offset, uint64_t wdata)
{
    
    
    bar_write(MEM_BAR, offset, wdata, 0x2);
}

void mem_read64(uint64_t offset, uint64_t *rdata)
{
    
    
    bar_read(MEM_BAR, offset, rdata, 0x2);
}

void csb_write(uint64_t offset, uint32_t wdata)
{
    
    
    bar_write(CSB_BAR, offset, wdata, 0x1);
}

void csb_read(uint64_t offset, uint32_t *rdata)
{
    
    
    uint64_t rdata64;
    bar_read(CSB_BAR, offset, &rdata64, 0x1);
    *rdata = 0xFFFFFFFF & rdata64;
}

void cfg_write(uint32_t offset, uint32_t data)
{
    
    
    pci_cfg_write(offset, data);
}

void cfg_read(uint32_t offset, uint32_t *data)
{
    
    
    pci_cfg_read(offset, data);
}

int kmem_new(uint32_t size, uint64_t *paddr, void **vaddr)
{
    
    
    int ret;
    ret = kmem_reserve(size);
    if (ret < 0) {
    
    
        printf("ERROR while trying to reserve kernel space\n");
        return ret;
    }
    *paddr = kmem_get_paddr(ret);
    *vaddr = kmem_mmap(ret, size);
    return ret;
}

int kmem_delete(uint32_t id)
{
    
    
    //return kmem_release(id);
}

int wait_irq(uint32_t vec)
{
    
    
   // return wait_msi_vector(vec);
}

pci_utils

#ifndef DPI_TASKS_H_
#define DPI_TASKS_H_

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
    
    
#endif

// Initialize PCIe device
int pci_init(char *device);

// Cleanup PCIe device
int pci_cleanup();

// Access PCIe bars 
void bar_write(uint32_t idx, uint64_t offset, uint64_t data, uint32_t ndw);
void bar_read(uint32_t idx, uint64_t offset, uint64_t *data, uint32_t ndw);
uint64_t bar_offset(uint32_t idx);
// Access PCIe configuration space
void pci_cfg_write(uint32_t offset, uint32_t data);
void pci_cfg_read(uint32_t offset, uint32_t *data);

// Kernal memory initialization
int kmem_init();

// Allocate/De-allocate kernel memory
int kmem_reserve(uint32_t size);
int kmem_release(uint32_t id);

// Get physical address of kernel memory
uint64_t kmem_get_paddr(uint32_t id);

// Get virtual address of kernel memory
void* kmem_mmap(uint32_t id, uint32_t size);

// MSI interrupt
int msi_init(void);
void msi_cleanup(void);
int wait_msi_vector(uint32_t vec);

#ifdef __cplusplus
}
#endif

#endif

#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>
#include <byteswap.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/eventfd.h>
#include <sys/epoll.h>
#include <readline/readline.h>
#include <readline/history.h>
#include "uio_pci_msi.h"
#include "pci_utils.h"
#include "pts_config.h"


//---------------------------------------------------------
// Type define and global variables
//---------------------------------------------------------

// Support maximum 32 interrupt vectors
#define MAX_IRQ_VEC 1
#ifdef SCORPIO 
#define ECF_BUS_OFFSET 0x2000000
#else 
#define ECF_BUS_OFFSET 0x00000
#endif 
// PCIe device type define
typedef struct {
    
    
	/* Base address region */
	unsigned int bar;

	/* Slot info */
	unsigned int domain;
	unsigned int bus;
	unsigned int slot;
	unsigned int function;

	/* Resource filename */
	char         filename[100];

	/* File descriptor of the resource */
	int          fd;

	/* Memory mapped resource */
	unsigned char *maddr;
	unsigned long int   size;
	unsigned int   offset;

	/* PCI physical address */
	unsigned int   phys;

	/* Address to pass to read/write (includes offset) */
	unsigned char *addr;
} device_t;

// Variables for ecf and edf device
device_t edf_device;
device_t ecf_device;
device_t csb_device;

// Variables for kernel memory access
int kmem_fd;

// Variables for MSI interrupt
struct uio_msi_irq_set msi_set[MAX_IRQ_VEC];


//---------------------------------------------------------
// Functions
//---------------------------------------------------------

// PCIe device initialization
int pci_init(char *device)
{
    
    
	int status;
	struct stat statbuf;
	/* Clear the structure fields */
	memset(&edf_device, 0, sizeof(device_t));
	memset(&ecf_device, 0, sizeof(device_t));
	memset(&csb_device, 0, sizeof(device_t));
	
       FILE * fp;
       char buffer[80];
       char command[50];
       char type[50];
       strcpy( command, "lspci -d 1e36:" );
       //strcpy( command, "lspci -d 1ea0:" );
       strcpy( type, "r" );
       fp=popen(command,type);
       fgets(buffer,sizeof(buffer),fp);
       printf("lspci -d 1e36: = %s",buffer);

       pclose(fp);

       //system(command);
    status = sscanf(buffer, "%2x:%2x.%1x",
    //status = sscanf(device, "%2x:%2x.%1x",
			&(edf_device.bus), &(edf_device.slot), &(edf_device.function));
	if (status != 3) {
    
    
		printf("Error parsing slot information!\n");
		return -1;
	}
        
    ecf_device.bus =  edf_device.bus;
    ecf_device.slot =  edf_device.slot;
    ecf_device.function =  edf_device.function;
    csb_device.bus =  edf_device.bus;
    csb_device.slot =  edf_device.slot;
    csb_device.function =  edf_device.function;
    ecf_device.bar = 1;
    edf_device.bar = 2;
    csb_device.bar = 4;
	
    /* Convert to a sysfs resource filename and open the resource */
	snprintf(ecf_device.filename, 99, "/sys/bus/pci/devices/%04x:%02x:%02x.%1x/resource%d",
			ecf_device.domain, ecf_device.bus, ecf_device.slot, ecf_device.function, ecf_device.bar);
	ecf_device.fd = open(ecf_device.filename, O_RDWR | O_SYNC);
	if (ecf_device.fd < 0) {
    
    
		printf("Open failed for file '%s': errno %d, %s\n",
			ecf_device.filename, errno, strerror(errno));
		return -1;
	}
	/* Convert to a sysfs resource filename and open the resource */
	snprintf(edf_device.filename, 99, "/sys/bus/pci/devices/%04x:%02x:%02x.%1x/resource%d",
			edf_device.domain, edf_device.bus, edf_device.slot, edf_device.function, edf_device.bar);
	edf_device.fd = open(edf_device.filename, O_RDWR | O_SYNC);
	if (edf_device.fd < 0) {
    
    
		printf("Open failed for file '%s': errno %d, %s\n",
			edf_device.filename, errno, strerror(errno));
		return -1;
	}
    /* Convert to a sysfs resource filename and open the resource */
	snprintf(csb_device.filename, 99, "/sys/bus/pci/devices/%04x:%02x:%02x.%1x/resource%d",
			csb_device.domain, csb_device.bus, csb_device.slot, csb_device.function, csb_device.bar);
	csb_device.fd = open(csb_device.filename, O_RDWR | O_SYNC);
	if (csb_device.fd < 0) {
    
    
		printf("Open failed for file '%s': errno %d, %s\n",
			csb_device.filename, errno, strerror(errno));
		return -1;
	}

	/* PCI memory size */
	status = fstat(ecf_device.fd, &statbuf);
	if (status < 0) {
    
    
		printf("fstat() failed: errno %d, %s\n",
			errno, strerror(errno));
		return -1;
	}
	ecf_device.size = statbuf.st_size;
	//printf("ecf_device.size = 0x%lx\n", ecf_device.size);

	status = fstat(edf_device.fd, &statbuf);
	if (status < 0) {
    
    
		printf("fstat() failed: errno %d, %s\n",
			errno, strerror(errno));
		return -1;
	}
	edf_device.size = statbuf.st_size;
	//printf("edf_device.size = 0x%lx\n", edf_device.size);

	status = fstat(csb_device.fd, &statbuf);
	if (status < 0) {
    
    
		printf("fstat() failed: errno %d, %s\n",
			errno, strerror(errno));
		return -1;
	}
	csb_device.size = statbuf.st_size;
	//printf("csb_device.size = 0x%lx\n", csb_device.size);

	/* Map */
	ecf_device.maddr = (unsigned char *)mmap(
		NULL,
		(size_t)(ecf_device.size),
		PROT_READ|PROT_WRITE,
		MAP_SHARED,
		ecf_device.fd,
		0);
	if (ecf_device.maddr == (unsigned char *)MAP_FAILED) {
    
    
		printf("BARs that are I/O ports are not supported by this tool\n");
		ecf_device.maddr = 0;
		close(ecf_device.fd);
		return -1;
	}
	edf_device.maddr = (unsigned char *)mmap(
		NULL,
		(size_t)(edf_device.size),
		PROT_READ|PROT_WRITE,
		MAP_SHARED,
		edf_device.fd,
		0);
	if (edf_device.maddr == (unsigned char *)MAP_FAILED) {
    
    
		printf("BARs that are I/O ports are not supported by this tool\n");
		edf_device.maddr = 0;
		close(edf_device.fd);
		return -1;
	}
	csb_device.maddr = (unsigned char *)mmap(
		NULL,
		(size_t)(csb_device.size),
		PROT_READ|PROT_WRITE,
		MAP_SHARED,
		csb_device.fd,
		0);
	if (csb_device.maddr == (unsigned char *)MAP_FAILED) {
    
    
		printf("BARs that are I/O ports are not supported by this tool\n");
		csb_device.maddr = 0;
		close(csb_device.fd);
		return -1;
	}

	/* Device regions smaller than a 4k page in size can be offset
	 * relative to the mapped base address. The offset is
	 * the physical address modulo 4k
	 */
	{
    
    
		char configname[100];
		int fd;

		snprintf(configname, 99, "/sys/bus/pci/devices/%04x:%02x:%02x.%1x/config",
				ecf_device.domain, ecf_device.bus, ecf_device.slot, ecf_device.function);
		fd = open(configname, O_RDWR | O_SYNC);
		if (fd < 0) {
    
    
			printf("Open failed for file '%s': errno %d, %s\n",
				configname, errno, strerror(errno));
			return -1;
		}

		status = lseek(fd, 0x10 + 4*ecf_device.bar, SEEK_SET);
		if (status < 0) {
    
    
			printf("Error: configuration space lseek failed\n");
			close(fd);
			return -1;
		}
		status = read(fd, &ecf_device.phys, 4);
		if (status < 0) {
    
    
			printf("Error: configuration space read failed\n");
			close(fd);
			return -1;
		}
		ecf_device.offset = ((ecf_device.phys & 0xFFFFFFF0) % 0x1000);
		ecf_device.addr = ecf_device.maddr + ecf_device.offset;
		close(fd);
	}
	{
    
    
		char configname[100];
		int fd;

		snprintf(configname, 99, "/sys/bus/pci/devices/%04x:%02x:%02x.%1x/config",
				edf_device.domain, edf_device.bus, edf_device.slot, edf_device.function);
		fd = open(configname, O_RDWR | O_SYNC);
		if (fd < 0) {
    
    
			printf("Open failed for file '%s': errno %d, %s\n",
				configname, errno, strerror(errno));
			return -1;
		}

		status = lseek(fd, 0x10 + 4*edf_device.bar, SEEK_SET);
		if (status < 0) {
    
    
			printf("Error: configuration space lseek failed\n");
			close(fd);
			return -1;
		}
		status = read(fd, &edf_device.phys, 4);
		if (status < 0) {
    
    
			printf("Error: configuration space read failed\n");
			close(fd);
			return -1;
		}
		edf_device.offset = ((edf_device.phys & 0xFFFFFFF0) % 0x1000);
		edf_device.addr = edf_device.maddr + edf_device.offset;
		close(fd);
	}
	{
    
    
		char configname[100];
		int fd;

		snprintf(configname, 99, "/sys/bus/pci/devices/%04x:%02x:%02x.%1x/config",
				csb_device.domain, csb_device.bus, csb_device.slot, csb_device.function);
		fd = open(configname, O_RDWR | O_SYNC);
		if (fd < 0) {
    
    
			printf("Open failed for file '%s': errno %d, %s\n",
				configname, errno, strerror(errno));
			return -1;
		}

		status = lseek(fd, 0x10 + 4*csb_device.bar, SEEK_SET);
		if (status < 0) {
    
    
			printf("Error: configuration space lseek failed\n");
			close(fd);
			return -1;
		}
		status = read(fd, &csb_device.phys, 4);
		if (status < 0) {
    
    
			printf("Error: configuration space read failed\n");
			close(fd);
			return -1;
		}
		csb_device.offset = ((csb_device.phys & 0xFFFFFFF0) % 0x1000);
		csb_device.addr = csb_device.maddr + csb_device.offset;
		close(fd);

	}

    // Initialize kernel memory
 //   status = kmem_init();
//	if (status < 0) {
    
    
 //       printf("Warning: initialize kmem failed\n");
//		return -1;
//	}

    // Initialize MSI interrupt
  //  status = msi_init();
//	if (status < 0) {
    
    
  //      printf("Warning: initialize msi failed\n");
//		return -1;
//	}

    return 0;
}

// Cleanup PCIe devices
int pci_cleanup()
{
    
    
    msi_cleanup();
}
uint64_t bar_offset(uint32_t idx)
{
    
    
    
    if (idx == 1) {
    
    
	return ecf_device.addr;	
    } else if (idx == 2) {
    
    
        return edf_device.addr;
    } else if (idx == 4) {
    
    
        return csb_device.addr;
    }

}
// Write PCIe bar space
void bar_write(uint32_t idx, uint64_t offset, uint64_t data, uint32_t ndw)
{
    
    
    if (idx == 1) {
    
    
        assert(ndw == 1);
        assert(offset%4 == 0);
	    *(volatile uint32_t *)(ecf_device.addr + offset - ECF_BUS_OFFSET) = data;
	    msync((void *)(ecf_device.addr + offset - ECF_BUS_OFFSET), 4, MS_SYNC | MS_INVALIDATE);
    } else if (idx == 2) {
    
    
        if (ndw == 2) {
    
    
            assert(offset%8 == 0);
	        *(volatile uint64_t *)(edf_device.addr + offset) = data;
	        msync((void *)(edf_device.addr + offset), 8, MS_SYNC | MS_INVALIDATE);
        } else if (ndw == 1) {
    
    
            assert(offset%4 == 0);
	        *(volatile uint32_t *)(edf_device.addr + offset) = data;
	        msync((void *)(edf_device.addr + offset), 4, MS_SYNC | MS_INVALIDATE);
        } else {
    
    
            assert(0);
        }
    } else if (idx == 4) {
    
    
        assert(ndw == 1);
        assert(offset%4 == 0);
	    *(volatile uint32_t *)(csb_device.addr + offset) = data;
	    msync((void *)(csb_device.addr + offset), 4, MS_SYNC | MS_INVALIDATE);
    } else {
    
    
        assert(0);
    }
}

// Read PCIe bar space
void bar_read(uint32_t idx, uint64_t offset, uint64_t *data, uint32_t ndw)
{
    
    
    if (idx == 1) {
    
    
        assert(ndw == 1);
        assert(offset%4 == 0);
	    uint32_t rdata = *(volatile uint32_t *)(ecf_device.addr + offset - ECF_BUS_OFFSET);
        *data = rdata;
    } else if (idx == 2) {
    
    
        if (ndw == 2) {
    
    
            assert(offset%8 == 0);
	        uint64_t rdata = *(volatile uint64_t *)(edf_device.addr + offset);
            *data = rdata;
        } else if (ndw == 1) {
    
    
            assert(offset%4 == 0);
	        uint32_t rdata = *(volatile uint32_t *)(edf_device.addr + offset);
            *data = rdata;
        } else {
    
    
            assert(0);
        }
    } else if (idx == 4) {
    
    
        assert(ndw == 1);
        assert(offset%4 == 0);
	    uint32_t rdata = *(volatile uint32_t *)(csb_device.addr + offset);
        *data = rdata;
    } else {
    
    
        assert(0);
    }
}

// Write PCIe config space
void pci_cfg_write(uint32_t offset, uint32_t data)
{
    
    
    printf("ERROR! pci_cfg_write not implemented!\n");
    assert(0);
}

// Read PCIe config space
void pci_cfg_read(uint32_t offset, uint32_t *data)
{
    
    
    printf("ERROR! pci_cfg_read not implemented!\n");
    assert(0);
}

// Kernel memory initialization
int kmem_init()
{
    
    
	kmem_fd = open("/dev/uio0", O_RDWR);
    if (kmem_fd == -1) {
    
    
        //printf("ERROR! cannot open device /dev/uio0\n");
        return -1;
    }
}

// Allocate kernel memory 
int kmem_reserve(uint32_t size)
{
    
    
	return ioctl(kmem_fd, UIO_MSI_DMEM_RESERVE, size);
}

// De-allocate kernel memory 
int kmem_release(uint32_t id)
{
    
    
	return ioctl(kmem_fd, UIO_MSI_DMEM_RELEASE, id);
}

// Get physical address of kernel memory
uint64_t kmem_get_paddr(uint32_t id)
{
    
    
	return ioctl(kmem_fd, UIO_MSI_DMEM_GET_PHYSICAL, id);
}

// Get virtual address of kernel memory
void* kmem_mmap(uint32_t id, uint32_t size)
{
    
    
	if (ioctl(kmem_fd, UIO_MSI_DMEM_ACTIVATE_BUFFER, id) < 0) {
    
    
        printf("ERROR while trying to activate kmem buffer %d\n", id);
        return NULL;
    }
	return mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, kmem_fd, 0);
}

// Initialize MSI interrupt
int msi_init(void)
{
    
    
    int i;
    for (i=0; i<MAX_IRQ_VEC; i++) {
    
    
        msi_set[i].vec = i;
        msi_set[i].fd = eventfd(0, 0);
        if (msi_set[i].fd < 0) {
    
    
            printf("ERROR trying to create fd for MSI vector %d\n", i);
            return -1;
        }
	if (ioctl(kmem_fd, UIO_MSI_IRQ_SET, &msi_set[i]) < 0) {
    
    
            printf("ERROR while trying to enable msi vector %d\n", i);
        }
    }

    return 0;
}

// MSI interrupt cleanup
void msi_cleanup(void)
{
    
    
    int i;
    for (i=0; i<MAX_IRQ_VEC; i++) {
    
    
        if (msi_set[i].fd >= 0) {
    
    
            close(msi_set[i].fd);
        }
    }
}

// Wait MSI interrupt vector
int wait_msi_vector(uint32_t vec)
{
    
    
    if (vec >= MAX_IRQ_VEC) {
    
    
        printf("ERROR! wait_msi_vector vec=%d, MAX_IRQ_VEC=%d", vec, MAX_IRQ_VEC);
        return -1;
    }

    uint32_t i;
    uint64_t cnt;
    if (read(msi_set[vec].fd, &cnt, sizeof(cnt)) < 0) {
    
    
        printf("NO MSI GET\n");
        return -1;
    }
    return cnt;
}

Guess you like

Origin blog.csdn.net/weixin_43360707/article/details/128331906