#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include "ecs_driverlib.h" static int flag_devnum = 0; static int flag_barnum = -1; static int flag_address = 0; static uint32_t flag_addroff; static int flag_write = 0; static uint32_t flag_writeval; static int flag_read = 0; //ug`pcie40_ecs.synopsis` // *pcie40_ecs* [-i _interface_] -b _bar_ -a _address_ -w _value_ _ // *pcie40_ecs* [-i _interface_] -b _bar_ -a _address_ -r static void usage() { fprintf(stderr, "usage: pcie40_ecs [options]\n"); fprintf(stderr, " -h Print this message\n"); fprintf(stderr, " -i {} Interface number (default: 0)\n"); fprintf(stderr, " -b {} BAR number\n"); fprintf(stderr, " -a {} Register address\n"); fprintf(stderr, " -w {} Write value to register\n"); fprintf(stderr, " -r Read register\n"); } //ug`pcie40_ecs.description` // Reads and writes PCIe40 BAR0 and BAR2 registers over PCI Express. int main(int argc, char *argv[]) { while (argc > 1 && argv[1][0] == '-') { switch (argv[1][1]) { //ug`pcie40_ecs.options`interface // *-i* _interface_:: // Bind to PCIe40 interface number _interface_. This is optional and by default the tool will bind to the first interface available (typically 0). case 'i': ++argv; --argc; flag_devnum = atoi(argv[1]); break; //ug`pcie40_ecs.options`bar // *-b* _bar_:: // Access BAR number _bar_. Two PCI BARs are available: // * 0 for user code (includes registers for DAQ, TFC, SCA...) // * 2 for the common low-level interface case 'b': ++argv; --argc; flag_barnum = atoi(argv[1]); break; //ug`pcie40_ecs.options`address // *-a* _address_:: // Address to use for BAR access. Can be in decimal, hexadecimal or any other format supported by *strtol(3)*. case 'a': ++argv; --argc; flag_address = 1; flag_addroff = strtol(argv[1], NULL, 0); break; //ug`pcie40_ecs.options`write // *-w* _value_:: // Write 32-bit _value_ to register at the given address. Same input format considerations apply as for the *-a* option. case 'w': ++argv; --argc; flag_write = 1; flag_writeval = strtoul(argv[1], NULL, 0); break; //ug`pcie40_ecs.options`read // *-r*:: // Read value of register at given address. Value is printed to stdout in hexadecimal format. case 'r': flag_read = 1; break; //ug`pcie40_ecs.options`help // *-h*:: // Output short program synopsis and exit. default: case 'h': usage(); exit(1); break; } --argc; ++argv; } //ug`pcie40_ecs.exit` // -1 is returned in case of access error or wrong command line options, 0 otherwise. if (!flag_address || flag_barnum < 0) { usage(); exit(-1); } if (!flag_read && !flag_write) { printf("-r and -w are mutually exclusive\n"); exit(-1); } uint32_t *regs; int ecs = p40_ecs_open(flag_devnum, flag_barnum, ®s); if (flag_write) { p40_ecs_w32(regs, flag_addroff, flag_writeval); } else if (flag_read) { uint32_t reg = p40_ecs_r32(regs, flag_addroff); printf("0x%08x\n", reg); } p40_ecs_close(ecs, regs, flag_barnum); return 0; }