#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <linux/types.h>
#include "upci.h"
#include "bitfile.h"
#undef DEBUG_PRINTS
#define array_size(x) (sizeof(x)/sizeof(x[0]))
struct board_info {
char *board_type;
char *chip_type;
unsigned short vendor_id;
unsigned short device_id;
unsigned short ss_vendor_id;
unsigned short ss_device_id;
int fpga_pci_region;
int upci_devnum;
};
struct board_info board_info_table[] =
{
{ "5i20", "2s200pq208", 0x10B5, 0x9030, 0x10B5, 0x3131, 5, 0},
{ "5i22-1M", "3s1000fg320", 0x10B5, 0x9054, 0x10B5, 0x3132, 3, 0},
{ "5i22-1.5M", "3s1500fg320", 0x10B5, 0x9054, 0x10B5, 0x3131, 3, 0}
};
static void errmsg(const char *funct, const char *fmt, ...);
static int parse_cmdline(unsigned argc, char *argv[]);
struct write_var {
__u32 *val;
__u32 minval, maxval;
char *shortname;
char *longname;
};
static __u32 cardnum, cardtype, pci_region, pci_offset, value;
static struct write_var params[] =
{
{&cardnum, 0, 15, "cardnum", "Card Number"},
{&cardtype, 0, array_size(board_info_table), "cardtype", "Card Type"},
{&pci_region, 0, 3, "region", "PCI Region"},
{&pci_offset, 0, 65532, "offset", "Region Offset"},
{&value, 0, 0, "value", "Write Value"}
};
#define EC_OK 0
#define EC_BADCL 100
#define EC_HDW 101
#define EC_FILE 102
#define EC_SYS 103
int main(int argc, char *argv[])
{
int data_region, retval;
#ifdef DEBUG_PRINTS
int dbg;
#endif
struct upci_dev_info info;
struct board_info board;
retval = seteuid(getuid());
if (retval != 0) {
fprintf(stderr, "failed to set euid to uid %d: %s\n", getuid(), strerror(errno));
return EC_SYS;
}
if ( parse_cmdline(argc, argv) != EC_OK ) {
return EC_BADCL;
}
#ifdef DEBUG_PRINTS
for (dbg=0;dbg<array_size(params);dbg++) {
printf("Parameter %s = %u\n", params[dbg].longname, *(params[dbg].val));
}
#endif
board = board_info_table[cardtype];
#ifdef DEBUG_PRINTS
printf ( "Board type: %s\n", board.board_type );
#endif
retval = upci_scan_bus();
if ( retval < 0 ) {
errmsg(__func__,"PCI bus data missing" );
return EC_SYS;
}
info.vendor_id = board.vendor_id;
info.device_id = board.device_id;
info.ss_vendor_id = board.ss_vendor_id;
info.ss_device_id = board.ss_device_id;
info.instance = cardnum;
board.upci_devnum = upci_find_device(&info);
if ( board.upci_devnum < 0 ) {
errmsg(__func__, "%s board #%d not found",
board.board_type, info.instance );
return EC_HDW;
}
#ifdef DEBUG_PRINTS
upci_print_device_info(board.upci_devnum);
#else
data_region = upci_open_region(board.upci_devnum, pci_region);
upci_write_u32(data_region, pci_offset, value);
#endif
return EC_OK;
}
static void errmsg(const char *funct, const char *fmt, ...)
{
va_list vp;
va_start(vp, fmt);
fprintf(stderr, "ERROR in %s(): ", funct);
vfprintf(stderr, fmt, vp);
fprintf(stderr, "\n");
va_end(vp);
}
void usage(void) {
int i;
printf("\npci_write <card> <cardtype> <region> <offset> <value>\n\n");
printf("All parameters are required.\n");
printf(" <card> - card number (0-15)\n\n");
printf(" <cardtype> - card type. valid types are:\n");
for (i=0;i<array_size(board_info_table);i++) {
printf(" %d - %s\n", i, board_info_table[i].board_type);
}
printf("\n <region> - which PCI region to write into\n\n");
printf(" <offset> - offset into the region\n\n");
printf(" <value> - value to write\n\n");
}
static int parse_cmdline(unsigned argc, char *argv[])
{
int i;
__u32 temp;
char *eptr;
if (argc != array_size(params)+1) {
usage();
return EC_BADCL;
}
for (i=0;i<array_size(params);i++)
{
temp = strtoul(argv[i+1], &eptr, 0);
if (*eptr!='\0')
{
errmsg(__func__,"invalid %s: %s", params[i].longname, argv[i+1]);
return EC_BADCL;
}
if (params[i].minval != params[i].maxval) {
if ((temp < params[i].minval) || (temp > params[i].maxval)) {
errmsg(__func__,"Parameter %s out of range: %u",
params[i].longname, temp);
return EC_BADCL;
}
}
*(params[i].val)=temp;
}
return EC_OK;
}