mesaflash/anyio.c

349 lines
9.9 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 <stdlib.h>
#include <string.h>
#include <errno.h>
#include "anyio.h"
#include "eeprom.h"
#include "bitfile.h"
#include "eth_boards.h"
#include "pci_boards.h"
#include "epp_boards.h"
#include "usb_boards.h"
#include "spi_boards.h"
#include "serial_boards.h"
supported_board_entry_t supported_boards[] = {
{"ETHER", BOARD_ETH | BOARD_WILDCARD},
{"7I92", BOARD_ETH},
{"7I93", BOARD_ETH},
{"7I96", BOARD_ETH},
{"7I80", BOARD_ETH},
{"7I76E", BOARD_ETH},
{"4I74", BOARD_PCI},
{"5I24", BOARD_PCI},
{"5I25", BOARD_PCI},
{"6I24", BOARD_PCI},
{"6I25", BOARD_PCI},
{"5I20", BOARD_PCI},
{"4I65", BOARD_PCI},
{"4I68", BOARD_PCI},
{"5I21", BOARD_PCI},
{"5I22", BOARD_PCI},
{"5I23", BOARD_PCI},
{"4I69", BOARD_PCI},
{"3X20", BOARD_PCI},
{"7I43", BOARD_MULTI_INTERFACE | BOARD_EPP | BOARD_USB},
{"7I90", BOARD_MULTI_INTERFACE | BOARD_EPP | BOARD_SPI | BOARD_SER},
{"7I64", BOARD_MULTI_INTERFACE | BOARD_USB | BOARD_SPI},
{NULL, 0},
};
board_t boards[MAX_BOARDS];
int boards_count;
int anyio_init(board_access_t *access) {
if (access == NULL) {
return -EINVAL;
}
return 0;
}
void anyio_cleanup(board_access_t *access) {
if (access == NULL) {
return;
}
if (access->open_iface & BOARD_ETH)
eth_boards_cleanup(access);
if (access->open_iface & BOARD_PCI)
pci_boards_cleanup(access);
if (access->open_iface & BOARD_EPP)
epp_boards_cleanup(access);
if (access->open_iface & BOARD_USB)
usb_boards_cleanup(access);
if (access->open_iface & BOARD_SPI)
spi_boards_cleanup(access);
if (access->open_iface & BOARD_SER)
serial_boards_cleanup(access);
access->open_iface = 0;
}
int anyio_find_dev(board_access_t *access) {
int i, ret = 0;
supported_board_entry_t *supported_board = NULL;
if (access == NULL) {
return -1;
}
for (i = 0; supported_boards[i].name != NULL; i++) {
if (strncmp(supported_boards[i].name, access->device_name, strlen(supported_boards[i].name)) == 0) {
supported_board = &supported_boards[i];
break;
}
}
if (supported_board == NULL) {
printf("ERROR: Unsupported device %s\n", access->device_name);
return -1;
}
access->open_iface = 0;
if (supported_board->type & BOARD_WILDCARD)
access->open_iface = BOARD_WILDCARD;
if (access->type == BOARD_ANY) {
if (supported_board->type & BOARD_MULTI_INTERFACE) {
printf("ERROR: you must select transport layer for board\n");
return -1;
}
if (supported_board->type & BOARD_ETH) {
ret = eth_boards_init(access);
access->open_iface |= BOARD_ETH;
eth_boards_scan(access);
}
if (supported_board->type & BOARD_PCI) {
ret = pci_boards_init(access);
if (ret < 0) {
return ret;
}
access->open_iface |= BOARD_PCI;
pci_boards_scan(access);
}
if (supported_board->type & BOARD_EPP) {
ret = epp_boards_init(access);
if (ret < 0) {
return ret;
}
access->open_iface |= BOARD_EPP;
epp_boards_scan(access);
}
if (supported_board->type & BOARD_USB) {
ret = usb_boards_init(access);
access->open_iface |= BOARD_USB;
usb_boards_scan(access);
}
if (supported_board->type & BOARD_SPI) {
ret = spi_boards_init(access);
access->open_iface |= BOARD_SPI;
spi_boards_scan(access);
}
if (supported_board->type & BOARD_SER) {
ret = serial_boards_init(access);
access->open_iface |= BOARD_SER;
serial_boards_scan(access);
}
} else {
if (access->type & BOARD_ETH) {
ret = eth_boards_init(access);
access->open_iface |= BOARD_ETH;
eth_boards_scan(access);
}
if (access->type & BOARD_PCI) {
ret = pci_boards_init(access);
if (ret < 0) {
return ret;
}
access->open_iface |= BOARD_PCI;
pci_boards_scan(access);
}
if (access->type & BOARD_EPP) {
ret = epp_boards_init(access);
if (ret < 0) {
return ret;
}
access->open_iface |= BOARD_EPP;
epp_boards_scan(access);
}
if (access->type & BOARD_USB) {
ret = usb_boards_init(access);
access->open_iface |= BOARD_USB;
usb_boards_scan(access);
}
if (access->type & BOARD_SPI) {
ret = spi_boards_init(access);
access->open_iface |= BOARD_SPI;
spi_boards_scan(access);
}
if (access->type & BOARD_SER) {
ret = serial_boards_init(access);
access->open_iface |= BOARD_SER;
serial_boards_scan(access);
}
}
return 0;
}
board_t *anyio_get_dev(board_access_t *access, int board_number) {
int i, j;
if (access == NULL) {
return NULL;
}
for (i = 0, j = 0; i < boards_count; i++) {
board_t *board = NULL;
board = &boards[i];
if (strncmp(access->device_name, board->llio.board_name, strlen(access->device_name)) == 0 || access->open_iface & BOARD_WILDCARD) {
j++;
if (j == board_number) {
return board;
}
}
}
return NULL;
}
int anyio_dev_write_flash(board_t *board, char *bitfile_name, int fallback_flag, int fix_boot_flag) {
int ret;
if (board == NULL) {
return -EINVAL;
}
if (board->llio.write_flash != NULL) {
u32 addr = board->flash_start_address;
if (fallback_flag == 1) {
addr = FALLBACK_ADDRESS;
}
ret = board->llio.write_flash(&(board->llio), bitfile_name, addr, fix_boot_flag);
} else {
printf("ERROR: Board %s doesn't support flash writing.\n", board->llio.board_name);
return -EINVAL;
}
return ret;
}
int anyio_dev_verify_flash(board_t *board, char *bitfile_name, int fallback_flag) {
int ret;
if (board == NULL) {
return -EINVAL;
}
if (board->llio.verify_flash != NULL) {
u32 addr = board->flash_start_address;
if (fallback_flag == 1) {
addr = FALLBACK_ADDRESS;
}
ret = board->llio.verify_flash(&(board->llio), bitfile_name, addr);
} else {
printf("ERROR: Board %s doesn't support flash verification.\n", board->llio.board_name);
return -EINVAL;
}
return ret;
}
int anyio_dev_program_fpga(board_t *board, char *bitfile_name) {
int ret;
if (board == NULL) {
return -EINVAL;
}
if (board->llio.reset == NULL) {
printf("ERROR: Board %s doesn't support FPGA resetting.\n", board->llio.board_name);
return -EINVAL;
}
if (board->llio.program_fpga == NULL) {
printf("ERROR: Board %s doesn't support FPGA programming.\n", board->llio.board_name);
return -EINVAL;
}
ret = board->llio.reset(&(board->llio));
if (ret != 0) {
return ret;
}
board->llio.program_fpga(&(board->llio), bitfile_name);
return 0;
}
int anyio_dev_set_remote_ip(board_t *board, char *lbp16_set_ip_addr) {
int ret;
if (board == NULL) {
return -EINVAL;
}
if ((board->type & BOARD_ETH) == 0) {
return -EPERM;
}
ret = eth_set_remote_ip(lbp16_set_ip_addr);
if (ret == 0) {
printf("Board IP updated successfully.\n");
printf("You must power cycle board to load updated eeprom settings.\n");
}
return ret;
}
int anyio_dev_reload(board_t *board, int fallback_flag) {
if (board == NULL) {
return -EINVAL;
}
if (board->llio.reload == NULL) {
printf("ERROR: Board %s doesn't support FPGA configuration reloading.\n", board->llio.board_name);
return -EINVAL;
}
return board->llio.reload(&(board->llio), fallback_flag);
}
int anyio_dev_reset(board_t *board) {
if (board == NULL) {
return -EINVAL;
}
if (board->llio.reset == NULL) {
printf("ERROR: Board %s doesn't support FPGA resetting.\n", board->llio.board_name);
return -EINVAL;
}
return board->llio.reset(&(board->llio));
}
void anyio_dev_print_hm2_info(board_t *board, int xml_flag) {
if (board == NULL) {
return;
}
hm2_read_idrom(&(board->llio.hm2));
hm2_print_pin_file(&(board->llio), xml_flag);
}
void anyio_dev_print_sserial_info(board_t *board) {
if (board == NULL) {
return;
}
hm2_read_idrom(&(board->llio.hm2));
sserial_module_init(&(board->llio));
}
void anyio_bitfile_print_info(char *bitfile_name, int verbose_flag) {
FILE *fp;
char part_name[32];
char board_name[5];
if (bitfile_name == NULL) {
return;
}
fp = fopen(bitfile_name, "rb");
if (fp == NULL) {
printf("Can't open file %s: %s\n", bitfile_name, strerror(errno));
return;
}
print_bitfile_header(fp, (char*) &part_name, (char*) &board_name, verbose_flag);
fclose(fp);
}