mesaflash/mesaflash.c
Jeff Epler 934769e0cc Fix problems regarding function prototypes
In C, you can call functions which do not have prototypes
available; however, if the implied prototype doesn't match
the actual prototype, the behavior is undefined.  These changes
make mesaflash compile cleanly even when these prototype-checking
compiler flags are enabled (and enables them by default):
    -Werror=missing-prototypes
    -Werror=strict-prototypes
    -Werror=implicit-function-declaration
2016-11-21 21:09:24 -06:00

415 lines
15 KiB
C

//
// Copyright (C) 2013-2014 Michael Geszkiewicz
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
#include <string.h>
#include <stdio.h>
#include <getopt.h>
#include <ctype.h>
#include <stdlib.h>
#include <errno.h>
#include "anyio.h"
#ifdef __linux__
#include <pci/pci.h>
#elif _WIN32
#include "libpci/pci.h"
#endif
static int device_flag;
static int addr_flag;
static int addr_hi_flag;
static int write_flag;
static int fix_boot_flag;
static int verify_flag;
static int auto_verify_flag = 1;
static int fallback_flag;
static int recover_flag;
static int program_flag;
static int readhmid_flag;
static int reload_flag;
static int reset_flag;
static int sserial_flag;
static int epp_flag;
static int usb_flag;
static int spi_flag;
static int serial_flag;
static int rpo_flag;
static int wpo_flag;
static u16 rpo_addr;
static u16 wpo_addr;
static u32 wpo_data;
static int set_flag;
static int xml_flag;
static char *lbp16_set_ip_addr;
static int info_flag;
static int verbose_flag;
static char bitfile_name[255];
static board_access_t access;
static struct option long_options[] = {
{"device", required_argument, 0, 'd'},
{"addr", required_argument, 0, 'a'},
{"addr_hi", required_argument, 0, 'b'},
{"write", required_argument, 0, 'w'},
{"no-auto-verify", no_argument, &auto_verify_flag, 0},
{"fix-boot-block", no_argument, &fix_boot_flag, 1},
{"verify", required_argument, 0, 'v'},
{"fallback", no_argument, &fallback_flag, 1},
{"recover", no_argument, &recover_flag, 1},
{"program", required_argument, 0, 'p'},
{"readhmid", no_argument, &readhmid_flag, 1},
{"reload", no_argument, &reload_flag, 1},
{"reset", no_argument, &reset_flag, 1},
{"sserial", no_argument, &sserial_flag, 1},
{"epp", no_argument, &epp_flag, 1},
{"usb", no_argument, &usb_flag, 1},
{"spi", no_argument, &spi_flag, 1},
{"serial", no_argument, &serial_flag, 1},
{"rpo", required_argument, 0, 'r'},
{"wpo", required_argument, 0, 'o'},
{"set", required_argument, 0, 's'},
{"xml", no_argument, &xml_flag, 1},
{"info", required_argument, 0, 'i'},
{"help", no_argument, 0, 'h'},
{"verbose", no_argument, &verbose_flag, 1},
{0, 0, 0, 0}
};
static void print_short_usage(void) {
printf("\nMesaflash version 3.3.0~pre (built on %s %s with libpci %s)\n", __DATE__, __TIME__, PCILIB_VERSION);
printf("Configuration and diagnostic tool for Mesa Electronics PCI(E)/ETH/EPP/USB boards\n");
printf("(C) 2013-2015 Michael Geszkiewicz (contact: micges@wp.pl)\n");
printf("(C) Mesa Electronics\n");
printf("Try 'mesaflash --help' for more information\n");
}
static void print_usage(void) {
printf("Syntax:\n");
printf(" mesaflash --device device_name [options]\n");
printf(" mesaflash --device device_name [options] --write filename\n");
printf(" mesaflash --device device_name [options] --verify filename\n");
printf(" mesaflash --device device_name [options] --program filename\n");
printf(" mesaflash --device device_name [options] --readhmid\n");
printf(" mesaflash --device device_name [options] --reload | --reset\n");
printf(" mesaflash --device device_name [options] --sserial\n");
printf(" mesaflash --device device_name [options] --rpo address\n");
printf(" mesaflash --device device_name [options] --wpo address=value\n");
printf(" mesaflash --device device_name [options] --set ip=n.n.n.n\n");
printf(" mesaflash --info file_name\n");
printf(" mesaflash --help\n");
printf("\nOptions:\n");
printf(" --device select active device name. If no command is given it will detect board with given name and print info about it.\n");
printf(" --addr <device_address>\n");
printf(" select <device address> for looking for <device_name> (network C mask for ethernet boards, serial port for USB boards)\n");
printf(" --addr_hi set the high register address for the EPP interface\n");
printf(" --epp use EPP interface to connect to board, only for boards with multiple interfaces (7i43, 7i90, 7i64)\n");
printf(" --usb use USB interface to connect to board, only for boards with multiple interfaces (7i43, 7i90, 7i64)\n");
printf(" --spi use SPI interface to connect to board, only for boards with multiple interfaces (7i43, 7i90, 7i64)\n");
printf(" --serial use serial interface to connect to board, only for boards with multiple interfaces (7i43, 7i90, 7i64)\n");
printf(" --fallback use the fallback area of the EEPROM while executing commands\n");
printf(" --recover access board using PCI bridge GPIO (currently only 6I25)\n");
printf(" --xml format output from 'readhmid' command into XML\n");
printf(" --verbose print detailed information while running commands\n");
printf("\nCommands:\n");
printf(" --write writes a standard bitfile 'filename' configuration to the userarea of the EEPROM (IMPORTANT! 'filename' must be VALID FPGA configuration file)\n");
printf(" --fix-boot-block If a write operation does not detect a valid boot block, write one\n");
printf(" --no-auto-verify Don't automatically verify after writing\n");
printf(" --verify verifies the EEPROM configuration against the bitfile 'filename'\n");
printf(" --program writes a standard bitfile 'filename' configuration to the FPGA (IMPORTANT! 'filename' must be VALID FPGA configuration file)\n");
printf(" --readhmid print hostmot2 configuration in PIN file format\n");
printf(" --reload do full FPGA reload from flash (only ethernet and pci boards)\n");
printf(" --reset do full firmware reset (only ethernet boards)\n");
printf(" --sserial print full information about all sserial remote boards\n");
printf(" --rpo read hostmot2 variable directly at 'address'\n");
printf(" --wpo write hostmot2 variable directly at 'address' with 'value'\n");
printf(" --set set board IP address in eeprom to n.n.n.n (only ethernet boards)\n");
printf(" --info print info about configuration in 'file_name'\n");
printf(" --help print this help message\n");
}
static int process_cmd_line(int argc, char *argv[]) {
int c;
while (1) {
/* getopt_long stores the option index here. */
int option_index = 0;
c = getopt_long(argc, argv, "", long_options, &option_index);
/* Detect the end of the options. */
if (c == -1) break;
switch (c) {
case 0: {
/* If this option set a flag, do nothing else now. */
if (long_options[option_index].flag != 0) break;
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
}
break;
case 'd': {
int i;
if (device_flag > 0) {
printf("Error: multiple --device options\n");
exit(-1);
}
access.device_name = optarg;
for (i = 0; optarg[i] != '\0'; i++)
access.device_name[i] = toupper(access.device_name[i]);
device_flag++;
}
break;
case 'a': {
if (addr_flag > 0) {
printf("Error: multiple --addr options\n");
exit(-1);
}
access.dev_addr = optarg;
addr_flag++;
}
break;
case 'b': {
if (addr_hi_flag > 0) {
printf("Error: multiple --addr_hi options\n");
exit(-1);
}
access.dev_hi_addr = optarg;
addr_hi_flag++;
}
break;
case 'w': {
if (write_flag > 0) {
printf("Error: multiple --write options\n");
exit(-1);
}
strncpy(bitfile_name, optarg, 255);
write_flag++;
}
break;
case 'p': {
if (program_flag > 0) {
printf("Error: multiple --program options\n");
exit(-1);
}
strncpy(bitfile_name, optarg, 255);
program_flag++;
}
break;
case 'r': {
if (rpo_flag > 0) {
printf("Error: multiple --rpo options\n");
exit(-1);
}
if (strncmp(optarg, "0x", 2) == 0) {
optarg[0] = '0';
optarg[1] = '0';
rpo_addr = strtol(optarg, NULL, 16);
} else {
rpo_addr = strtol(optarg, NULL, 10);
}
rpo_flag++;
}
break;
case 'o': {
char *pch;
if (wpo_flag > 0) {
printf("Error: multiple --wpo options\n");
exit(-1);
}
pch = strtok(optarg, "=");
if (strncmp(pch, "0x", 2) == 0) {
pch[0] = '0';
pch[1] = '0';
wpo_addr = strtol(pch, NULL, 16);
} else {
wpo_addr = strtol(pch, NULL, 10);
}
pch = strtok(NULL, "=");
if (strncmp(pch, "0x", 2) == 0) {
pch[0] = '0';
pch[1] = '0';
wpo_data = strtol(pch, NULL, 16);
} else {
wpo_data = strtol(pch, NULL, 10);
}
wpo_flag++;
}
break;
case 's': {
if (set_flag > 0) {
printf("Error: multiple --set options\n");
exit(-1);
}
if (strncmp(optarg, "ip=", 3) == 0) {
char *pch;
pch = strtok(optarg, "=");
pch = strtok(NULL, "=");
lbp16_set_ip_addr = pch;
} else {
printf("Error: Unknown set command syntax, see --help for examples\n");
exit(-1);
}
set_flag++;
}
break;
case 'v': {
if (verify_flag > 0) {
printf("Error: multiple --verify options\n");
exit(-1);
}
strncpy(bitfile_name, optarg, 255);
verify_flag++;
}
break;
case 'i': {
if (info_flag > 0) {
printf("Error: multiple --info options\n");
exit(-1);
}
strncpy(bitfile_name, optarg, 255);
info_flag++;
}
break;
case 'h': {
print_usage();
exit(0);
}
break;
case '?':
/* getopt_long already printed an error message. */
return -1;
break;
default:
abort();
}
}
access.type = BOARD_ANY;
if ((epp_flag == 1) && (usb_flag == 0) && (spi_flag == 0) && (serial_flag == 0)) {
access.type = BOARD_EPP;
} else if ((epp_flag == 0) && (usb_flag == 1) && (spi_flag == 0) && (serial_flag == 0)) {
access.type = BOARD_USB;
} else if ((epp_flag == 0) && (usb_flag == 0) && (spi_flag == 1) && (serial_flag == 0)) {
access.type = BOARD_SPI;
} else if ((epp_flag == 0) && (usb_flag == 0) && (spi_flag == 0) && (serial_flag == 1)) {
access.type = BOARD_SER;
}
return 0;
}
int main(int argc, char *argv[]) {
int ret = 0;
if (argc == 1) {
print_short_usage();
return 0;
}
if (process_cmd_line(argc, argv) == -1)
return -1;
if (info_flag == 1) {
anyio_bitfile_print_info(bitfile_name, 1);
} else if (device_flag == 1) {
board_t *board = NULL;
access.verbose = verbose_flag;
access.recover = recover_flag;
access.address = addr_flag;
if (anyio_init(&access) != 0)
exit(1);
ret = anyio_find_dev(&access);
if (ret < 0) {
return -1;
}
board = anyio_get_dev(&access, 1);
if (board == NULL) {
printf("No %s board found\n", access.device_name);
return -1;
}
board->open(board);
if (readhmid_flag == 1) {
anyio_dev_print_hm2_info(board, xml_flag);
} else if (sserial_flag == 1) {
anyio_dev_print_sserial_info(board);
} else if (rpo_flag == 1) {
u32 data;
board->llio.read(&(board->llio), rpo_addr, &data, sizeof(u32));
printf("%08X\n", data);
} else if (wpo_flag == 1) {
board->llio.write(&(board->llio), wpo_addr, &wpo_data, sizeof(u32));
} else if (set_flag == 1) {
ret = anyio_dev_set_remote_ip(board, lbp16_set_ip_addr);
} else if (write_flag == 1) {
ret = anyio_dev_write_flash(board, bitfile_name, fallback_flag, fix_boot_flag);
if (ret == 0) {
if (auto_verify_flag) {
ret = anyio_dev_verify_flash(board, bitfile_name, fallback_flag);
}
}
if (ret == 0) {
if (reload_flag == 1) {
ret = anyio_dev_reload(board, fallback_flag);
if (ret == -1) {
printf("\nYou must power cycle the hardware to load a new firmware.\n");
}
} else if (board->llio.reload) {
printf("\nYou must power cycle the hardware or use the --reload command to load a new firmware.\n");
} else {
printf("\nYou must power cycle the hardware\n");
}
}
} else if (verify_flag == 1) {
ret = anyio_dev_verify_flash(board, bitfile_name, fallback_flag);
} else if (program_flag == 1) {
ret = anyio_dev_program_fpga(board, bitfile_name);
} else if (reload_flag == 1) {
anyio_dev_reload(board, fallback_flag);
} else if (reset_flag == 1) {
anyio_dev_reset(board);
} else {
board->print_info(board);
}
board->close(board);
anyio_cleanup(&access);
} else {
printf("No action requested. Please specify at least --device or --info.\n");
}
return ret;
}