mesaflash/serial_boards.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

305 lines
11 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 <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <termios.h>
#include <string.h>
#include <errno.h>
#include <math.h>
#include <poll.h>
#include <sys/poll.h>
#include <unistd.h>
#include "types.h"
#include "anyio.h"
#include "serial_boards.h"
#include "lbp16.h"
#include "eeprom.h"
#include "eeprom_remote.h"
extern board_t boards[MAX_BOARDS];
extern int boards_count;
int sd;
// serial access functions
int serial_send_packet(void *packet, int size) {
int rc, ret;
int r = 0, timeouts = 0;
struct timespec timeout = {0, 50*1000*1000};
struct pollfd fds[1];
fds[0].fd = sd;
fds[0].events = POLLOUT;
while (r < size) {
rc = ppoll(fds, 1, &timeout, NULL);
if (rc > 0) {
ret = write(sd, packet, size);
r += ret;
} else if (rc == 0) {
timeouts ++;
if (timeouts == 5) {
printf("serial write timeout!\n");
return -1;
}
} else if (rc < 0) {
break;
}
}
return r;
}
int serial_recv_packet(void *packet, int size) {
int rc, ret;
int r = 0, timeouts = 0;
struct timespec timeout = {0, 300*1000*1000};
struct pollfd fds[1];
fds[0].fd = sd;
fds[0].events = POLLIN;
char buffer[1024];
while (r < size) {
rc = ppoll(fds, 1, &timeout, NULL);
if (rc > 0) {
ret = read(sd, buffer + r, rc);
r += rc;
} else if (rc == 0) {
timeouts ++;
if (timeouts == 5) {
printf("serial read timeout!\n");
return -1;
}
} else if (rc < 0) {
break;
}
}
memcpy(packet, buffer, r);
return r;
}
static int serial_read(llio_t *self, u32 addr, void *buffer, int size) {
return lbp16_read(CMD_READ_HOSTMOT2_ADDR32_INCR(size/4), addr, buffer, size);
}
static int serial_write(llio_t *self, u32 addr, void *buffer, int size) {
return lbp16_write(CMD_WRITE_HOSTMOT2_ADDR32_INCR(size/4), addr, buffer, size);
}
static int serial_board_open(board_t *board) {
eeprom_init(&(board->llio));
lbp16_read(CMD_READ_FLASH_IDROM, FLASH_ID_REG, &(board->flash_id), sizeof(u32));
if (board->fallback_support == 1) {
eeprom_prepare_boot_block(board->flash_id);
board->flash_start_address = eeprom_calc_user_space(board->flash_id);
} else {
board->flash_start_address = 0;
}
return 0;
}
static int serial_board_close(board_t *board) {
return 0;
}
// public functions
int serial_boards_init(board_access_t *access) {
#ifdef __linux__
struct termios options;
sd = open(access->dev_addr, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (sd == -1) {
perror("Unable to open the serial port\n");
}
tcgetattr(sd, &options); /* Get the current options for the port */
cfsetispeed(&options, B115200); /* Set the baud rates to 9600 */
cfsetospeed(&options, B115200);
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
options.c_cflag &= ~(PARENB | PARODD); // shut off parity
options.c_lflag = 0;
options.c_cflag &= ~CRTSCTS; /* Disable hardware flow control */
options.c_iflag &= ~IGNBRK;
options.c_oflag = 0;
tcsetattr(sd, TCSANOW, &options);
#elif _WIN32
char dev_name[32];
snprintf(dev_name, 32, "\\\\.\\%s", access->dev_addr);
sd = CreateFile(dev_name, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if (sd == INVALID_HANDLE_VALUE) {
printf("Unable to open the serial port %d\n", errno);
}
#endif
lbp16_init(BOARD_SER);
return 0;
}
void serial_boards_cleanup(board_access_t *access) {
close(sd);
}
void serial_boards_scan(board_access_t *access) {
lbp16_cmd_addr packet;
int send = 0, recv = 0;
char buff[16];
LBP16_INIT_PACKET4(packet, CMD_READ_BOARD_INFO_ADDR16_INCR(8), 0);
send = lbp16_send_packet(&packet, sizeof(packet));
recv = lbp16_recv_packet(buff, 16);
if (strncmp(buff, "7I90HD", 6) == 0) {
board_t *board = &boards[boards_count];
board_init_struct(board);
board->type = BOARD_SER;
strncpy(board->dev_addr, access->dev_addr, 16);
strncpy(board->llio.board_name, buff, 16);
board->llio.num_ioport_connectors = 3;
board->llio.pins_per_connector = 24;
board->llio.ioport_connector_name[0] = "P1";
board->llio.ioport_connector_name[1] = "P2";
board->llio.ioport_connector_name[2] = "P3";
board->llio.fpga_part_number = "6slx9tqg144";
board->llio.num_leds = 2;
board->llio.read = &serial_read;
board->llio.write = &serial_write;
board->llio.write_flash = &remote_write_flash;
board->llio.verify_flash = &remote_verify_flash;
board->llio.reset = &lbp16_board_reset;
board->llio.reload = &lbp16_board_reload;
board->open = &serial_board_open;
board->close = &serial_board_close;
board->print_info = &serial_print_info;
board->flash = BOARD_FLASH_REMOTE;
board->fallback_support = 1;
board->llio.verbose = access->verbose;
boards_count++;
}
}
void serial_print_info(board_t *board) {
lbp16_cmd_addr packet;
int i, j, recv;
char *mem_types[16] = {NULL, "registers", "memory", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "EEPROM", "flash"};
char *mem_writeable[2] = {"RO", "RW"};
char *acc_types[4] = {"8-bit", "16-bit", "32-bit", "64-bit"};
lbp_mem_info_area mem_area;
lbp_timers_area timers_area;
lbp_status_area stat_area;
lbp_info_area info_area;
lbp16_cmd_addr cmds[LBP16_MEM_SPACE_COUNT];
printf("\nSerial device %s at %s\n", board->llio.board_name, board->dev_addr);
if (board->llio.verbose == 0)
return;
LBP16_INIT_PACKET4(cmds[0], CMD_READ_AREA_INFO_ADDR16_INCR(LBP16_SPACE_HM2, sizeof(mem_area)/2), 0);
LBP16_INIT_PACKET4(cmds[1], 0, 0);
LBP16_INIT_PACKET4(cmds[2], 0, 0);
LBP16_INIT_PACKET4(cmds[3], CMD_READ_AREA_INFO_ADDR16_INCR(LBP16_SPACE_FPGA_FLASH, sizeof(mem_area)/2), 0);
LBP16_INIT_PACKET4(cmds[4], 0, 0);
LBP16_INIT_PACKET4(cmds[5], 0, 0);
LBP16_INIT_PACKET4(cmds[6], CMD_READ_AREA_INFO_ADDR16_INCR(LBP16_SPACE_COMM_CTRL, sizeof(mem_area)/2), 0);
LBP16_INIT_PACKET4(cmds[7], CMD_READ_AREA_INFO_ADDR16_INCR(LBP16_SPACE_BOARD_INFO, sizeof(mem_area)/2), 0);
LBP16_INIT_PACKET4(packet, CMD_READ_COMM_CTRL_ADDR16_INCR(sizeof(stat_area)/2), 0);
memset(&stat_area, 0, sizeof(stat_area));
lbp16_send_packet(&packet, sizeof(packet));
recv = lbp16_recv_packet(&stat_area, sizeof(stat_area));
LBP16_INIT_PACKET4(packet, CMD_READ_BOARD_INFO_ADDR16_INCR(sizeof(info_area)/2), 0);
memset(&info_area, 0, sizeof(info_area));
lbp16_send_packet(&packet, sizeof(packet));
recv = lbp16_recv_packet(&info_area, sizeof(info_area));
if (info_area.LBP16_version >= 3) {
LBP16_INIT_PACKET4(cmds[4], CMD_READ_AREA_INFO_ADDR16_INCR(LBP16_SPACE_TIMER, sizeof(mem_area)/2), 0);
LBP16_INIT_PACKET4(packet, CMD_READ_TIMER_ADDR16_INCR(sizeof(timers_area)/2), 0);
memset(&timers_area, 0, sizeof(timers_area));
lbp16_send_packet(&packet, sizeof(packet));
recv = lbp16_recv_packet(&timers_area, sizeof(timers_area));
}
printf("Communication:\n");
printf(" transport layer: serial\n");
printf(" protocol: LBP16 version %d\n", info_area.LBP16_version);
show_board_info(board);
printf("Board firmware info:\n");
printf(" memory spaces:\n");
for (i = 0; i < LBP16_MEM_SPACE_COUNT; i++) {
u32 size;
if ((cmds[i].cmd_lo == 0) && (cmds[i].cmd_hi == 0)) continue;
memset(&mem_area, 0, sizeof(mem_area));
lbp16_send_packet(&cmds[i], sizeof(cmds[i]));
lbp16_recv_packet(&mem_area, sizeof (mem_area));
printf(" %d: %.*s (%s, %s", i, (int)sizeof(mem_area.name), mem_area.name, mem_types[(mem_area.size >> 8) & 0x7F],
mem_writeable[(mem_area.size & 0x8000) >> 15]);
for (j = 0; j < 4; j++) {
if ((mem_area.size & 0xFF) & 1 << j)
printf(", %s)", acc_types[j]);
}
size = pow(2, mem_area.range & 0x3F);
show_formatted_size(size);
if (((mem_area.size >> 8) & 0x7F) >= 0xE)
printf(", page size: %u, erase size: %u",
(unsigned int) pow(2, (mem_area.range >> 6) & 0x1F), (unsigned int) pow(2, (mem_area.range >> 11) & 0x1F));
printf("\n");
}
printf(" [space 0] HostMot2\n");
printf(" [space 3] FPGA flash eeprom:\n");
printf(" flash size: %s (id: 0x%02X)\n", eeprom_get_flash_type(board->flash_id), board->flash_id);
if (info_area.LBP16_version >= 3) {
printf(" [space 4] timers:\n");
printf(" uSTimeStampReg: 0x%04X\n", timers_area.uSTimeStampReg);
printf(" WaituSReg: 0x%04X\n", timers_area.WaituSReg);
printf(" HM2Timeout: 0x%04X\n", timers_area.HM2Timeout);
}
printf(" [space 6] LBP16 control/status:\n");
printf(" packets received: all %d, good %d, bad %d\n", stat_area.RXPacketCount, stat_area.RXGoodCount, stat_area.RXBadCount);
printf(" packets sended: all %d, good %d, bad %d\n", stat_area.TXPacketCount, stat_area.TXGoodCount, stat_area.TXBadCount);
printf(" parse errors: %d, mem errors %d, write errors %d\n", stat_area.LBPParseErrors, stat_area.LBPMemErrors, stat_area.LBPWriteErrors);
printf(" error flags: 0x%04X\n", stat_area.ErrorReg);
printf(" debug LED ptr: 0x%04X\n", stat_area.DebugLEDPtr);
printf(" scratch: 0x%04X\n", stat_area.Scratch);
printf(" [space 7] LBP16 info:\n");
printf(" board name: %.*s\n", (int)sizeof(info_area.name), info_area.name);
printf(" LBP16 protocol version %d\n", info_area.LBP16_version);
printf(" board firmware version %d\n", info_area.firmware_version);
}