FRONTPANEL: Cleanup for building as C++. Add initial support for device panels concurrently on a simulator. Added an API to set a register value.

This commit is contained in:
Mark Pizzolato 2015-02-12 14:59:24 -08:00
parent 9accae5905
commit 4c8e1631b5
4 changed files with 274 additions and 93 deletions

View file

@ -45,14 +45,14 @@
#else #else
#include <unistd.h> #include <unistd.h>
#endif #endif
char *sim_path = const char *sim_path =
#if defined(_WIN32) #if defined(_WIN32)
"vax.exe"; "vax.exe";
#else #else
"vax"; "vax";
#endif #endif
char *sim_config = const char *sim_config =
"VAX-PANEL.ini"; "VAX-PANEL.ini";
/* Registers visible on the Front Panel */ /* Registers visible on the Front Panel */
@ -62,7 +62,7 @@ static void
DisplayCallback (PANEL *panel, void *context) DisplayCallback (PANEL *panel, void *context)
{ {
char buf1[100], buf2[100], buf3[100]; char buf1[100], buf2[100], buf3[100];
static char *states[] = {"Halt", "Run "}; static const char *states[] = {"Halt", "Run "};
buf1[sizeof(buf1)-1] = buf2[sizeof(buf2)-1] = buf3[sizeof(buf3)-1] = 0; buf1[sizeof(buf1)-1] = buf2[sizeof(buf2)-1] = buf3[sizeof(buf3)-1] = 0;
sprintf (buf1, "%s PC: %08X SP: %08X AP: %08X FP: %08X\r\n", states[sim_panel_get_state (panel)], PC, SP, AP, FP); sprintf (buf1, "%s PC: %08X SP: %08X AP: %08X FP: %08X\r\n", states[sim_panel_get_state (panel)], PC, SP, AP, FP);
@ -122,7 +122,7 @@ return;
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
PANEL *panel; PANEL *panel, *tape;
FILE *f; FILE *f;
/* Create pseudo config file for a test */ /* Create pseudo config file for a test */
@ -138,13 +138,21 @@ if ((f = fopen (sim_config, "w"))) {
InitDisplay(); InitDisplay();
signal (SIGINT, halt_handler); signal (SIGINT, halt_handler);
panel = sim_panel_start_simulator (sim_path, panel = sim_panel_start_simulator (sim_path,
sim_config); sim_config,
2);
if (!panel) { if (!panel) {
printf ("Error starting simulator: %s\n", sim_panel_get_error()); printf ("Error starting simulator: %s\n", sim_panel_get_error());
goto Done; goto Done;
} }
tape = sim_panel_add_device_panel (panel, "TAPE DRIVE");
if (!tape) {
printf ("Error adding tape device to simulator: %s\n", sim_panel_get_error());
goto Done;
}
if (sim_panel_add_register (panel, "PC", sizeof(PC), &PC)) { if (sim_panel_add_register (panel, "PC", sizeof(PC), &PC)) {
printf ("Error adding register 'PC': %s\n", sim_panel_get_error()); printf ("Error adding register 'PC': %s\n", sim_panel_get_error());
goto Done; goto Done;
@ -263,7 +271,7 @@ while (1) {
} }
Done: Done:
sim_panel_stop_simulator (panel); sim_panel_destroy (panel);
/* Get rid of pseudo config file created above */ /* Get rid of pseudo config file created above */
remove (sim_config); remove (sim_config);

View file

@ -31,6 +31,10 @@
*/ */
#ifdef __cplusplus
extern "C" {
#endif
#include "sim_frontpanel.h" #include "sim_frontpanel.h"
#include <stdio.h> #include <stdio.h>
@ -54,10 +58,6 @@
#include <sys/wait.h> #include <sys/wait.h>
#endif #endif
#ifdef __cplusplus
extern "C" {
#endif
#include "sim_sock.h" #include "sim_sock.h"
typedef struct { typedef struct {
@ -66,20 +66,26 @@ typedef struct {
size_t size; size_t size;
} REG; } REG;
struct sim_frontpanel { struct PANEL {
char *path; PANEL *parent; /* Device Panels can have parent panels */
char *name; /* simulator path or device name */
char *config; char *config;
char *temp_config; char *temp_config;
char hostport[64]; char hostport[64];
size_t device_count;
PANEL **devices;
SOCKET sock; SOCKET sock;
int reg_count; int reg_count;
REG *regs; REG *regs;
char *reg_query;
size_t reg_query_size;
OperationalState State; OperationalState State;
pthread_mutex_t lock; pthread_mutex_t lock;
pthread_t io_thread; pthread_t io_thread;
int io_thread_running; int io_thread_running;
pthread_mutex_t io_lock; pthread_mutex_t io_lock;
pthread_mutex_t io_send_lock; pthread_mutex_t io_send_lock;
int io_waiting;
pthread_cond_t io_done; pthread_cond_t io_done;
pthread_cond_t startup_cond; pthread_cond_t startup_cond;
PANEL_DISPLAY_PCALLBACK callback; PANEL_DISPLAY_PCALLBACK callback;
@ -94,10 +100,13 @@ struct sim_frontpanel {
#endif #endif
}; };
static char *sim_prompt = "sim> "; static const char *sim_prompt = "sim> ";
static const char *register_get_echo = "# REGISTERS-DONE";
static const char *command_done_echo = "# COMMAND-DONE";
static int little_endian; static int little_endian;
static void *_panel_reader(void *arg); static void *_panel_reader(void *arg);
static void *_panel_callback(void *arg); static void *_panel_callback(void *arg);
static void sim_panel_set_error (const char *fmt, ...);
#define TN_IAC 0xFFu /* -1 */ /* protocol delim */ #define TN_IAC 0xFFu /* -1 */ /* protocol delim */
#define TN_DONT 0xFEu /* -2 */ /* dont */ #define TN_DONT 0xFEu /* -2 */ /* dont */
@ -155,21 +164,25 @@ return sent;
} }
static int static int
_panel_sendf (PANEL *p, const char *fmt, ...); _panel_sendf (PANEL *p, int wait_for_completion, const char *fmt, ...);
static int static int
_panel_register_query_string (PANEL *panel, char **buf, int *buf_size) _panel_register_query_string (PANEL *panel, char **buf, size_t *buf_size)
{ {
int i, buf_data, buf_needed = 0; int i;
size_t buf_data, buf_needed = 0;
pthread_mutex_lock (&panel->io_lock);
for (i=0; i<panel->reg_count; i++) for (i=0; i<panel->reg_count; i++)
buf_needed += 7 + strlen (panel->regs[i].name); buf_needed += 7 + strlen (panel->regs[i].name);
buf_needed += 20; /* # REGISTERS-DONE */ buf_needed += 10 + strlen (register_get_echo); /* # REGISTERS-DONE */
if (buf_needed > *buf_size) { if (buf_needed > *buf_size) {
free (*buf); free (*buf);
*buf = (char *)_panel_malloc (buf_needed); *buf = (char *)_panel_malloc (buf_needed);
if (!*buf) if (!*buf) {
pthread_mutex_unlock (&panel->io_lock);
return -1; return -1;
}
*buf_size = buf_needed; *buf_size = buf_needed;
} }
buf_data = 0; buf_data = 0;
@ -185,12 +198,15 @@ for (i=0; i<panel->reg_count; i++) {
sprintf (*buf + buf_data, "%s%s", (i>0) ? "," : "", panel->regs[i].name); sprintf (*buf + buf_data, "%s%s", (i>0) ? "," : "", panel->regs[i].name);
buf_data += strlen (*buf + buf_data); buf_data += strlen (*buf + buf_data);
} }
sprintf (*buf + buf_data, "\r"); strcpy (*buf + buf_data, "\r");
buf_data += strlen (*buf + buf_data); buf_data += strlen (*buf + buf_data);
#endif #endif
sprintf (*buf + buf_data, "# REGISTERS-DONE\r"); strcpy (*buf + buf_data, register_get_echo);
buf_data += strlen (*buf + buf_data);
strcpy (*buf + buf_data, "\r");
buf_data += strlen (*buf + buf_data); buf_data += strlen (*buf + buf_data);
*buf_size = buf_data; *buf_size = buf_data;
pthread_mutex_unlock (&panel->io_lock);
return 0; return 0;
} }
@ -201,14 +217,14 @@ static void
_panel_cleanup (void) _panel_cleanup (void)
{ {
while (panel_count) while (panel_count)
sim_panel_stop_simulator (*panels); sim_panel_destroy (*panels);
} }
static void static void
_panel_register_panel (PANEL *p) _panel_register_panel (PANEL *p)
{ {
++panel_count; ++panel_count;
panels = realloc (panels, sizeof(*panels)*panel_count); panels = (PANEL **)realloc (panels, sizeof(*panels)*panel_count);
panels[panel_count-1] = p; panels[panel_count-1] = p;
if (panel_count == 1) if (panel_count == 1)
atexit (&_panel_cleanup); atexit (&_panel_cleanup);
@ -237,7 +253,8 @@ for (i=0; i<panel_count; i++) {
PANEL * PANEL *
sim_panel_start_simulator (const char *sim_path, sim_panel_start_simulator (const char *sim_path,
const char *sim_config) const char *sim_config,
size_t device_panel_count)
{ {
PANEL *p = NULL; PANEL *p = NULL;
FILE *f = NULL; FILE *f = NULL;
@ -282,10 +299,10 @@ if (p == NULL)
goto Error_Return; goto Error_Return;
memset (p, 0, sizeof(*p)); memset (p, 0, sizeof(*p));
p->sock = INVALID_SOCKET; p->sock = INVALID_SOCKET;
p->path = (char *)_panel_malloc (strlen (sim_path) + 1); p->name = (char *)_panel_malloc (strlen (sim_path) + 1);
if (p->path == NULL) if (p->name == NULL)
goto Error_Return; goto Error_Return;
strcpy (p->path, sim_path); strcpy (p->name, sim_path);
p->config = (char *)_panel_malloc (strlen (sim_config) + 1); p->config = (char *)_panel_malloc (strlen (sim_config) + 1);
if (p->config == NULL) if (p->config == NULL)
goto Error_Return; goto Error_Return;
@ -312,11 +329,13 @@ if (f == NULL) {
} }
fprintf (f, "# Temporary FrontPanel generated simh configuration file\n"); fprintf (f, "# Temporary FrontPanel generated simh configuration file\n");
fprintf (f, "# Original Configuration File: %s\n", p->config); fprintf (f, "# Original Configuration File: %s\n", p->config);
fprintf (f, "# Simulator Path: %s\n", p->path); fprintf (f, "# Simulator Path: %s\n", sim_path);
fprintf (f, "%s\n", buf); fprintf (f, "%s\n", buf);
free (buf); free (buf);
buf = NULL; buf = NULL;
fprintf (f, "set remote -u telnet=%s\n", hostport); fprintf (f, "set remote -u telnet=%s\n", hostport);
if (device_panel_count)
fprintf (f, "set remote connections=%d\n", (int)device_panel_count+1);
fprintf (f, "set remote master\n"); fprintf (f, "set remote master\n");
fclose (f); fclose (f);
f = NULL; f = NULL;
@ -326,7 +345,7 @@ if (1) {
PROCESS_INFORMATION ProcessInfo; PROCESS_INFORMATION ProcessInfo;
STARTUPINFO StartupInfo; STARTUPINFO StartupInfo;
sprintf(cmd, "%s%s%s %s%s%s", strchr (p->path, ' ') ? "\"" : "", p->path, strchr (p->path, ' ') ? "\"" : "", strchr (p->temp_config, ' ') ? "\"" : "", p->temp_config, strchr (p->temp_config, ' ') ? "\"" : ""); sprintf(cmd, "%s%s%s %s%s%s", strchr (sim_path, ' ') ? "\"" : "", sim_path, strchr (sim_path, ' ') ? "\"" : "", strchr (p->temp_config, ' ') ? "\"" : "", p->temp_config, strchr (p->temp_config, ' ') ? "\"" : "");
memset (&ProcessInfo, 0, sizeof(ProcessInfo)); memset (&ProcessInfo, 0, sizeof(ProcessInfo));
memset (&StartupInfo, 0, sizeof(StartupInfo)); memset (&StartupInfo, 0, sizeof(StartupInfo));
@ -346,7 +365,7 @@ if (1) {
p->pidProcess = fork(); p->pidProcess = fork();
if (p->pidProcess == 0) { if (p->pidProcess == 0) {
close (0); close (1); close (2); /* make sure not to pass the open standard handles */ close (0); close (1); close (2); /* make sure not to pass the open standard handles */
if (execlp (p->path, p->path, p->temp_config, NULL, NULL)) { if (execlp (sim_path, sim_path, p->temp_config, NULL, NULL)) {
perror ("execl"); perror ("execl");
exit(errno); exit(errno);
} }
@ -369,6 +388,7 @@ if (p->sock == INVALID_SOCKET) {
sim_panel_set_error ("Can't connect to simulator Remote Console on port %s", hostport); sim_panel_set_error ("Can't connect to simulator Remote Console on port %s", hostport);
goto Error_Return; goto Error_Return;
} }
strcpy (p->hostport, hostport);
if (1) { if (1) {
pthread_attr_t attr; pthread_attr_t attr;
@ -390,6 +410,13 @@ if (sizeof(mantra) != _panel_send (p, (char *)mantra, sizeof(mantra))) {
sim_panel_set_error ("Error sending Telnet mantra (options): %s", sim_get_err_sock ("send")); sim_panel_set_error ("Error sending Telnet mantra (options): %s", sim_get_err_sock ("send"));
goto Error_Return; goto Error_Return;
} }
if (device_panel_count) {
p->devices = (PANEL **)_panel_malloc (device_panel_count*sizeof(*p->devices));
if (p->devices == NULL)
goto Error_Return;
memset (p->devices, 0, device_panel_count*sizeof(*p->devices));
p->device_count = device_panel_count;
}
_panel_register_panel (p); _panel_register_panel (p);
return p; return p;
@ -398,18 +425,94 @@ if (f)
fclose (f); fclose (f);
if (buf) if (buf)
free (buf); free (buf);
sim_panel_stop_simulator (p); sim_panel_destroy (p);
return NULL;
}
PANEL *
sim_panel_add_device_panel (PANEL *simulator_panel,
const char *device_name)
{
size_t i, device_num;
PANEL *p = NULL;
if (!simulator_panel) {
sim_panel_set_error ("Invalid Panel");
return NULL;
}
for (device_num=0; device_num < simulator_panel->device_count; ++device_num)
if (simulator_panel->devices[device_num] == NULL)
break;
if (device_num == simulator_panel->device_count) {
sim_panel_set_error ("No free panel devices slots available %s simulator. All %d slots are used.", simulator_panel->name, (int)simulator_panel->device_count);
return NULL;
}
p = (PANEL *)_panel_malloc (sizeof(*p));
if (p == NULL)
goto Error_Return;
memset (p, 0, sizeof(*p));
p->parent = simulator_panel;
p->sock = INVALID_SOCKET;
for (i=0; i<5; i++) {
p->sock = sim_connect_sock_ex (NULL, simulator_panel->hostport, NULL, NULL, SIM_SOCK_OPT_NODELAY | SIM_SOCK_OPT_BLOCKING);
if (p->sock == INVALID_SOCKET)
msleep (100);
else
break;
}
if (p->sock == INVALID_SOCKET) {
sim_panel_set_error ("Can't connect to simulator Remote Console on port %s", simulator_panel->hostport);
goto Error_Return;
}
strcpy (p->hostport, simulator_panel->hostport);
if (1) {
pthread_attr_t attr;
pthread_mutex_init (&p->io_lock, NULL);
pthread_mutex_init (&p->io_send_lock, NULL);
pthread_cond_init (&p->io_done, NULL);
pthread_cond_init (&p->startup_cond, NULL);
pthread_attr_init(&attr);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
pthread_mutex_lock (&p->io_lock);
pthread_create (&p->io_thread, &attr, _panel_reader, (void *)p);
pthread_attr_destroy(&attr);
while (!p->io_thread_running)
pthread_cond_wait (&p->startup_cond, &p->io_lock); /* Wait for thread to stabilize */
pthread_mutex_unlock (&p->io_lock);
pthread_cond_destroy (&p->startup_cond);
}
if (sizeof(mantra) != _panel_send (p, (char *)mantra, sizeof(mantra))) {
sim_panel_set_error ("Error sending Telnet mantra (options): %s", sim_get_err_sock ("send"));
goto Error_Return;
}
simulator_panel->devices[device_num] = p;
_panel_register_panel (p);
return p;
Error_Return:
sim_panel_destroy (p);
return NULL; return NULL;
} }
int int
sim_panel_stop_simulator (PANEL *panel) sim_panel_destroy (PANEL *panel)
{ {
REG *reg; REG *reg;
if (panel) { if (panel) {
if (panel->devices) {
size_t i;
for (i=0; i<panel->device_count; i++) {
if (panel->devices[i])
sim_panel_destroy (panel->devices[i]);
}
free (panel->devices);
panel->devices = NULL;
}
_panel_deregister_panel (panel); _panel_deregister_panel (panel);
free (panel->path); free (panel->name);
free (panel->config); free (panel->config);
if (panel->sock != INVALID_SOCKET) { if (panel->sock != INVALID_SOCKET) {
SOCKET sock = panel->sock; SOCKET sock = panel->sock;
@ -458,19 +561,18 @@ if (panel) {
reg++; reg++;
} }
free (panel->regs); free (panel->regs);
} free (panel->reg_query);
sim_cleanup_sock (); sim_cleanup_sock ();
free (panel); free (panel);
}
return 0; return 0;
} }
OperationalState OperationalState
sim_panel_get_state (PANEL *panel) sim_panel_get_state (PANEL *panel)
{ {
if (!panel) { if (!panel)
sim_panel_set_error ("Invalid Panel"); return Halt;
return -1;
}
return panel->State; return panel->State;
} }
@ -489,6 +591,7 @@ if (!panel) {
regs = (REG *)_panel_malloc ((1 + panel->reg_count)*sizeof(*regs)); regs = (REG *)_panel_malloc ((1 + panel->reg_count)*sizeof(*regs));
if (regs == NULL) if (regs == NULL)
return -1; return -1;
pthread_mutex_lock (&panel->io_lock);
memcpy (regs, panel->regs, panel->reg_count*sizeof(*regs)); memcpy (regs, panel->regs, panel->reg_count*sizeof(*regs));
reg = &regs[panel->reg_count]; reg = &regs[panel->reg_count];
memset (reg, 0, sizeof(*regs)); memset (reg, 0, sizeof(*regs));
@ -503,15 +606,16 @@ reg->size = size;
++panel->reg_count; ++panel->reg_count;
free (panel->regs); free (panel->regs);
panel->regs = regs; panel->regs = regs;
pthread_mutex_unlock (&panel->io_lock);
/* Now build the register query string for the whole register list */
if (_panel_register_query_string (panel, &panel->reg_query, &panel->reg_query_size))
return -1;
return 0; return 0;
} }
int int
sim_panel_get_registers (PANEL *panel) sim_panel_get_registers (PANEL *panel)
{ {
char *buf = NULL;
int buf_data;
if (!panel) { if (!panel) {
sim_panel_set_error ("Invalid Panel"); sim_panel_set_error ("Invalid Panel");
return -1; return -1;
@ -520,12 +624,17 @@ if (panel->callback) {
sim_panel_set_error ("Callback provides register data"); sim_panel_set_error ("Callback provides register data");
return -1; return -1;
} }
buf_data = 0; if (!panel->reg_count) {
if (_panel_register_query_string (panel, &buf, &buf_data)) sim_panel_set_error ("No registers specified");
return -1; return -1;
}
pthread_mutex_lock (&panel->io_lock); pthread_mutex_lock (&panel->io_lock);
if (buf_data != _panel_send (panel, buf, buf_data)) if (panel->reg_query_size != _panel_send (panel, panel->reg_query, panel->reg_query_size)) {
pthread_mutex_unlock (&panel->io_lock);
return -1; return -1;
}
panel->io_waiting = 1;
while (panel->io_waiting)
pthread_cond_wait (&panel->io_done, &panel->io_lock); pthread_cond_wait (&panel->io_done, &panel->io_lock);
pthread_mutex_unlock (&panel->io_lock); pthread_mutex_unlock (&panel->io_lock);
return 0; return 0;
@ -592,7 +701,7 @@ if (panel->State == Run) {
sim_panel_set_error ("Not Halted"); sim_panel_set_error ("Not Halted");
return -1; return -1;
} }
if (_panel_sendf (panel, "BOOT %s\r", device)) if (_panel_sendf (panel, 0, "BOOT %s\r", device))
return -1; return -1;
panel->State = Run; panel->State = Run;
return 0; return 0;
@ -609,7 +718,7 @@ if (panel->State == Run) {
sim_panel_set_error ("Not Halted"); sim_panel_set_error ("Not Halted");
return -1; return -1;
} }
if (5 != _panel_send (panel, "CONT\r", 5)) if (_panel_sendf (panel, 0, "CONT\r", 5))
return -1; return -1;
panel->State = Run; panel->State = Run;
return 0; return 0;
@ -633,6 +742,24 @@ panel->State = Run;
return 0; return 0;
} }
int
sim_panel_set_register_value (PANEL *panel,
const char *name,
const char *value)
{
if (!panel) {
sim_panel_set_error ("Invalid Panel");
return -1;
}
if (panel->callback) {
sim_panel_set_error ("Callback provides register data");
return -1;
}
if (_panel_sendf (panel, 1, "D %s %s", name, value))
return -1;
return 0;
}
static void * static void *
_panel_reader(void *arg) _panel_reader(void *arg)
{ {
@ -689,12 +816,21 @@ while (p->sock != INVALID_SOCKET) {
} }
} }
else { else {
if (!strcmp (s + strlen (sim_prompt), "# REGISTERS-DONE")) if (!strcmp (s + strlen (sim_prompt), register_get_echo)) {
if (p->callback) { if (p->callback) {
p->callback (p, p->callback_context); p->callback (p, p->callback_context);
} }
else { else {
pthread_mutex_lock (&p->io_lock); pthread_mutex_lock (&p->io_lock);
p->io_waiting = 0;
pthread_cond_signal (&p->io_done);
pthread_mutex_unlock (&p->io_lock);
}
}
else {
if (!strcmp (s + strlen (sim_prompt), command_done_echo)) {
pthread_mutex_lock (&p->io_lock);
p->io_waiting = 0;
pthread_cond_signal (&p->io_done); pthread_cond_signal (&p->io_done);
pthread_mutex_unlock (&p->io_lock); pthread_mutex_unlock (&p->io_lock);
} }
@ -702,6 +838,7 @@ while (p->sock != INVALID_SOCKET) {
/* Non Register Data Found (echo of EXAMINE or other commands) */ /* Non Register Data Found (echo of EXAMINE or other commands) */
} }
} }
}
s = eol; s = eol;
while (isspace(*s)) while (isspace(*s))
++s; ++s;
@ -730,7 +867,7 @@ PANEL *p = (PANEL*)arg;
int sched_policy; int sched_policy;
struct sched_param sched_priority; struct sched_param sched_priority;
char *buf = NULL; char *buf = NULL;
int buf_data = 0; size_t buf_data = 0;
unsigned int callback_count = 0; unsigned int callback_count = 0;
/* /*
@ -750,8 +887,9 @@ while ((p->sock != INVALID_SOCKET) &&
pthread_mutex_unlock (&p->io_lock); pthread_mutex_unlock (&p->io_lock);
++callback_count; ++callback_count;
if (1 == callback_count%rate) if (1 == callback_count%rate) {
_panel_register_query_string (p, &buf, &buf_data); _panel_register_query_string (p, &buf, &buf_data);
}
msleep (1000/rate); msleep (1000/rate);
if ((p->State == Run) || (0 == callback_count%(5*rate))) if ((p->State == Run) || (0 == callback_count%(5*rate)))
if (buf_data != _panel_send (p, buf, buf_data)) { if (buf_data != _panel_send (p, buf, buf_data)) {
@ -785,7 +923,7 @@ sim_panel_error_bufsize = 0;
#define vsnprintf _vsnprintf #define vsnprintf _vsnprintf
#endif #endif
void sim_panel_set_error (const char *fmt, ...) static void sim_panel_set_error (const char *fmt, ...)
{ {
va_list arglist; va_list arglist;
int len; int len;
@ -793,8 +931,8 @@ int len;
if (sim_panel_error_bufsize == 0) { if (sim_panel_error_bufsize == 0) {
sim_panel_error_bufsize = 2048; sim_panel_error_bufsize = 2048;
sim_panel_error_buf = (char *) malloc (sim_panel_error_bufsize); sim_panel_error_buf = (char *) malloc (sim_panel_error_bufsize);
if (sim_panel_error_buf == NULL) { /* out of memory */ if (sim_panel_error_buf == NULL) {
sim_panel_error_buf = "sim_panel_set_error(): Out of Memory\n"; sim_panel_error_buf = (char *)"sim_panel_set_error(): Out of Memory\n";
sim_panel_error_bufsize = 0; sim_panel_error_bufsize = 0;
return; return;
} }
@ -814,8 +952,8 @@ while (1) { /* format passed string, arg
while ((int)sim_panel_error_bufsize < len + 1) while ((int)sim_panel_error_bufsize < len + 1)
sim_panel_error_bufsize = sim_panel_error_bufsize * 2; sim_panel_error_bufsize = sim_panel_error_bufsize * 2;
sim_panel_error_buf = (char *) malloc (sim_panel_error_bufsize); sim_panel_error_buf = (char *) malloc (sim_panel_error_bufsize);
if (sim_panel_error_buf == NULL) { /* out of memory */ if (sim_panel_error_buf == NULL) {
sim_panel_error_buf = "sim_panel_set_error(): Out of Memory\n"; sim_panel_error_buf = (char *)"sim_panel_set_error(): Out of Memory\n";
sim_panel_error_bufsize = 0; sim_panel_error_bufsize = 0;
return; return;
} }
@ -829,12 +967,13 @@ return;
} }
static int static int
_panel_sendf (PANEL *p, const char *fmt, ...) _panel_sendf (PANEL *p, int wait_for_completion, const char *fmt, ...)
{ {
char stackbuf[1024]; char stackbuf[1024];
int bufsize = sizeof(stackbuf); int bufsize = sizeof(stackbuf);
char *buf = stackbuf; char *buf = stackbuf;
int len; int len;
int post_fix_len = wait_for_completion ? 5 + strlen (command_done_echo): 1;
va_list arglist; va_list arglist;
int ret; int ret;
@ -845,12 +984,12 @@ while (1) { /* format passed string, arg
/* If the formatted result didn't fit into the buffer, then grow the buffer and try again */ /* If the formatted result didn't fit into the buffer, then grow the buffer and try again */
if ((len < 0) || (len >= bufsize-1)) { if ((len < 0) || ((len + post_fix_len) >= bufsize-1)) {
if (buf != stackbuf) if (buf != stackbuf)
free (buf); free (buf);
bufsize = bufsize * 2; bufsize = bufsize * 2;
buf = (char *) _panel_malloc (bufsize); buf = (char *) _panel_malloc (bufsize);
if (buf == NULL) /* out of memory */ if (buf == NULL)
return -1; return -1;
buf[bufsize-1] = '\0'; buf[bufsize-1] = '\0';
continue; continue;
@ -858,8 +997,25 @@ while (1) { /* format passed string, arg
break; break;
} }
strcat (buf, "\r"); /* Make sure command line is terminated */
if (wait_for_completion) {
strcat (buf, command_done_echo);
strcat (buf, "\r");
pthread_mutex_lock (&p->io_lock);
}
ret = (strlen (buf) == _panel_send (p, buf, strlen (buf))) ? 0 : -1; ret = (strlen (buf) == _panel_send (p, buf, strlen (buf))) ? 0 : -1;
if (wait_for_completion) {
if (!ret) { /* Sent OK? */
p->io_waiting = 1;
while (p->io_waiting)
pthread_cond_wait (&p->io_done, &p->io_lock); /* Wait for completion */
}
pthread_mutex_unlock (&p->io_lock);
}
if (buf != stackbuf) if (buf != stackbuf)
free (buf); free (buf);
return ret; return ret;

View file

@ -40,22 +40,19 @@ extern "C" {
#include <stdlib.h> #include <stdlib.h>
typedef enum { typedef struct PANEL PANEL;
Halt,
Run
} OperationalState;
typedef struct sim_frontpanel PANEL;
typedef void (*PANEL_DISPLAY_PCALLBACK)(PANEL *panel,
void *context);
PANEL * PANEL *
sim_panel_start_simulator (const char *sim_path, sim_panel_start_simulator (const char *sim_path,
const char *sim_config); const char *sim_config,
size_t device_panel_count);
PANEL *
sim_panel_add_device_panel (PANEL *simulator_panel,
const char *device_name);
int int
sim_panel_stop_simulator (PANEL *panel); sim_panel_destroy (PANEL *panel);
int int
sim_panel_add_register (PANEL *panel, sim_panel_add_register (PANEL *panel,
@ -66,6 +63,9 @@ sim_panel_add_register (PANEL *panel,
int int
sim_panel_get_registers (PANEL *panel); sim_panel_get_registers (PANEL *panel);
typedef void (*PANEL_DISPLAY_PCALLBACK)(PANEL *panel,
void *context);
int int
sim_panel_set_display_callback (PANEL *panel, sim_panel_set_display_callback (PANEL *panel,
PANEL_DISPLAY_PCALLBACK callback, PANEL_DISPLAY_PCALLBACK callback,
@ -84,12 +84,21 @@ sim_panel_exec_run (PANEL *panel);
int int
sim_panel_exec_step (PANEL *panel); sim_panel_exec_step (PANEL *panel);
int
sim_panel_set_register_value (PANEL *panel,
const char *name,
const char *value);
typedef enum {
Halt,
Run
} OperationalState;
OperationalState OperationalState
sim_panel_get_state (PANEL *panel); sim_panel_get_state (PANEL *panel);
const char *sim_panel_get_error (void); const char *sim_panel_get_error (void);
void sim_panel_clear_error (void); void sim_panel_clear_error (void);
void sim_panel_set_error (const char *fmt, ...);
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -42,6 +42,10 @@
02-Sep-01 RMS Fixed UNIX bugs found by Mirian Lennox and Tom Markson 02-Sep-01 RMS Fixed UNIX bugs found by Mirian Lennox and Tom Markson
*/ */
#ifdef __cplusplus
extern "C" {
#endif
#include "sim_sock.h" #include "sim_sock.h"
#include <signal.h> #include <signal.h>
#include <stdio.h> #include <stdio.h>
@ -127,7 +131,7 @@ return;
static struct sock_errors { static struct sock_errors {
int value; int value;
char *text; const char *text;
} sock_errors[] = { } sock_errors[] = {
{WSAEWOULDBLOCK, "Operation would block"}, {WSAEWOULDBLOCK, "Operation would block"},
{WSAENAMETOOLONG, "File name too long"}, {WSAENAMETOOLONG, "File name too long"},
@ -694,7 +698,7 @@ return 0;
*/ */
int sim_parse_addr_ex (const char *cptr, char *host, size_t hostlen, const char *default_host, char *port, size_t port_len, char *localport, size_t localport_len, const char *default_port) int sim_parse_addr_ex (const char *cptr, char *host, size_t hostlen, const char *default_host, char *port, size_t port_len, char *localport, size_t localport_len, const char *default_port)
{ {
char *hostp; const char *hostp;
if ((localport != NULL) && (localport_len != 0)) if ((localport != NULL) && (localport_len != 0))
memset (localport, 0, localport_len); memset (localport, 0, localport_len);
@ -1258,3 +1262,7 @@ closesocket (sock);
} }
#endif /* end else !implemented */ #endif /* end else !implemented */
#ifdef __cplusplus
}
#endif