FRONTPANEL: sim_frontpanel API version 3 release
Adds: 1) Simulator side execution of register update activities at an interval specified in usecs. Rates in excess of 1000Hz should be achievable for locally connected frontpanel applications. 2) New API for simulators to describe the register state available in the simulator. If all of a the state which is potentially interesting to front panel applications is always present in the variables described by simh REG structures, then frontpanel API access to that data can be more efficiently provided.
This commit is contained in:
parent
7ac92a0e84
commit
110ded6904
6 changed files with 726 additions and 221 deletions
|
@ -35,6 +35,9 @@
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCXMLDataGeneratorTool"
|
Name="VCXMLDataGeneratorTool"
|
||||||
/>
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCMIDLTool"
|
Name="VCMIDLTool"
|
||||||
/>
|
/>
|
||||||
|
@ -116,6 +119,9 @@
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCXMLDataGeneratorTool"
|
Name="VCXMLDataGeneratorTool"
|
||||||
/>
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCMIDLTool"
|
Name="VCMIDLTool"
|
||||||
/>
|
/>
|
||||||
|
@ -126,7 +132,7 @@
|
||||||
EnableIntrinsicFunctions="true"
|
EnableIntrinsicFunctions="true"
|
||||||
FavorSizeOrSpeed="1"
|
FavorSizeOrSpeed="1"
|
||||||
OmitFramePointers="true"
|
OmitFramePointers="true"
|
||||||
WholeProgramOptimization="true"
|
WholeProgramOptimization="false"
|
||||||
AdditionalIncludeDirectories="./;../;../VAX/;../pdp11/;"../../windows-build/winpcap/Wpdpack/Include";"../../windows-build/PCRE/include/";"../../windows-build/pthreads""
|
AdditionalIncludeDirectories="./;../;../VAX/;../pdp11/;"../../windows-build/winpcap/Wpdpack/Include";"../../windows-build/PCRE/include/";"../../windows-build/pthreads""
|
||||||
PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;PTW32_STATIC_LIB"
|
PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;PTW32_STATIC_LIB"
|
||||||
StringPooling="true"
|
StringPooling="true"
|
||||||
|
|
|
@ -148,11 +148,10 @@ if ((argc > 1) && ((!strcmp("-d", argv[1])) || (!strcmp("-D", argv[1])) || (!str
|
||||||
if ((f = fopen (sim_config, "w"))) {
|
if ((f = fopen (sim_config, "w"))) {
|
||||||
if (debug) {
|
if (debug) {
|
||||||
fprintf (f, "set verbose\n");
|
fprintf (f, "set verbose\n");
|
||||||
fprintf (f, "set log simulator.dbg\n");
|
fprintf (f, "set debug -n -a simulator.dbg\n");
|
||||||
fprintf (f, "set debug -n -a log\n");
|
|
||||||
fprintf (f, "set cpu conhalt\n");
|
fprintf (f, "set cpu conhalt\n");
|
||||||
fprintf (f, "set remote telnet=2226\n");
|
fprintf (f, "set remote telnet=2226\n");
|
||||||
fprintf (f, "set rem-con debug=XMT;RCV\n");
|
fprintf (f, "set rem-con debug=XMT;RCV;MODE;REPEAT;CMD\n");
|
||||||
fprintf (f, "set remote notelnet\n");
|
fprintf (f, "set remote notelnet\n");
|
||||||
}
|
}
|
||||||
fprintf (f, "set cpu autoboot\n");
|
fprintf (f, "set cpu autoboot\n");
|
||||||
|
@ -184,9 +183,8 @@ if (!panel) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
sim_panel_set_debug_mode (panel, DBG_XMT|DBG_RCV);
|
sim_panel_set_debug_mode (panel, DBG_XMT|DBG_RCV|DBG_REQ|DBG_RSP);
|
||||||
}
|
}
|
||||||
|
|
||||||
tape = sim_panel_add_device_panel (panel, "TAPE DRIVE");
|
tape = sim_panel_add_device_panel (panel, "TAPE DRIVE");
|
||||||
|
|
||||||
if (!tape) {
|
if (!tape) {
|
||||||
|
@ -313,7 +311,7 @@ if (sim_panel_get_registers (panel, NULL)) {
|
||||||
printf ("Error getting register data: %s\n", sim_panel_get_error());
|
printf ("Error getting register data: %s\n", sim_panel_get_error());
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
if (sim_panel_set_display_callback (panel, &DisplayCallback, NULL, 5)) {
|
if (sim_panel_set_display_callback_interval (panel, &DisplayCallback, NULL, 200000)) {
|
||||||
printf ("Error setting automatic display callback: %s\n", sim_panel_get_error());
|
printf ("Error setting automatic display callback: %s\n", sim_panel_get_error());
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
@ -336,19 +334,27 @@ if (sim_panel_dismount (panel, "RL0")) {
|
||||||
}
|
}
|
||||||
remove ("TEST-RL.DSK");
|
remove ("TEST-RL.DSK");
|
||||||
if (sim_panel_break_set (panel, "400")) {
|
if (sim_panel_break_set (panel, "400")) {
|
||||||
printf ("Unexpected establishing a breakpoint: %s\n", sim_panel_get_error());
|
printf ("Unexpected error establishing a breakpoint: %s\n", sim_panel_get_error());
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
if (sim_panel_break_clear (panel, "400")) {
|
if (sim_panel_break_clear (panel, "400")) {
|
||||||
printf ("Unexpected clearing a breakpoint: %s\n", sim_panel_get_error());
|
printf ("Unexpected error clearing a breakpoint: %s\n", sim_panel_get_error());
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
if (sim_panel_break_output_set (panel, "\"32..31..30\"")) {
|
if (sim_panel_break_output_set (panel, "\"32..31..30\"")) {
|
||||||
printf ("Unexpected establishing an output breakpoint: %s\n", sim_panel_get_error());
|
printf ("Unexpected error establishing an output breakpoint: %s\n", sim_panel_get_error());
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
if (sim_panel_break_output_clear (panel, "\"32..31..30\"")) {
|
if (sim_panel_break_output_clear (panel, "\"32..31..30\"")) {
|
||||||
printf ("Unexpected clearing an output breakpoint: %s\n", sim_panel_get_error());
|
printf ("Unexpected error clearing an output breakpoint: %s\n", sim_panel_get_error());
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
if (sim_panel_break_output_set (panel, "-P \"Normal operation not possible.\"")) {
|
||||||
|
printf ("Unexpected error establishing an output breakpoint: %s\n", sim_panel_get_error());
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
if (sim_panel_break_output_set (panel, "-P \"Device? [XQA0]: \"")) {
|
||||||
|
printf ("Unexpected error establishing an output breakpoint: %s\n", sim_panel_get_error());
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
sim_panel_clear_error ();
|
sim_panel_clear_error ();
|
||||||
|
|
348
sim_console.c
348
sim_console.c
|
@ -114,6 +114,9 @@
|
||||||
sim_ttisatty called to determine if running interactively
|
sim_ttisatty called to determine if running interactively
|
||||||
sim_os_poll_kbd poll for keyboard input
|
sim_os_poll_kbd poll for keyboard input
|
||||||
sim_os_putchar output character to console
|
sim_os_putchar output character to console
|
||||||
|
sim_set_noconsole_port Enable automatic WRU console polling
|
||||||
|
sim_set_stable_registers_state Declare that all registers are always stable
|
||||||
|
|
||||||
|
|
||||||
The first group is OS-independent; the second group is OS-dependent.
|
The first group is OS-independent; the second group is OS-dependent.
|
||||||
|
|
||||||
|
@ -172,6 +175,7 @@ int32 sim_del_char = '\b'; /* delete character */
|
||||||
#else
|
#else
|
||||||
int32 sim_del_char = 0177;
|
int32 sim_del_char = 0177;
|
||||||
#endif
|
#endif
|
||||||
|
extern TMLN *sim_oline; /* global output socket */
|
||||||
|
|
||||||
static t_stat sim_con_poll_svc (UNIT *uptr); /* console connection poll routine */
|
static t_stat sim_con_poll_svc (UNIT *uptr); /* console connection poll routine */
|
||||||
static t_stat sim_con_reset (DEVICE *dptr); /* console reset routine */
|
static t_stat sim_con_reset (DEVICE *dptr); /* console reset routine */
|
||||||
|
@ -243,6 +247,16 @@ sim_con_console_port = FALSE;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static t_bool sim_con_stable_registers = FALSE;
|
||||||
|
|
||||||
|
/* Enable automatic WRU console polling */
|
||||||
|
|
||||||
|
t_stat sim_set_stable_registers_state (void)
|
||||||
|
{
|
||||||
|
sim_con_stable_registers = TRUE;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Unit service for console connection polling */
|
/* Unit service for console connection polling */
|
||||||
|
|
||||||
static t_stat sim_con_poll_svc (UNIT *uptr)
|
static t_stat sim_con_poll_svc (UNIT *uptr)
|
||||||
|
@ -409,18 +423,28 @@ while (*cptr != 0) {
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MAX_REMOTE_SESSIONS 40 /* Arbitrary Session Limit */
|
||||||
|
|
||||||
t_stat sim_rem_con_poll_svc (UNIT *uptr); /* remote console connection poll routine */
|
t_stat sim_rem_con_poll_svc (UNIT *uptr); /* remote console connection poll routine */
|
||||||
t_stat sim_rem_con_data_svc (UNIT *uptr); /* remote console connection data routine */
|
t_stat sim_rem_con_data_svc (UNIT *uptr); /* remote console connection data routine */
|
||||||
|
t_stat sim_rem_con_repeat_svc (UNIT *uptr); /* remote auto repeat command console timing routine */
|
||||||
t_stat sim_rem_con_reset (DEVICE *dptr); /* remote console reset routine */
|
t_stat sim_rem_con_reset (DEVICE *dptr); /* remote console reset routine */
|
||||||
UNIT sim_rem_con_unit[2] = {
|
UNIT sim_rem_con_unit[2+MAX_REMOTE_SESSIONS] = {
|
||||||
{ UDATA (&sim_rem_con_poll_svc, UNIT_IDLE, 0) }, /* remote console connection polling unit */
|
{ UDATA (&sim_rem_con_poll_svc, UNIT_IDLE, 0) }, /* remote console connection polling unit */
|
||||||
{ UDATA (&sim_rem_con_data_svc, UNIT_IDLE|UNIT_DIS, 0) }}; /* console data handling unit */
|
{ UDATA (&sim_rem_con_data_svc, UNIT_IDLE|UNIT_DIS, 0) }}; /* console data handling unit */
|
||||||
|
|
||||||
|
#define DBG_MOD 0x00000004 /* Remote Console Mode activities */
|
||||||
|
#define DBG_REP 0x00000008 /* Remote Console Repeat activities */
|
||||||
|
#define DBG_CMD 0x00000010 /* Remote Console Command activities */
|
||||||
|
|
||||||
DEBTAB sim_rem_con_debug[] = {
|
DEBTAB sim_rem_con_debug[] = {
|
||||||
{"TRC", DBG_TRC, "routine calls"},
|
{"TRC", DBG_TRC, "routine calls"},
|
||||||
{"XMT", DBG_XMT, "Transmitted Data"},
|
{"XMT", DBG_XMT, "Transmitted Data"},
|
||||||
{"RCV", DBG_RCV, "Received Data"},
|
{"RCV", DBG_RCV, "Received Data"},
|
||||||
{"CON", DBG_CON, "connection activity"},
|
{"CON", DBG_CON, "connection activity"},
|
||||||
|
{"CMD", DBG_CMD, "Remote Console Command activity"},
|
||||||
|
{"MODE", DBG_MOD, "Remote Console Mode activity"},
|
||||||
|
{"REPEAT", DBG_REP, "Remote Console Repeat activity"},
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -439,10 +463,15 @@ DEVICE sim_remote_console = {
|
||||||
NULL, NULL, sim_rem_con_reset, NULL, NULL, NULL,
|
NULL, NULL, sim_rem_con_reset, NULL, NULL, NULL,
|
||||||
NULL, DEV_DEBUG | DEV_NOSAVE, 0, sim_rem_con_debug,
|
NULL, DEV_DEBUG | DEV_NOSAVE, 0, sim_rem_con_debug,
|
||||||
NULL, NULL, NULL, NULL, NULL, sim_rem_con_description};
|
NULL, NULL, NULL, NULL, NULL, sim_rem_con_description};
|
||||||
#define MAX_REMOTE_SESSIONS 40 /* Arbitrary Session Limit */
|
|
||||||
static int32 *sim_rem_buf_size = NULL;
|
static int32 *sim_rem_buf_size = NULL;
|
||||||
static int32 *sim_rem_buf_ptr = NULL;
|
static int32 *sim_rem_buf_ptr = NULL;
|
||||||
static char **sim_rem_buf = NULL;
|
static char **sim_rem_buf = NULL;
|
||||||
|
static char **sim_rem_act_buf = NULL;
|
||||||
|
static size_t *sim_rem_act_buf_size = NULL;
|
||||||
|
static char **sim_rem_act = NULL;
|
||||||
|
static uint32 *sim_rem_repeat_interval = NULL;
|
||||||
|
static t_bool *sim_rem_repeat_pending = NULL;
|
||||||
|
static char **sim_rem_repeat_action = NULL;
|
||||||
static t_bool *sim_rem_single_mode = NULL; /* per line command mode (single command or must continue) */
|
static t_bool *sim_rem_single_mode = NULL; /* per line command mode (single command or must continue) */
|
||||||
static TMXR sim_rem_con_tmxr = { 0, 0, 0, NULL, NULL, &sim_remote_console };/* remote console line mux */
|
static TMXR sim_rem_con_tmxr = { 0, 0, 0, NULL, NULL, &sim_remote_console };/* remote console line mux */
|
||||||
static uint32 sim_rem_read_timeout = 30; /* seconds before automatic continue */
|
static uint32 sim_rem_read_timeout = 30; /* seconds before automatic continue */
|
||||||
|
@ -523,6 +552,10 @@ for (i=connections=0; i<sim_rem_con_tmxr.lines; i++) {
|
||||||
else
|
else
|
||||||
fprintf (st, "Remote Console Input on connection %d does not continue automatically\n", i);
|
fprintf (st, "Remote Console Input on connection %d does not continue automatically\n", i);
|
||||||
}
|
}
|
||||||
|
if (sim_rem_repeat_action[i]) {
|
||||||
|
fprintf (st, "The Command: %s\n", sim_rem_repeat_action[i]);
|
||||||
|
fprintf (st, " is repeated every %s\n", sim_fmt_secs (sim_rem_repeat_interval[i] / 1000000.0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -567,17 +600,22 @@ return SCPE_OK;
|
||||||
|
|
||||||
static t_stat x_continue_cmd (int32 flag, CONST char *cptr)
|
static t_stat x_continue_cmd (int32 flag, CONST char *cptr)
|
||||||
{
|
{
|
||||||
return SCPE_IERR; /* This routine should never be called */
|
return 1+SCPE_IERR; /* This routine should never be called */
|
||||||
|
}
|
||||||
|
|
||||||
|
static t_stat x_repeat_cmd (int32 flag, CONST char *cptr)
|
||||||
|
{
|
||||||
|
return 2+SCPE_IERR; /* This routine should never be called */
|
||||||
}
|
}
|
||||||
|
|
||||||
static t_stat x_step_cmd (int32 flag, CONST char *cptr)
|
static t_stat x_step_cmd (int32 flag, CONST char *cptr)
|
||||||
{
|
{
|
||||||
return SCPE_IERR; /* This routine should never be called */
|
return 3+SCPE_IERR; /* This routine should never be called */
|
||||||
}
|
}
|
||||||
|
|
||||||
static t_stat x_run_cmd (int32 flag, CONST char *cptr)
|
static t_stat x_run_cmd (int32 flag, CONST char *cptr)
|
||||||
{
|
{
|
||||||
return SCPE_IERR; /* This routine should never be called */
|
return 4+SCPE_IERR; /* This routine should never be called */
|
||||||
}
|
}
|
||||||
|
|
||||||
static t_stat x_help_cmd (int32 flag, CONST char *cptr);
|
static t_stat x_help_cmd (int32 flag, CONST char *cptr);
|
||||||
|
@ -591,6 +629,7 @@ static CTAB allowed_remote_cmds[] = {
|
||||||
{ "ASSIGN", &assign_cmd, 0 },
|
{ "ASSIGN", &assign_cmd, 0 },
|
||||||
{ "DEASSIGN", &deassign_cmd, 0 },
|
{ "DEASSIGN", &deassign_cmd, 0 },
|
||||||
{ "CONTINUE", &x_continue_cmd, 0 },
|
{ "CONTINUE", &x_continue_cmd, 0 },
|
||||||
|
{ "REPEAT", &x_repeat_cmd, 0 },
|
||||||
{ "STEP", &x_step_cmd, 0 },
|
{ "STEP", &x_step_cmd, 0 },
|
||||||
{ "PWD", &pwd_cmd, 0 },
|
{ "PWD", &pwd_cmd, 0 },
|
||||||
{ "SAVE", &save_cmd, 0 },
|
{ "SAVE", &save_cmd, 0 },
|
||||||
|
@ -612,6 +651,7 @@ static CTAB allowed_master_remote_cmds[] = {
|
||||||
{ "ASSIGN", &assign_cmd, 0 },
|
{ "ASSIGN", &assign_cmd, 0 },
|
||||||
{ "DEASSIGN", &deassign_cmd, 0 },
|
{ "DEASSIGN", &deassign_cmd, 0 },
|
||||||
{ "CONTINUE", &x_continue_cmd, 0 },
|
{ "CONTINUE", &x_continue_cmd, 0 },
|
||||||
|
{ "REPEAT", &x_repeat_cmd, 0 },
|
||||||
{ "STEP", &x_step_cmd, 0 },
|
{ "STEP", &x_step_cmd, 0 },
|
||||||
{ "PWD", &pwd_cmd, 0 },
|
{ "PWD", &pwd_cmd, 0 },
|
||||||
{ "SAVE", &save_cmd, 0 },
|
{ "SAVE", &save_cmd, 0 },
|
||||||
|
@ -629,6 +669,9 @@ static CTAB allowed_master_remote_cmds[] = {
|
||||||
{ "BOOT", &x_run_cmd, RU_BOOT },
|
{ "BOOT", &x_run_cmd, RU_BOOT },
|
||||||
{ "BREAK", &brk_cmd, SSH_ST },
|
{ "BREAK", &brk_cmd, SSH_ST },
|
||||||
{ "NOBREAK", &brk_cmd, SSH_CL },
|
{ "NOBREAK", &brk_cmd, SSH_CL },
|
||||||
|
{ "EXPECT", &expect_cmd, 1 },
|
||||||
|
{ "NOEXPECT", &expect_cmd, 0 },
|
||||||
|
{ "SEND", &send_cmd, 0 },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -637,6 +680,7 @@ static CTAB allowed_single_remote_cmds[] = {
|
||||||
{ "DETACH", &detach_cmd, 0 },
|
{ "DETACH", &detach_cmd, 0 },
|
||||||
{ "EXAMINE", &exdep_cmd, EX_E },
|
{ "EXAMINE", &exdep_cmd, EX_E },
|
||||||
{ "EVALUATE", &eval_cmd, 0 },
|
{ "EVALUATE", &eval_cmd, 0 },
|
||||||
|
{ "REPEAT", &x_repeat_cmd, 0 },
|
||||||
{ "PWD", &pwd_cmd, 0 },
|
{ "PWD", &pwd_cmd, 0 },
|
||||||
{ "DIR", &dir_cmd, 0 },
|
{ "DIR", &dir_cmd, 0 },
|
||||||
{ "LS", &dir_cmd, 0 },
|
{ "LS", &dir_cmd, 0 },
|
||||||
|
@ -646,6 +690,11 @@ static CTAB allowed_single_remote_cmds[] = {
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static CTAB remote_only_cmds[] = {
|
||||||
|
{ "REPEAT", &x_repeat_cmd, 0 },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
static t_stat x_help_cmd (int32 flag, CONST char *cptr)
|
static t_stat x_help_cmd (int32 flag, CONST char *cptr)
|
||||||
{
|
{
|
||||||
CTAB *cmdp, *cmdph;
|
CTAB *cmdp, *cmdph;
|
||||||
|
@ -690,23 +739,27 @@ return stat;
|
||||||
static void _sim_rem_log_out (TMLN *lp)
|
static void _sim_rem_log_out (TMLN *lp)
|
||||||
{
|
{
|
||||||
char cbuf[4*CBUFSIZE];
|
char cbuf[4*CBUFSIZE];
|
||||||
|
int line = (int)(lp - sim_rem_con_tmxr.ldsc);
|
||||||
|
|
||||||
if (sim_log) {
|
if ((!sim_oline) && (sim_log)) {
|
||||||
int32 unwritten;
|
|
||||||
|
|
||||||
fflush (sim_log);
|
fflush (sim_log);
|
||||||
sim_fseeko (sim_log, sim_rem_cmd_log_start, SEEK_SET);
|
sim_fseeko (sim_log, sim_rem_cmd_log_start, SEEK_SET);
|
||||||
cbuf[sizeof(cbuf)-1] = '\0';
|
cbuf[sizeof(cbuf)-1] = '\0';
|
||||||
while (fgets (cbuf, sizeof(cbuf)-1, sim_log))
|
while (fgets (cbuf, sizeof(cbuf)-1, sim_log))
|
||||||
tmxr_linemsgf (lp, "%s", cbuf);
|
tmxr_linemsgf (lp, "%s", cbuf);
|
||||||
if (!tmxr_input_pending_ln (lp)) {
|
}
|
||||||
|
sim_oline = NULL;
|
||||||
|
if ((sim_rem_act[line] == NULL) &&
|
||||||
|
(!tmxr_input_pending_ln (lp))) {
|
||||||
|
int32 unwritten;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
unwritten = tmxr_send_buffered_data (lp);
|
unwritten = tmxr_send_buffered_data (lp);
|
||||||
if (unwritten == lp->txbsz)
|
if (unwritten == lp->txbsz)
|
||||||
sim_os_ms_sleep (100);
|
sim_os_ms_sleep (100);
|
||||||
} while (unwritten == lp->txbsz);
|
} while (unwritten == lp->txbsz);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sim_remote_process_command (void)
|
void sim_remote_process_command (void)
|
||||||
|
@ -724,17 +777,152 @@ cptr = cbuf;
|
||||||
cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */
|
cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */
|
||||||
sim_rem_active_command = find_cmd (gbuf); /* find command */
|
sim_rem_active_command = find_cmd (gbuf); /* find command */
|
||||||
|
|
||||||
sim_ttcmd (); /* restore console */
|
if (!sim_processing_event)
|
||||||
|
sim_ttcmd (); /* restore console */
|
||||||
stat = sim_rem_active_command->action (sim_rem_active_command->arg, cptr);/* execute command */
|
stat = sim_rem_active_command->action (sim_rem_active_command->arg, cptr);/* execute command */
|
||||||
if (stat != SCPE_OK)
|
if (stat != SCPE_OK)
|
||||||
stat = _sim_rem_message (gbuf, stat); /* display results */
|
stat = _sim_rem_message (gbuf, stat); /* display results */
|
||||||
sim_last_cmd_stat = SCPE_BARE_STATUS(stat);
|
sim_last_cmd_stat = SCPE_BARE_STATUS(stat);
|
||||||
sim_ttrun (); /* set console mode */
|
if (!sim_processing_event) {
|
||||||
sim_cancel (&sim_rem_con_unit[1]); /* force immediate activation of sim_rem_con_data_svc */
|
sim_ttrun (); /* set console mode */
|
||||||
sim_activate (&sim_rem_con_unit[1], -1);
|
sim_cancel (&sim_rem_con_unit[1]); /* force immediate activation of sim_rem_con_data_svc */
|
||||||
|
sim_activate (&sim_rem_con_unit[1], -1);
|
||||||
|
}
|
||||||
sim_switches = saved_switches; /* restore original switches */
|
sim_switches = saved_switches; /* restore original switches */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Clear pending actions */
|
||||||
|
|
||||||
|
static char *sim_rem_clract (int32 line)
|
||||||
|
{
|
||||||
|
TMLN *lp = &sim_rem_con_tmxr.ldsc[line];
|
||||||
|
|
||||||
|
tmxr_send_buffered_data (lp); /* flush any buffered data */
|
||||||
|
return sim_rem_act[line] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up pending actions */
|
||||||
|
|
||||||
|
static void sim_rem_setact (int32 line, const char *action)
|
||||||
|
{
|
||||||
|
if (action) {
|
||||||
|
size_t act_size = strlen (action) + 1;
|
||||||
|
|
||||||
|
if (act_size > sim_rem_act_buf_size[line]) {/* expand buffer if necessary */
|
||||||
|
sim_rem_act_buf[line] = (char *)realloc (sim_rem_act_buf[line], act_size);
|
||||||
|
sim_rem_act_buf_size[line] = act_size;
|
||||||
|
}
|
||||||
|
strcpy (sim_rem_act_buf[line], action); /* populate buffer */
|
||||||
|
sim_rem_act[line] = sim_rem_act_buf[line]; /* start at beginning of buffer */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sim_rem_clract (line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get next pending action, if any */
|
||||||
|
|
||||||
|
static char *sim_rem_getact (int32 line, char *buf, int32 size)
|
||||||
|
{
|
||||||
|
char *ep;
|
||||||
|
size_t lnt;
|
||||||
|
|
||||||
|
if (sim_rem_act[line] == NULL) /* any action? */
|
||||||
|
return NULL;
|
||||||
|
while (sim_isspace (*sim_rem_act[line])) /* skip spaces */
|
||||||
|
sim_rem_act[line]++;
|
||||||
|
if (*sim_rem_act[line] == 0) /* now empty? */
|
||||||
|
return sim_rem_clract (line);
|
||||||
|
if ((ep = strchr (sim_rem_act[line], ';'))) { /* cmd delimiter? */
|
||||||
|
lnt = ep - sim_rem_act[line]; /* cmd length */
|
||||||
|
memcpy (buf, sim_rem_act[line], lnt + 1); /* copy with ; */
|
||||||
|
buf[lnt] = 0; /* erase ; */
|
||||||
|
sim_rem_act[line] += lnt + 1; /* adv ptr */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strncpy (buf, sim_rem_act[line], size); /* copy action */
|
||||||
|
sim_rem_act[line] += strlen (sim_rem_act[line]);/* adv ptr to end */
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Parse and setup Remote Console REPEAT command:
|
||||||
|
REPEAT EVERY nnn USECS Command {; command...}
|
||||||
|
*/
|
||||||
|
static t_stat _rem_repeat_cmd_setup (int32 line, CONST char **iptr)
|
||||||
|
{
|
||||||
|
char gbuf[CBUFSIZE];
|
||||||
|
int32 val;
|
||||||
|
t_bool all_stop = FALSE;
|
||||||
|
t_stat stat = SCPE_OK;
|
||||||
|
CONST char *cptr = *iptr;
|
||||||
|
|
||||||
|
sim_debug (DBG_REP, &sim_remote_console, "Repeat Setup: %s\n", cptr);
|
||||||
|
if (*cptr == 0) /* required argument? */
|
||||||
|
stat = SCPE_2FARG;
|
||||||
|
else {
|
||||||
|
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
||||||
|
if (MATCH_CMD (gbuf, "EVERY") == 0) {
|
||||||
|
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
||||||
|
val = (int32) get_uint (gbuf, 10, INT_MAX, &stat);
|
||||||
|
if ((stat != SCPE_OK) || (val <= 0)) /* error? */
|
||||||
|
stat = SCPE_ARG;
|
||||||
|
else {
|
||||||
|
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
||||||
|
if ((MATCH_CMD (gbuf, "USECS") != 0) || (*cptr == 0))
|
||||||
|
stat = SCPE_ARG;
|
||||||
|
else
|
||||||
|
sim_rem_repeat_interval[line] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (MATCH_CMD (gbuf, "STOP") == 0) {
|
||||||
|
if (*cptr) { /* more command arguments? */
|
||||||
|
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
||||||
|
if ((MATCH_CMD (gbuf, "ALL") != 0) || /* */
|
||||||
|
(*cptr != 0) || /* */
|
||||||
|
(line != 0)) /* master line? */
|
||||||
|
stat = SCPE_ARG;
|
||||||
|
else
|
||||||
|
all_stop = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sim_rem_repeat_interval[line] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
stat = SCPE_ARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stat == SCPE_OK) {
|
||||||
|
if (all_stop) {
|
||||||
|
for (line = 0; line < sim_rem_con_tmxr.lines; line++) {
|
||||||
|
free (sim_rem_repeat_action[line]);
|
||||||
|
sim_rem_repeat_action[line] = NULL;
|
||||||
|
sim_cancel (&sim_rem_con_unit[line + 2]);
|
||||||
|
sim_rem_repeat_pending[line] = FALSE;
|
||||||
|
sim_rem_clract (line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (sim_rem_repeat_interval[line] != 0) {
|
||||||
|
sim_rem_repeat_action[line] = (char *)realloc (sim_rem_repeat_action[line], 1 + strlen (cptr));
|
||||||
|
strcpy (sim_rem_repeat_action[line], cptr);
|
||||||
|
cptr += strlen (cptr);
|
||||||
|
stat = sim_activate_after (&sim_rem_con_unit[line + 2], sim_rem_repeat_interval[line]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
free (sim_rem_repeat_action[line]);
|
||||||
|
sim_rem_repeat_action[line] = NULL;
|
||||||
|
sim_cancel (&sim_rem_con_unit[line + 2]);
|
||||||
|
}
|
||||||
|
sim_rem_repeat_pending[line] = FALSE;
|
||||||
|
sim_rem_clract (line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*iptr = cptr;
|
||||||
|
return stat;
|
||||||
|
}
|
||||||
|
|
||||||
/* Unit service for remote console data polling */
|
/* Unit service for remote console data polling */
|
||||||
|
|
||||||
t_stat sim_rem_con_data_svc (UNIT *uptr)
|
t_stat sim_rem_con_data_svc (UNIT *uptr)
|
||||||
|
@ -760,8 +948,13 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||||
t_bool master_session = (sim_rem_master_mode && (i == 0));
|
t_bool master_session = (sim_rem_master_mode && (i == 0));
|
||||||
|
|
||||||
lp = &sim_rem_con_tmxr.ldsc[i];
|
lp = &sim_rem_con_tmxr.ldsc[i];
|
||||||
if (!lp->conn)
|
if (!lp->conn) {
|
||||||
|
if (sim_rem_repeat_interval[i]) { /* was repeated enabled? */
|
||||||
|
cptr = strcpy (gbuf, "STOP");
|
||||||
|
_rem_repeat_cmd_setup (i, &cptr); /* make sure it is now disabled */
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if (master_session && !sim_rem_master_was_connected) {
|
if (master_session && !sim_rem_master_was_connected) {
|
||||||
tmxr_linemsgf (lp, "\nMaster Mode Session\r\n");
|
tmxr_linemsgf (lp, "\nMaster Mode Session\r\n");
|
||||||
tmxr_send_buffered_data (lp); /* flush any buffered data */
|
tmxr_send_buffered_data (lp); /* flush any buffered data */
|
||||||
|
@ -770,6 +963,7 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||||
stat = SCPE_OK;
|
stat = SCPE_OK;
|
||||||
if ((was_active_command) ||
|
if ((was_active_command) ||
|
||||||
(master_session && !sim_rem_single_mode[i])) {
|
(master_session && !sim_rem_single_mode[i])) {
|
||||||
|
sim_debug (DBG_MOD, &sim_remote_console, "Session: %d %s %s\n", i, was_active_command ? "Was Active" : "", (master_session && !sim_rem_single_mode[i]) ? "master_session && !sim_rem_single_mode[i]" : "");
|
||||||
if (was_active_command) {
|
if (was_active_command) {
|
||||||
sim_rem_cmd_active_line = -1; /* Done with active command */
|
sim_rem_cmd_active_line = -1; /* Done with active command */
|
||||||
if (!sim_rem_active_command) { /* STEP command? */
|
if (!sim_rem_active_command) { /* STEP command? */
|
||||||
|
@ -792,10 +986,10 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||||
tmxr_linemsgf (lpj, "\nRemote Master Console(%s) Entering Commands\n", lp->ipad);
|
tmxr_linemsgf (lpj, "\nRemote Master Console(%s) Entering Commands\n", lp->ipad);
|
||||||
tmxr_send_buffered_data (lpj); /* flush any buffered data */
|
tmxr_send_buffered_data (lpj); /* flush any buffered data */
|
||||||
}
|
}
|
||||||
lp = &sim_rem_con_tmxr.ldsc[i];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if ((!sim_rem_repeat_pending[i]) || (sim_rem_buf_ptr[i] != 0)) {
|
||||||
c = tmxr_getc_ln (lp);
|
c = tmxr_getc_ln (lp);
|
||||||
if (!(TMXR_VALID & c))
|
if (!(TMXR_VALID & c))
|
||||||
continue;
|
continue;
|
||||||
|
@ -842,12 +1036,13 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||||
else
|
else
|
||||||
tmxr_linemsgf (lp, "\r\n%s", sim_is_running ? "SIM> " : "sim> ");
|
tmxr_linemsgf (lp, "\r\n%s", sim_is_running ? "SIM> " : "sim> ");
|
||||||
sim_debug (DBG_XMT, &sim_remote_console, "Prompt Written: %s\n", sim_is_running ? "SIM> " : "sim> ");
|
sim_debug (DBG_XMT, &sim_remote_console, "Prompt Written: %s\n", sim_is_running ? "SIM> " : "sim> ");
|
||||||
if (!tmxr_input_pending_ln (lp))
|
if ((sim_rem_act[i] == NULL) && (!tmxr_input_pending_ln (lp)))
|
||||||
tmxr_send_buffered_data (lp); /* flush any buffered data */
|
tmxr_send_buffered_data (lp); /* flush any buffered data */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
got_command = FALSE;
|
got_command = FALSE;
|
||||||
while (1) {
|
while (1) {
|
||||||
if (stat == SCPE_EXIT)
|
if (stat == SCPE_EXIT)
|
||||||
|
@ -861,6 +1056,31 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||||
tmxr_send_buffered_data (lp); /* flush any buffered data */
|
tmxr_send_buffered_data (lp); /* flush any buffered data */
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
|
if (sim_rem_buf_ptr[i] == 0) {
|
||||||
|
if (sim_rem_getact (i, sim_rem_buf[i], sim_rem_buf_size[i])) {
|
||||||
|
if (!master_session)
|
||||||
|
tmxr_linemsgf (lp, "%s%s\n", sim_prompt, sim_rem_buf[i]);
|
||||||
|
else
|
||||||
|
tmxr_linemsgf (lp, "%s%s\n", sim_is_running ? "SIM> " : "sim> ", sim_rem_buf[i]);
|
||||||
|
sim_rem_buf_ptr[i] = strlen (sim_rem_repeat_action[i]);
|
||||||
|
got_command = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (sim_rem_repeat_pending[i]) {
|
||||||
|
sim_rem_repeat_pending[i] = FALSE;
|
||||||
|
sim_rem_setact (i, sim_rem_repeat_action[i]);
|
||||||
|
sim_rem_getact (i, sim_rem_buf[i], sim_rem_buf_size[i]);
|
||||||
|
if (!master_session)
|
||||||
|
tmxr_linemsgf (lp, "%s%s\n", sim_prompt, sim_rem_buf[i]);
|
||||||
|
else
|
||||||
|
tmxr_linemsgf (lp, "%s%s\n", sim_is_running ? "SIM> " : "sim> ", sim_rem_buf[i]);
|
||||||
|
sim_rem_buf_ptr[i] = strlen (sim_rem_repeat_action[i]);
|
||||||
|
got_command = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!sim_rem_single_mode[i]) {
|
if (!sim_rem_single_mode[i]) {
|
||||||
c = tmxr_getc_ln (lp);
|
c = tmxr_getc_ln (lp);
|
||||||
if (!(TMXR_VALID & c)) {
|
if (!(TMXR_VALID & c)) {
|
||||||
|
@ -957,11 +1177,12 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||||
c = c & ~TMXR_VALID;
|
c = c & ~TMXR_VALID;
|
||||||
}
|
}
|
||||||
} while ((!got_command) && ((!sim_rem_single_mode[i]) || c));
|
} while ((!got_command) && ((!sim_rem_single_mode[i]) || c));
|
||||||
if (!tmxr_input_pending_ln (lp))
|
if ((sim_rem_act[i] == NULL) && (!tmxr_input_pending_ln (lp)))
|
||||||
tmxr_send_buffered_data (lp); /* flush any buffered data */
|
tmxr_send_buffered_data (lp); /* flush any buffered data */
|
||||||
if ((sim_rem_single_mode[i]) && !got_command) {
|
if ((sim_rem_single_mode[i]) && !got_command) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!sim_rem_master_mode)
|
||||||
sim_printf ("Remote Console Command from %s> %s\r\n", lp->ipad, sim_rem_buf[i]);
|
sim_printf ("Remote Console Command from %s> %s\r\n", lp->ipad, sim_rem_buf[i]);
|
||||||
got_command = FALSE;
|
got_command = FALSE;
|
||||||
if (strlen(sim_rem_buf[i]) >= sizeof(cbuf)) {
|
if (strlen(sim_rem_buf[i]) >= sizeof(cbuf)) {
|
||||||
|
@ -1000,6 +1221,8 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||||
}
|
}
|
||||||
sim_rem_cmd_log_start = sim_ftell (sim_log);
|
sim_rem_cmd_log_start = sim_ftell (sim_log);
|
||||||
basecmdp = find_cmd (gbuf); /* validate basic command */
|
basecmdp = find_cmd (gbuf); /* validate basic command */
|
||||||
|
if (basecmdp == NULL)
|
||||||
|
basecmdp = find_ctab (remote_only_cmds, gbuf);/* validate basic command */
|
||||||
if (basecmdp == NULL) {
|
if (basecmdp == NULL) {
|
||||||
if ((gbuf[0] == ';') || (gbuf[0] == '#')) { /* ignore comment */
|
if ((gbuf[0] == ';') || (gbuf[0] == '#')) { /* ignore comment */
|
||||||
sim_rem_cmd_active_line = i;
|
sim_rem_cmd_active_line = i;
|
||||||
|
@ -1013,12 +1236,16 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ((cmdp = find_ctab (sim_rem_single_mode[i] ? allowed_single_remote_cmds : (master_session ? allowed_master_remote_cmds : allowed_remote_cmds), gbuf))) {/* lookup command */
|
if ((cmdp = find_ctab (sim_rem_single_mode[i] ? allowed_single_remote_cmds : (master_session ? allowed_master_remote_cmds : allowed_remote_cmds), gbuf))) {/* lookup command */
|
||||||
if (cmdp->action == &x_continue_cmd)
|
sim_debug (DBG_CMD, &sim_remote_console, "gbuf='%s', basecmd='%s', cmd='%s', action=%p, continue_cmd=%p, repeat_cmd=%p\n", gbuf, basecmdp->name, cmdp->name, cmdp->action, &x_continue_cmd, &x_repeat_cmd);
|
||||||
|
if (cmdp->action == &x_continue_cmd) {
|
||||||
|
sim_debug (DBG_CMD, &sim_remote_console, "continue_cmd executing\n");
|
||||||
stat = SCPE_OK;
|
stat = SCPE_OK;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if (cmdp->action == &exit_cmd)
|
if (cmdp->action == &exit_cmd)
|
||||||
return SCPE_EXIT;
|
return SCPE_EXIT;
|
||||||
if (cmdp->action == &x_step_cmd) {
|
if (cmdp->action == &x_step_cmd) {
|
||||||
|
sim_debug (DBG_CMD, &sim_remote_console, "step_cmd executing\n");
|
||||||
steps = 1; /* default of 1 instruction */
|
steps = 1; /* default of 1 instruction */
|
||||||
stat = SCPE_OK;
|
stat = SCPE_OK;
|
||||||
if (*cptr != 0) { /* argument? */
|
if (*cptr != 0) { /* argument? */
|
||||||
|
@ -1036,19 +1263,40 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (cmdp->action == &x_run_cmd) {
|
if (cmdp->action == &x_run_cmd) {
|
||||||
sim_switches |= SIM_SW_HIDE;/* Request Setup only */
|
sim_debug (DBG_CMD, &sim_remote_console, "run_cmd executing\n");
|
||||||
|
if (sim_con_stable_registers && /* can we process command now? */
|
||||||
|
sim_rem_master_mode)
|
||||||
|
sim_oline = lp; /* specify output socket */
|
||||||
|
sim_switches |= SIM_SW_HIDE; /* Request Setup only */
|
||||||
stat = basecmdp->action (cmdp->arg, cptr);
|
stat = basecmdp->action (cmdp->arg, cptr);
|
||||||
sim_switches &= ~SIM_SW_HIDE;/* Done with Setup only mode */
|
sim_switches &= ~SIM_SW_HIDE; /* Done with Setup only mode */
|
||||||
if (stat == SCPE_OK) {
|
if (stat == SCPE_OK) {
|
||||||
/* switch to CONTINUE after x_run_cmd() did RUN setup */
|
/* switch to CONTINUE after x_run_cmd() did RUN setup */
|
||||||
cmdp = find_ctab (allowed_master_remote_cmds, "CONTINUE");
|
cmdp = find_ctab (allowed_master_remote_cmds, "CONTINUE");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
|
if (cmdp->action == &x_repeat_cmd) {
|
||||||
|
sim_debug (DBG_CMD, &sim_remote_console, "repeat_cmd executing\n");
|
||||||
|
stat = _rem_repeat_cmd_setup (i, &cptr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (sim_con_stable_registers &&
|
||||||
|
sim_rem_master_mode) { /* can we process command now? */
|
||||||
|
sim_debug (DBG_CMD, &sim_remote_console, "Processing Command directly\n");
|
||||||
|
sim_oline = lp; /* specify output socket */
|
||||||
|
sim_remote_process_command ();
|
||||||
|
stat = SCPE_OK; /* any message has already been emitted */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sim_debug (DBG_CMD, &sim_remote_console, "Processing Command via SCPE_REMOTE\n");
|
||||||
stat = SCPE_REMOTE; /* force processing outside of sim_instr() */
|
stat = SCPE_REMOTE; /* force processing outside of sim_instr() */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
stat = SCPE_INVREM;
|
stat = SCPE_INVREM;
|
||||||
}
|
}
|
||||||
|
@ -1136,14 +1384,36 @@ else
|
||||||
return SCPE_OK; /* keep going */
|
return SCPE_OK; /* keep going */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t_stat sim_rem_con_repeat_svc (UNIT *uptr)
|
||||||
|
{
|
||||||
|
int line = uptr - (sim_rem_con_unit + 2);
|
||||||
|
|
||||||
|
sim_debug (DBG_REP, &sim_remote_console, "sim_rem_con_repeat_svc(line=%d) - interval=%d\n", line, sim_rem_repeat_interval[line]);
|
||||||
|
if (sim_rem_repeat_interval[line]) {
|
||||||
|
sim_rem_repeat_pending[line] = TRUE;
|
||||||
|
sim_activate_after (uptr, sim_rem_repeat_interval[line]); /* reschedule */
|
||||||
|
sim_activate_abs (&sim_rem_con_unit[1], -1); /* wake up to process */
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
t_stat sim_rem_con_reset (DEVICE *dptr)
|
t_stat sim_rem_con_reset (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
if (sim_rem_con_tmxr.lines) {
|
if (sim_rem_con_tmxr.lines) {
|
||||||
int32 i;
|
int32 i;
|
||||||
|
|
||||||
for (i=0; i<sim_rem_con_tmxr.lines; i++)
|
sim_debug (DBG_REP, &sim_remote_console, "sim_rem_con_reset(lines=%d)\n", sim_rem_con_tmxr.lines);
|
||||||
if (sim_rem_con_tmxr.ldsc[i].conn)
|
for (i=0; i<MAX_REMOTE_SESSIONS; i++) {
|
||||||
break;
|
sim_rem_con_unit[i + 2].flags = UNIT_DIS;
|
||||||
|
sim_rem_con_unit[i + 2].action = &sim_rem_con_repeat_svc;
|
||||||
|
}
|
||||||
|
for (i=0; i<sim_rem_con_tmxr.lines; i++) {
|
||||||
|
if (!sim_rem_con_tmxr.ldsc[i].conn)
|
||||||
|
continue;
|
||||||
|
sim_debug (DBG_REP, &sim_remote_console, "sim_rem_con_reset(line=%d, usecs=%d)\n", i, sim_rem_repeat_interval[i]);
|
||||||
|
if (sim_rem_repeat_interval[i])
|
||||||
|
sim_activate_after (sim_rem_con_unit + 2 + i, sim_rem_repeat_interval[i]);/* schedule */
|
||||||
|
}
|
||||||
if (i != sim_rem_con_tmxr.lines)
|
if (i != sim_rem_con_tmxr.lines)
|
||||||
sim_activate_after (&dptr->units[1], 100000); /* continue polling for open sessions */
|
sim_activate_after (&dptr->units[1], 100000); /* continue polling for open sessions */
|
||||||
return sim_rem_con_poll_svc (&dptr->units[0]); /* establish polling as needed */
|
return sim_rem_con_poll_svc (&dptr->units[0]); /* establish polling as needed */
|
||||||
|
@ -1208,10 +1478,22 @@ sim_rem_con_tmxr.ldsc = (TMLN *)realloc (sim_rem_con_tmxr.ldsc, sizeof(*sim_rem_
|
||||||
memset (sim_rem_con_tmxr.ldsc, 0, sizeof(*sim_rem_con_tmxr.ldsc)*lines);
|
memset (sim_rem_con_tmxr.ldsc, 0, sizeof(*sim_rem_con_tmxr.ldsc)*lines);
|
||||||
sim_rem_buf = (char **)realloc (sim_rem_buf, sizeof(*sim_rem_buf)*lines);
|
sim_rem_buf = (char **)realloc (sim_rem_buf, sizeof(*sim_rem_buf)*lines);
|
||||||
memset (sim_rem_buf, 0, sizeof(*sim_rem_buf)*lines);
|
memset (sim_rem_buf, 0, sizeof(*sim_rem_buf)*lines);
|
||||||
|
sim_rem_act_buf = (char **)realloc (sim_rem_act_buf, sizeof(*sim_rem_act_buf)*lines);
|
||||||
|
memset (sim_rem_act_buf, 0, sizeof(*sim_rem_act_buf)*lines);
|
||||||
|
sim_rem_act_buf_size = (size_t *)realloc (sim_rem_act_buf_size, sizeof(*sim_rem_act_buf_size)*lines);
|
||||||
|
memset (sim_rem_act_buf_size, 0, sizeof(*sim_rem_act_buf_size)*lines);
|
||||||
|
sim_rem_act = (char **)realloc (sim_rem_act, sizeof(*sim_rem_act)*lines);
|
||||||
|
memset (sim_rem_act, 0, sizeof(*sim_rem_act)*lines);
|
||||||
sim_rem_buf_size = (int32 *)realloc (sim_rem_buf_size, sizeof(*sim_rem_buf_size)*lines);
|
sim_rem_buf_size = (int32 *)realloc (sim_rem_buf_size, sizeof(*sim_rem_buf_size)*lines);
|
||||||
memset (sim_rem_buf_size, 0, sizeof(*sim_rem_buf_size)*lines);
|
memset (sim_rem_buf_size, 0, sizeof(*sim_rem_buf_size)*lines);
|
||||||
sim_rem_buf_ptr = (int32 *)realloc (sim_rem_buf_ptr, sizeof(*sim_rem_buf_ptr)*lines);
|
sim_rem_buf_ptr = (int32 *)realloc (sim_rem_buf_ptr, sizeof(*sim_rem_buf_ptr)*lines);
|
||||||
memset (sim_rem_buf_ptr, 0, sizeof(*sim_rem_buf_ptr)*lines);
|
memset (sim_rem_buf_ptr, 0, sizeof(*sim_rem_buf_ptr)*lines);
|
||||||
|
sim_rem_repeat_interval = (uint32 *)realloc (sim_rem_repeat_interval, sizeof(*sim_rem_repeat_interval)*lines);
|
||||||
|
memset (sim_rem_repeat_interval, 0, sizeof(*sim_rem_repeat_interval)*lines);
|
||||||
|
sim_rem_repeat_pending = (t_bool *)realloc (sim_rem_repeat_pending, sizeof(*sim_rem_repeat_pending)*lines);
|
||||||
|
memset (sim_rem_repeat_pending, 0, sizeof(*sim_rem_repeat_pending)*lines);
|
||||||
|
sim_rem_repeat_action = (char **)realloc (sim_rem_repeat_action, sizeof(*sim_rem_repeat_action)*lines);
|
||||||
|
memset (sim_rem_repeat_action, 0, sizeof(*sim_rem_repeat_action)*lines);
|
||||||
sim_rem_single_mode = (t_bool *)realloc (sim_rem_single_mode, sizeof(*sim_rem_single_mode)*lines);
|
sim_rem_single_mode = (t_bool *)realloc (sim_rem_single_mode, sizeof(*sim_rem_single_mode)*lines);
|
||||||
memset (sim_rem_single_mode, 0, sizeof(*sim_rem_single_mode)*lines);
|
memset (sim_rem_single_mode, 0, sizeof(*sim_rem_single_mode)*lines);
|
||||||
sim_rem_read_timeouts = (uint32 *)realloc (sim_rem_read_timeouts, sizeof(*sim_rem_read_timeouts)*lines);
|
sim_rem_read_timeouts = (uint32 *)realloc (sim_rem_read_timeouts, sizeof(*sim_rem_read_timeouts)*lines);
|
||||||
|
@ -1346,7 +1628,8 @@ t_stat sim_show_kmap (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char
|
||||||
{
|
{
|
||||||
if (sim_devices[0]->dradix == 16)
|
if (sim_devices[0]->dradix == 16)
|
||||||
fprintf (st, "%s = %X\n", show_con_tab[flag].name, *(cons_kmap[flag & KMAP_MASK]));
|
fprintf (st, "%s = %X\n", show_con_tab[flag].name, *(cons_kmap[flag & KMAP_MASK]));
|
||||||
else fprintf (st, "%s = %o\n", show_con_tab[flag].name, *(cons_kmap[flag & KMAP_MASK]));
|
else
|
||||||
|
fprintf (st, "%s = %o\n", show_con_tab[flag].name, *(cons_kmap[flag & KMAP_MASK]));
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1376,7 +1659,8 @@ t_stat sim_show_pchar (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST cha
|
||||||
{
|
{
|
||||||
if (sim_devices[0]->dradix == 16)
|
if (sim_devices[0]->dradix == 16)
|
||||||
fprintf (st, "pchar mask = %X", sim_tt_pchar);
|
fprintf (st, "pchar mask = %X", sim_tt_pchar);
|
||||||
else fprintf (st, "pchar mask = %o", sim_tt_pchar);
|
else
|
||||||
|
fprintf (st, "pchar mask = %o", sim_tt_pchar);
|
||||||
if (sim_tt_pchar) {
|
if (sim_tt_pchar) {
|
||||||
static const char *pchars[] = {"NUL(^@)", "SOH(^A)", "STX(^B)", "ETX(^C)", "EOT(^D)", "ENQ(^E)", "ACK(^F)", "BEL(^G)",
|
static const char *pchars[] = {"NUL(^@)", "SOH(^A)", "STX(^B)", "ETX(^C)", "EOT(^D)", "ENQ(^E)", "ACK(^F)", "BEL(^G)",
|
||||||
"BS(^H)" , "HT(^I)", "LF(^J)", "VT(^K)", "FF(^L)", "CR(^M)", "SO(^N)", "SI(^O)",
|
"BS(^H)" , "HT(^I)", "LF(^J)", "VT(^K)", "FF(^L)", "CR(^M)", "SO(^N)", "SI(^O)",
|
||||||
|
@ -1433,7 +1717,7 @@ r = sim_open_logfile (gbuf, FALSE, &sim_log, &sim_log_ref); /* open log */
|
||||||
if (r != SCPE_OK) /* error? */
|
if (r != SCPE_OK) /* error? */
|
||||||
return r;
|
return r;
|
||||||
if (!sim_quiet)
|
if (!sim_quiet)
|
||||||
printf ("Logging to file \"%s\"\n",
|
fprintf (stdout, "Logging to file \"%s\"\n",
|
||||||
sim_logfile_name (sim_log, sim_log_ref));
|
sim_logfile_name (sim_log, sim_log_ref));
|
||||||
fprintf (sim_log, "Logging to file \"%s\"\n",
|
fprintf (sim_log, "Logging to file \"%s\"\n",
|
||||||
sim_logfile_name (sim_log, sim_log_ref)); /* start of log */
|
sim_logfile_name (sim_log, sim_log_ref)); /* start of log */
|
||||||
|
@ -1451,7 +1735,7 @@ if (cptr && (*cptr != 0)) /* now eol? */
|
||||||
if (sim_log == NULL) /* no log? */
|
if (sim_log == NULL) /* no log? */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
if (!sim_quiet)
|
if (!sim_quiet)
|
||||||
printf ("Log file closed\n");
|
fprintf (stdout, "Log file closed\n");
|
||||||
fprintf (sim_log, "Log file closed\n");
|
fprintf (sim_log, "Log file closed\n");
|
||||||
sim_close_logfile (&sim_log_ref); /* close log */
|
sim_close_logfile (&sim_log_ref); /* close log */
|
||||||
sim_log = NULL;
|
sim_log = NULL;
|
||||||
|
@ -1467,7 +1751,8 @@ if (cptr && (*cptr != 0))
|
||||||
if (sim_log)
|
if (sim_log)
|
||||||
fprintf (st, "Logging enabled to \"%s\"\n",
|
fprintf (st, "Logging enabled to \"%s\"\n",
|
||||||
sim_logfile_name (sim_log, sim_log_ref));
|
sim_logfile_name (sim_log, sim_log_ref));
|
||||||
else fprintf (st, "Logging disabled\n");
|
else
|
||||||
|
fprintf (st, "Logging disabled\n");
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1591,7 +1876,8 @@ if (sim_deb) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else fprintf (st, "Debug output disabled\n");
|
else
|
||||||
|
fprintf (st, "Debug output disabled\n");
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,6 +113,7 @@ SEND *sim_cons_get_send (void);
|
||||||
EXPECT *sim_cons_get_expect (void);
|
EXPECT *sim_cons_get_expect (void);
|
||||||
t_stat sim_show_cons_send_input (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr);
|
t_stat sim_show_cons_send_input (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr);
|
||||||
t_stat sim_set_noconsole_port (void);
|
t_stat sim_set_noconsole_port (void);
|
||||||
|
t_stat sim_set_stable_registers_state (void);
|
||||||
t_stat sim_poll_kbd (void);
|
t_stat sim_poll_kbd (void);
|
||||||
t_stat sim_putchar (int32 c);
|
t_stat sim_putchar (int32 c);
|
||||||
t_stat sim_putchar_s (int32 c);
|
t_stat sim_putchar_s (int32 c);
|
||||||
|
|
394
sim_frontpanel.c
394
sim_frontpanel.c
|
@ -134,6 +134,7 @@ struct PANEL {
|
||||||
size_t reg_count;
|
size_t reg_count;
|
||||||
REG *regs;
|
REG *regs;
|
||||||
char *reg_query;
|
char *reg_query;
|
||||||
|
int new_register;
|
||||||
size_t reg_query_size;
|
size_t reg_query_size;
|
||||||
unsigned long long array_element_data;
|
unsigned long long array_element_data;
|
||||||
OperationalState State;
|
OperationalState State;
|
||||||
|
@ -143,6 +144,8 @@ struct PANEL {
|
||||||
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;
|
||||||
|
pthread_mutex_t io_command_lock;
|
||||||
|
int command_count;
|
||||||
int io_reg_query_pending;
|
int io_reg_query_pending;
|
||||||
int io_waiting;
|
int io_waiting;
|
||||||
char *io_response;
|
char *io_response;
|
||||||
|
@ -154,7 +157,7 @@ struct PANEL {
|
||||||
pthread_t callback_thread;
|
pthread_t callback_thread;
|
||||||
int callback_thread_running;
|
int callback_thread_running;
|
||||||
void *callback_context;
|
void *callback_context;
|
||||||
int callbacks_per_second;
|
int usecs_between_callbacks;
|
||||||
int debug;
|
int debug;
|
||||||
char *simulator_version;
|
char *simulator_version;
|
||||||
int radix;
|
int radix;
|
||||||
|
@ -167,10 +170,16 @@ struct PANEL {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *sim_prompt = "sim> ";
|
static const char *sim_prompt = "sim> ";
|
||||||
|
static const char *register_repeat_prefix = "repeat every ";
|
||||||
|
static const char *register_repeat_stop = "repeat stop";
|
||||||
|
static const char *register_repeat_stop_all = "repeat stop all";
|
||||||
|
static const char *register_repeat_units = " usecs ";
|
||||||
static const char *register_get_prefix = "show time";
|
static const char *register_get_prefix = "show time";
|
||||||
static const char *register_get_echo = "# REGISTERS-DONE";
|
static const char *register_get_echo = "# REGISTERS-DONE";
|
||||||
|
static const char *register_repeat_echo = "# REGISTERS-REPEAT-DONE";
|
||||||
static const char *register_dev_echo = "# REGISTERS-FOR-DEVICE:";
|
static const char *register_dev_echo = "# REGISTERS-FOR-DEVICE:";
|
||||||
static const char *register_ind_echo = "# REGISTER-INDIRECT:";
|
static const char *register_ind_echo = "# REGISTER-INDIRECT:";
|
||||||
|
static const char *command_status = "ECHO Status:%STATUS%-%TSTATUS%";
|
||||||
static const char *command_done_echo = "# COMMAND-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);
|
||||||
|
@ -209,7 +218,18 @@ if (p == NULL)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _panel_debug (PANEL *p, int dbits, const char *fmt, const char *buf, int bufsize, ...)
|
/* Allow compiler to help validate printf style format arguments */
|
||||||
|
#if !defined __GNUC__
|
||||||
|
#define GCC_FMT_ATTR(n, m)
|
||||||
|
#endif
|
||||||
|
#if !defined(GCC_FMT_ATTR)
|
||||||
|
#define GCC_FMT_ATTR(n, m) __attribute__ ((format (__printf__, n, m)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void __panel_debug (PANEL *p, int dbits, const char *fmt, const char *buf, int bufsize, ...) GCC_FMT_ATTR(3, 6);
|
||||||
|
#define _panel_debug(p, dbits, fmt, buf, bufsize, ...) do { if (p && p->Debug && (dbits & p->debug)) __panel_debug (p, dbits, fmt, buf, bufsize, ##__VA_ARGS__);} while (0)
|
||||||
|
|
||||||
|
static void __panel_debug (PANEL *p, int dbits, const char *fmt, const char *buf, int bufsize, ...)
|
||||||
{
|
{
|
||||||
if (p && p->Debug && (dbits & p->debug)) {
|
if (p && p->Debug && (dbits & p->debug)) {
|
||||||
int i;
|
int i;
|
||||||
|
@ -300,6 +320,7 @@ sim_panel_set_debug_file (PANEL *panel, const char *debug_file)
|
||||||
if (!panel)
|
if (!panel)
|
||||||
return;
|
return;
|
||||||
panel->Debug = fopen(debug_file, "w");
|
panel->Debug = fopen(debug_file, "w");
|
||||||
|
setvbuf (panel->Debug, NULL, _IOFBF, 65536);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -348,13 +369,13 @@ return sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_panel_sendf (PANEL *p, int wait_for_completion, char **response, const char *fmt, ...);
|
_panel_sendf (PANEL *p, int *completion_status, char **response, const char *fmt, ...);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_panel_register_query_string (PANEL *panel, char **buf, size_t *buf_size)
|
_panel_register_query_string (PANEL *panel, char **buf, size_t *buf_size)
|
||||||
{
|
{
|
||||||
size_t i, j, buf_data, buf_needed = 0;
|
size_t i, j, buf_data, buf_needed = 0;
|
||||||
char *dev;
|
const char *dev;
|
||||||
|
|
||||||
pthread_mutex_lock (&panel->io_lock);
|
pthread_mutex_lock (&panel->io_lock);
|
||||||
buf_needed = 2 + strlen (register_get_prefix); /* SHOW TIME */
|
buf_needed = 2 + strlen (register_get_prefix); /* SHOW TIME */
|
||||||
|
@ -381,7 +402,7 @@ sprintf (*buf + buf_data, "%s\r", register_get_prefix);
|
||||||
buf_data += strlen (*buf + buf_data);
|
buf_data += strlen (*buf + buf_data);
|
||||||
dev = "";
|
dev = "";
|
||||||
for (i=j=0; i<panel->reg_count; i++) {
|
for (i=j=0; i<panel->reg_count; i++) {
|
||||||
char *reg_dev = panel->regs[i].device_name ? panel->regs[i].device_name : "";
|
const char *reg_dev = panel->regs[i].device_name ? panel->regs[i].device_name : "";
|
||||||
|
|
||||||
if (panel->regs[i].indirect)
|
if (panel->regs[i].indirect)
|
||||||
continue;
|
continue;
|
||||||
|
@ -412,9 +433,9 @@ for (i=j=0; i<panel->reg_count; i++) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (j == 0)
|
if (j == 0)
|
||||||
sprintf (*buf + buf_data, "E -H %s %s[0:%d]", dev, panel->regs[i].name, panel->regs[i].element_count-1);
|
sprintf (*buf + buf_data, "E -H %s %s[0:%d]", dev, panel->regs[i].name, (int)(panel->regs[i].element_count-1));
|
||||||
else
|
else
|
||||||
sprintf (*buf + buf_data, ",%s[0:%d]", panel->regs[i].name, panel->regs[i].element_count-1);
|
sprintf (*buf + buf_data, ",%s[0:%d]", panel->regs[i].name, (int)(panel->regs[i].element_count-1));
|
||||||
}
|
}
|
||||||
++j;
|
++j;
|
||||||
buf_data += strlen (*buf + buf_data);
|
buf_data += strlen (*buf + buf_data);
|
||||||
|
@ -424,7 +445,7 @@ if (buf_data && ((*buf)[buf_data-1] != '\r')) {
|
||||||
buf_data += strlen (*buf + buf_data);
|
buf_data += strlen (*buf + buf_data);
|
||||||
}
|
}
|
||||||
for (i=j=0; i<panel->reg_count; i++) {
|
for (i=j=0; i<panel->reg_count; i++) {
|
||||||
char *reg_dev = panel->regs[i].device_name ? panel->regs[i].device_name : "";
|
const char *reg_dev = panel->regs[i].device_name ? panel->regs[i].device_name : "";
|
||||||
|
|
||||||
if (!panel->regs[i].indirect)
|
if (!panel->regs[i].indirect)
|
||||||
continue;
|
continue;
|
||||||
|
@ -495,6 +516,7 @@ FILE *fOut = NULL;
|
||||||
struct stat statb;
|
struct stat statb;
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
int port;
|
int port;
|
||||||
|
int cmd_stat;
|
||||||
size_t i, device_num;
|
size_t i, device_num;
|
||||||
char hostport[64];
|
char hostport[64];
|
||||||
union {int i; char c[sizeof (int)]; } end_test;
|
union {int i; char c[sizeof (int)]; } end_test;
|
||||||
|
@ -540,7 +562,6 @@ else {
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
if (stat (sim_config, &statb) < 0) {
|
if (stat (sim_config, &statb) < 0) {
|
||||||
sim_panel_set_error ("Can't stat simulator configuration '%s': %s", sim_config, strerror(errno));
|
sim_panel_set_error ("Can't stat simulator configuration '%s': %s", sim_config, strerror(errno));
|
||||||
|
@ -599,6 +620,30 @@ if (debug_file) {
|
||||||
sim_panel_set_debug_file (p, debug_file);
|
sim_panel_set_debug_file (p, debug_file);
|
||||||
sim_panel_set_debug_mode (p, DBG_XMT|DBG_RCV);
|
sim_panel_set_debug_mode (p, DBG_XMT|DBG_RCV);
|
||||||
_panel_debug (p, DBG_XMT|DBG_RCV, "Creating Simulator Process %s\n", NULL, 0, sim_path);
|
_panel_debug (p, DBG_XMT|DBG_RCV, "Creating Simulator Process %s\n", NULL, 0, sim_path);
|
||||||
|
|
||||||
|
if (stat (p->temp_config, &statb) < 0) {
|
||||||
|
sim_panel_set_error ("Can't stat temporary simulator configuration '%s': %s", p->temp_config, strerror(errno));
|
||||||
|
goto Error_Return;
|
||||||
|
}
|
||||||
|
buf = (char *)_panel_malloc (statb.st_size+1);
|
||||||
|
if (buf == NULL)
|
||||||
|
goto Error_Return;
|
||||||
|
buf[statb.st_size] = '\0';
|
||||||
|
fIn = fopen (p->temp_config, "r");
|
||||||
|
if (fIn == NULL) {
|
||||||
|
sim_panel_set_error ("Can't open temporary configuration file '%s': %s", p->temp_config, strerror(errno));
|
||||||
|
goto Error_Return;
|
||||||
|
}
|
||||||
|
_panel_debug (p, DBG_XMT|DBG_RCV, "Using Temporary Configuration File '%s' containing:", NULL, 0, p->temp_config);
|
||||||
|
i = 0;
|
||||||
|
while (fgets (buf, statb.st_size, fIn)) {
|
||||||
|
++i;
|
||||||
|
buf[strlen(buf) - 1] = '\0';
|
||||||
|
_panel_debug (p, DBG_XMT|DBG_RCV, "Line %2d: %s", NULL, 0, (int)i, buf);
|
||||||
|
}
|
||||||
|
free (buf);
|
||||||
|
buf = NULL;
|
||||||
|
fclose (fIn);
|
||||||
}
|
}
|
||||||
if (!simulator_panel) {
|
if (!simulator_panel) {
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
@ -659,9 +704,10 @@ if (p->sock == INVALID_SOCKET) {
|
||||||
}
|
}
|
||||||
goto Error_Return;
|
goto Error_Return;
|
||||||
}
|
}
|
||||||
_panel_debug (p, DBG_XMT|DBG_RCV, "Connected to simulator at %s after %dms\n", NULL, 0, p->hostport, i*100);
|
_panel_debug (p, DBG_XMT|DBG_RCV, "Connected to simulator on %s after %dms\n", NULL, 0, p->hostport, (int)i*100);
|
||||||
pthread_mutex_init (&p->io_lock, NULL);
|
pthread_mutex_init (&p->io_lock, NULL);
|
||||||
pthread_mutex_init (&p->io_send_lock, NULL);
|
pthread_mutex_init (&p->io_send_lock, NULL);
|
||||||
|
pthread_mutex_init (&p->io_command_lock, NULL);
|
||||||
pthread_cond_init (&p->io_done, NULL);
|
pthread_cond_init (&p->io_done, NULL);
|
||||||
pthread_cond_init (&p->startup_cond, NULL);
|
pthread_cond_init (&p->startup_cond, NULL);
|
||||||
if (sizeof(mantra) != _panel_send (p, (char *)mantra, sizeof(mantra))) {
|
if (sizeof(mantra) != _panel_send (p, (char *)mantra, sizeof(mantra))) {
|
||||||
|
@ -696,7 +742,7 @@ else {
|
||||||
if (p->State == Error)
|
if (p->State == Error)
|
||||||
goto Error_Return;
|
goto Error_Return;
|
||||||
/* Validate sim_frontpanel API version */
|
/* Validate sim_frontpanel API version */
|
||||||
if (_panel_sendf (p, 1, &p->simulator_version, "SHOW VERSION\r"))
|
if (_panel_sendf (p, &cmd_stat, &p->simulator_version, "SHOW VERSION\r"))
|
||||||
goto Error_Return;
|
goto Error_Return;
|
||||||
if (1) {
|
if (1) {
|
||||||
int api_version = 0;
|
int api_version = 0;
|
||||||
|
@ -712,7 +758,7 @@ else {
|
||||||
if (1) {
|
if (1) {
|
||||||
char *radix = NULL;
|
char *radix = NULL;
|
||||||
|
|
||||||
if (_panel_sendf (p, 1, &radix, "SHOW %s RADIX\r", p->device_name ? p->device_name : "")) {
|
if (_panel_sendf (p, &cmd_stat, &radix, "SHOW %s RADIX\r", p->device_name ? p->device_name : "")) {
|
||||||
free (radix);
|
free (radix);
|
||||||
goto Error_Return;
|
goto Error_Return;
|
||||||
}
|
}
|
||||||
|
@ -807,18 +853,23 @@ if (panel) {
|
||||||
int wait_count;
|
int wait_count;
|
||||||
|
|
||||||
/* First, wind down the automatic register queries */
|
/* First, wind down the automatic register queries */
|
||||||
sim_panel_set_display_callback (panel, NULL, NULL, 0);
|
sim_panel_set_display_callback_interval (panel, NULL, NULL, 0);
|
||||||
/* Next, attempt a simulator shutdown */
|
/* Next, attempt a simulator shutdown only with the master panel */
|
||||||
_panel_send (panel, "\005\rEXIT\r", 7);
|
if (panel->parent == NULL) {
|
||||||
|
if (panel->State == Run)
|
||||||
|
_panel_send (panel, "\005\r", 2);
|
||||||
|
_panel_send (panel, "EXIT\r", 5);
|
||||||
|
}
|
||||||
/* Wait for up to 2 seconds for a graceful shutdown */
|
/* Wait for up to 2 seconds for a graceful shutdown */
|
||||||
for (wait_count=0; panel->io_thread_running && (wait_count<20); ++wait_count)
|
for (wait_count=0; panel->io_thread_running && (wait_count<20); ++wait_count)
|
||||||
msleep (100);
|
msleep (100);
|
||||||
/* Now close the socket which should stop a pending read which hasn't completed */
|
/* Now close the socket which should stop a pending read that hasn't completed */
|
||||||
panel->sock = INVALID_SOCKET;
|
panel->sock = INVALID_SOCKET;
|
||||||
sim_close_sock (sock);
|
sim_close_sock (sock);
|
||||||
pthread_join (panel->io_thread, NULL);
|
pthread_join (panel->io_thread, NULL);
|
||||||
pthread_mutex_destroy (&panel->io_lock);
|
pthread_mutex_destroy (&panel->io_lock);
|
||||||
pthread_mutex_destroy (&panel->io_send_lock);
|
pthread_mutex_destroy (&panel->io_send_lock);
|
||||||
|
pthread_mutex_destroy (&panel->io_command_lock);
|
||||||
pthread_cond_destroy (&panel->io_done);
|
pthread_cond_destroy (&panel->io_done);
|
||||||
}
|
}
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
@ -881,11 +932,16 @@ _panel_add_register (PANEL *panel,
|
||||||
REG *regs, *reg;
|
REG *regs, *reg;
|
||||||
char *response = NULL;
|
char *response = NULL;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
int cmd_stat;
|
||||||
|
|
||||||
if (!panel || (panel->State == Error)) {
|
if (!panel || (panel->State == Error)) {
|
||||||
sim_panel_set_error ("Invalid Panel");
|
sim_panel_set_error ("Invalid Panel");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (panel->State == Run) {
|
||||||
|
sim_panel_set_error ("Not Halted");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
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) {
|
||||||
panel->State = Error;
|
panel->State = Error;
|
||||||
|
@ -953,7 +1009,7 @@ reg->size = size;
|
||||||
reg->element_count = element_count;
|
reg->element_count = element_count;
|
||||||
pthread_mutex_unlock (&panel->io_lock);
|
pthread_mutex_unlock (&panel->io_lock);
|
||||||
/* Validate existence of requested register/array */
|
/* Validate existence of requested register/array */
|
||||||
if (_panel_sendf (panel, 1, &response, "EXAMINE %s %s%s\r", device_name? device_name : "", name, (element_count > 0) ? "[0]" : "")) {
|
if (_panel_sendf (panel, &cmd_stat, &response, "EXAMINE %s %s%s\r", device_name? device_name : "", name, (element_count > 0) ? "[0]" : "")) {
|
||||||
free (reg->name);
|
free (reg->name);
|
||||||
free (reg->device_name);
|
free (reg->device_name);
|
||||||
free (regs);
|
free (regs);
|
||||||
|
@ -969,7 +1025,7 @@ if (!strcmp ("Invalid argument\r\n", response)) {
|
||||||
}
|
}
|
||||||
free (response);
|
free (response);
|
||||||
if (element_count > 0) {
|
if (element_count > 0) {
|
||||||
if (_panel_sendf (panel, 1, &response, "EXAMINE %s %s[%d]\r", device_name? device_name : "", name, element_count-1)) {
|
if (_panel_sendf (panel, &cmd_stat, &response, "EXAMINE %s %s[%d]\r", device_name? device_name : "", name, element_count-1)) {
|
||||||
free (reg->name);
|
free (reg->name);
|
||||||
free (reg->device_name);
|
free (reg->device_name);
|
||||||
free (regs);
|
free (regs);
|
||||||
|
@ -989,6 +1045,7 @@ pthread_mutex_lock (&panel->io_lock);
|
||||||
++panel->reg_count;
|
++panel->reg_count;
|
||||||
free (panel->regs);
|
free (panel->regs);
|
||||||
panel->regs = regs;
|
panel->regs = regs;
|
||||||
|
panel->new_register = 1;
|
||||||
pthread_mutex_unlock (&panel->io_lock);
|
pthread_mutex_unlock (&panel->io_lock);
|
||||||
/* Now build the register query string for the whole register list */
|
/* Now build the register query string for the whole register list */
|
||||||
if (_panel_register_query_string (panel, &panel->reg_query, &panel->reg_query_size))
|
if (_panel_register_query_string (panel, &panel->reg_query, &panel->reg_query_size))
|
||||||
|
@ -1028,14 +1085,14 @@ sim_panel_add_register_indirect (PANEL *panel,
|
||||||
return _panel_add_register (panel, name, device_name, size, addr, 1, 0);
|
return _panel_add_register (panel, name, device_name, size, addr, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
sim_panel_get_registers (PANEL *panel, unsigned long long *simulation_time)
|
_panel_get_registers (PANEL *panel, int calledback, unsigned long long *simulation_time)
|
||||||
{
|
{
|
||||||
if ((!panel) || (panel->State == Error)) {
|
if ((!panel) || (panel->State == Error)) {
|
||||||
sim_panel_set_error ("Invalid Panel");
|
sim_panel_set_error ("Invalid Panel");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (panel->callback) {
|
if ((!calledback) && (panel->callback)) {
|
||||||
sim_panel_set_error ("Callback provides register data");
|
sim_panel_set_error ("Callback provides register data");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1043,11 +1100,18 @@ if (!panel->reg_count) {
|
||||||
sim_panel_set_error ("No registers specified");
|
sim_panel_set_error ("No registers specified");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
pthread_mutex_lock (&panel->io_command_lock);
|
||||||
pthread_mutex_lock (&panel->io_lock);
|
pthread_mutex_lock (&panel->io_lock);
|
||||||
if (panel->reg_query_size != _panel_send (panel, panel->reg_query, panel->reg_query_size)) {
|
if (panel->reg_query_size != _panel_send (panel, panel->reg_query, panel->reg_query_size)) {
|
||||||
pthread_mutex_unlock (&panel->io_lock);
|
pthread_mutex_unlock (&panel->io_lock);
|
||||||
|
pthread_mutex_unlock (&panel->io_command_lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
while (panel->io_reg_query_pending != 0) {
|
||||||
|
pthread_mutex_unlock (&panel->io_lock);
|
||||||
|
msleep (100);
|
||||||
|
pthread_mutex_lock (&panel->io_lock);
|
||||||
|
}
|
||||||
++panel->io_reg_query_pending;
|
++panel->io_reg_query_pending;
|
||||||
panel->io_waiting = 1;
|
panel->io_waiting = 1;
|
||||||
while (panel->io_waiting)
|
while (panel->io_waiting)
|
||||||
|
@ -1055,14 +1119,21 @@ while (panel->io_waiting)
|
||||||
if (simulation_time)
|
if (simulation_time)
|
||||||
*simulation_time = panel->simulation_time;
|
*simulation_time = panel->simulation_time;
|
||||||
pthread_mutex_unlock (&panel->io_lock);
|
pthread_mutex_unlock (&panel->io_lock);
|
||||||
|
pthread_mutex_unlock (&panel->io_command_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sim_panel_set_display_callback (PANEL *panel,
|
sim_panel_get_registers (PANEL *panel, unsigned long long *simulation_time)
|
||||||
|
{
|
||||||
|
return _panel_get_registers (panel, 0, simulation_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sim_panel_set_display_callback_interval (PANEL *panel,
|
||||||
PANEL_DISPLAY_PCALLBACK callback,
|
PANEL_DISPLAY_PCALLBACK callback,
|
||||||
void *context,
|
void *context,
|
||||||
int callbacks_per_second)
|
int usecs_between_callbacks)
|
||||||
{
|
{
|
||||||
if (!panel) {
|
if (!panel) {
|
||||||
sim_panel_set_error ("Invalid Panel");
|
sim_panel_set_error ("Invalid Panel");
|
||||||
|
@ -1071,10 +1142,10 @@ if (!panel) {
|
||||||
pthread_mutex_lock (&panel->io_lock);
|
pthread_mutex_lock (&panel->io_lock);
|
||||||
panel->callback = callback;
|
panel->callback = callback;
|
||||||
panel->callback_context = context;
|
panel->callback_context = context;
|
||||||
if (callbacks_per_second && (0 == panel->callbacks_per_second)) { /* Need to start callbacks */
|
if (usecs_between_callbacks && (0 == panel->usecs_between_callbacks)) { /* Need to start/enable callbacks */
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
|
|
||||||
panel->callbacks_per_second = callbacks_per_second;
|
panel->usecs_between_callbacks = usecs_between_callbacks;
|
||||||
pthread_cond_init (&panel->startup_cond, NULL);
|
pthread_cond_init (&panel->startup_cond, NULL);
|
||||||
pthread_attr_init(&attr);
|
pthread_attr_init(&attr);
|
||||||
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
|
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
|
||||||
|
@ -1084,8 +1155,8 @@ if (callbacks_per_second && (0 == panel->callbacks_per_second)) { /* Need to sta
|
||||||
pthread_cond_wait (&panel->startup_cond, &panel->io_lock); /* Wait for thread to stabilize */
|
pthread_cond_wait (&panel->startup_cond, &panel->io_lock); /* Wait for thread to stabilize */
|
||||||
pthread_cond_destroy (&panel->startup_cond);
|
pthread_cond_destroy (&panel->startup_cond);
|
||||||
}
|
}
|
||||||
if ((callbacks_per_second == 0) && panel->callbacks_per_second) { /* Need to stop callbacks */
|
if ((usecs_between_callbacks == 0) && panel->usecs_between_callbacks) { /* Need to stop callbacks */
|
||||||
panel->callbacks_per_second = 0;
|
panel->usecs_between_callbacks = 0;
|
||||||
pthread_mutex_unlock (&panel->io_lock);
|
pthread_mutex_unlock (&panel->io_lock);
|
||||||
pthread_join (panel->callback_thread, NULL);
|
pthread_join (panel->callback_thread, NULL);
|
||||||
pthread_mutex_lock (&panel->io_lock);
|
pthread_mutex_lock (&panel->io_lock);
|
||||||
|
@ -1127,7 +1198,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, 0, NULL, "BOOT %s\r", device))
|
if (_panel_sendf (panel, NULL, NULL, "BOOT %s\r", device))
|
||||||
return -1;
|
return -1;
|
||||||
panel->State = Run;
|
panel->State = Run;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1148,7 +1219,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, 0, NULL, "CONT\r", 5))
|
if (_panel_sendf (panel, NULL, NULL, "CONT\r", 5))
|
||||||
return -1;
|
return -1;
|
||||||
panel->State = Run;
|
panel->State = Run;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1179,6 +1250,9 @@ return 0;
|
||||||
int
|
int
|
||||||
sim_panel_break_set (PANEL *panel, const char *condition)
|
sim_panel_break_set (PANEL *panel, const char *condition)
|
||||||
{
|
{
|
||||||
|
char *response = NULL;
|
||||||
|
int cmd_stat;
|
||||||
|
|
||||||
if (!panel || (panel->State == Error)) {
|
if (!panel || (panel->State == Error)) {
|
||||||
sim_panel_set_error ("Invalid Panel");
|
sim_panel_set_error ("Invalid Panel");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1192,14 +1266,22 @@ if (panel->State == Run) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_panel_sendf (panel, 1, NULL, "BREAK %s\r", condition))
|
if ((_panel_sendf (panel, &cmd_stat, &response, "BREAK %s\r", condition)) ||
|
||||||
|
(*response)) {
|
||||||
|
sim_panel_set_error ("Error establishing breakpoint at '%s': %s", condition, response ? response : "");
|
||||||
|
free (response);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
free (response);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sim_panel_break_clear (PANEL *panel, const char *condition)
|
sim_panel_break_clear (PANEL *panel, const char *condition)
|
||||||
{
|
{
|
||||||
|
char *response = NULL;
|
||||||
|
int cmd_stat;
|
||||||
|
|
||||||
if (!panel || (panel->State == Error)) {
|
if (!panel || (panel->State == Error)) {
|
||||||
sim_panel_set_error ("Invalid Panel");
|
sim_panel_set_error ("Invalid Panel");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1213,14 +1295,22 @@ if (panel->State == Run) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_panel_sendf (panel, 1, NULL, "NOBREAK %s\r", condition))
|
if ((_panel_sendf (panel, &cmd_stat, &response, "NOBREAK %s\r", condition)) ||
|
||||||
|
(*response)) {
|
||||||
|
sim_panel_set_error ("Error clearing breakpoint at '%s': %s", condition, response ? response : "");
|
||||||
|
free (response);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
free (response);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sim_panel_break_output_set (PANEL *panel, const char *condition)
|
sim_panel_break_output_set (PANEL *panel, const char *condition)
|
||||||
{
|
{
|
||||||
|
char *response = NULL;
|
||||||
|
int cmd_stat;
|
||||||
|
|
||||||
if (!panel || (panel->State == Error)) {
|
if (!panel || (panel->State == Error)) {
|
||||||
sim_panel_set_error ("Invalid Panel");
|
sim_panel_set_error ("Invalid Panel");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1234,14 +1324,22 @@ if (panel->State == Run) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_panel_sendf (panel, 1, NULL, "EXPECT %s\r", condition))
|
if ((_panel_sendf (panel, &cmd_stat, &response, "EXPECT %s\r", condition)) ||
|
||||||
|
(*response)) {
|
||||||
|
sim_panel_set_error ("Error establishing output breakpoint for '%s': %s", condition, response ? response : "");
|
||||||
|
free (response);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
free (response);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sim_panel_break_output_clear (PANEL *panel, const char *condition)
|
sim_panel_break_output_clear (PANEL *panel, const char *condition)
|
||||||
{
|
{
|
||||||
|
char *response = NULL;
|
||||||
|
int cmd_stat;
|
||||||
|
|
||||||
if (!panel || (panel->State == Error)) {
|
if (!panel || (panel->State == Error)) {
|
||||||
sim_panel_set_error ("Invalid Panel");
|
sim_panel_set_error ("Invalid Panel");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1255,8 +1353,13 @@ if (panel->State == Run) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_panel_sendf (panel, 1, NULL, "NOEXPECT %s\r", condition))
|
if ((_panel_sendf (panel, &cmd_stat, &response, "NOEXPECT %s\r", condition)) ||
|
||||||
|
(*response)) {
|
||||||
|
sim_panel_set_error ("Error clearing output breakpoint for '%s': %s", condition, response ? response : "");
|
||||||
|
free (response);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
free (response);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1279,6 +1382,7 @@ sim_panel_gen_examine (PANEL *panel,
|
||||||
{
|
{
|
||||||
char *response = NULL, *c;
|
char *response = NULL, *c;
|
||||||
unsigned long long data = 0;
|
unsigned long long data = 0;
|
||||||
|
int cmd_stat;
|
||||||
|
|
||||||
if (!panel || (panel->State == Error)) {
|
if (!panel || (panel->State == Error)) {
|
||||||
sim_panel_set_error ("Invalid Panel");
|
sim_panel_set_error ("Invalid Panel");
|
||||||
|
@ -1288,7 +1392,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, 1, &response, "EXAMINE -H %s", name_or_addr)) {
|
if (_panel_sendf (panel, &cmd_stat, &response, "EXAMINE -H %s", name_or_addr)) {
|
||||||
free (response);
|
free (response);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1325,6 +1429,7 @@ sim_panel_gen_deposit (PANEL *panel,
|
||||||
const void *value)
|
const void *value)
|
||||||
{
|
{
|
||||||
unsigned long long data = 0;
|
unsigned long long data = 0;
|
||||||
|
int cmd_stat;
|
||||||
|
|
||||||
if (!panel || (panel->State == Error)) {
|
if (!panel || (panel->State == Error)) {
|
||||||
sim_panel_set_error ("Invalid Panel");
|
sim_panel_set_error ("Invalid Panel");
|
||||||
|
@ -1338,7 +1443,7 @@ if (little_endian)
|
||||||
memcpy (&data, value, size);
|
memcpy (&data, value, size);
|
||||||
else
|
else
|
||||||
memcpy (((char *)&data) + sizeof(data)-size, value, size);
|
memcpy (((char *)&data) + sizeof(data)-size, value, size);
|
||||||
if (_panel_sendf (panel, 1, NULL, "DEPOSIT -H %s %llx", name_or_addr, data))
|
if (_panel_sendf (panel, &cmd_stat, NULL, "DEPOSIT -H %s %llx", name_or_addr, data))
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1367,6 +1472,7 @@ sim_panel_mem_examine (PANEL *panel,
|
||||||
{
|
{
|
||||||
char *response = NULL, *c;
|
char *response = NULL, *c;
|
||||||
unsigned long long data = 0, address = 0;
|
unsigned long long data = 0, address = 0;
|
||||||
|
int cmd_stat;
|
||||||
|
|
||||||
if (!panel || (panel->State == Error)) {
|
if (!panel || (panel->State == Error)) {
|
||||||
sim_panel_set_error ("Invalid Panel");
|
sim_panel_set_error ("Invalid Panel");
|
||||||
|
@ -1380,7 +1486,7 @@ if (little_endian)
|
||||||
memcpy (&address, addr, addr_size);
|
memcpy (&address, addr, addr_size);
|
||||||
else
|
else
|
||||||
memcpy (((char *)&address) + sizeof(address)-addr_size, addr, addr_size);
|
memcpy (((char *)&address) + sizeof(address)-addr_size, addr, addr_size);
|
||||||
if (_panel_sendf (panel, 1, &response, (panel->radix == 16) ? "EXAMINE -H %llx" : "EXAMINE -H %llo", address)) {
|
if (_panel_sendf (panel, &cmd_stat, &response, (panel->radix == 16) ? "EXAMINE -H %llx" : "EXAMINE -H %llo", address)) {
|
||||||
free (response);
|
free (response);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1422,6 +1528,7 @@ sim_panel_mem_deposit (PANEL *panel,
|
||||||
const void *value)
|
const void *value)
|
||||||
{
|
{
|
||||||
unsigned long long data = 0, address = 0;
|
unsigned long long data = 0, address = 0;
|
||||||
|
int cmd_stat;
|
||||||
|
|
||||||
if (!panel || (panel->State == Error)) {
|
if (!panel || (panel->State == Error)) {
|
||||||
sim_panel_set_error ("Invalid Panel");
|
sim_panel_set_error ("Invalid Panel");
|
||||||
|
@ -1439,7 +1546,7 @@ else {
|
||||||
memcpy (((char *)&data) + sizeof(data)-value_size, value, value_size);
|
memcpy (((char *)&data) + sizeof(data)-value_size, value, value_size);
|
||||||
memcpy (((char *)&address) + sizeof(address)-addr_size, addr, addr_size);
|
memcpy (((char *)&address) + sizeof(address)-addr_size, addr, addr_size);
|
||||||
}
|
}
|
||||||
if (_panel_sendf (panel, 1, NULL, (panel->radix == 16) ? "DEPOSIT -H %llx %llx" : "DEPOSIT -H %llo %llx", address, data))
|
if (_panel_sendf (panel, &cmd_stat, NULL, (panel->radix == 16) ? "DEPOSIT -H %llx %llx" : "DEPOSIT -H %llo %llx", address, data))
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1460,6 +1567,8 @@ sim_panel_set_register_value (PANEL *panel,
|
||||||
const char *name,
|
const char *name,
|
||||||
const char *value)
|
const char *value)
|
||||||
{
|
{
|
||||||
|
int cmd_stat;
|
||||||
|
|
||||||
if (!panel || (panel->State == Error)) {
|
if (!panel || (panel->State == Error)) {
|
||||||
sim_panel_set_error ("Invalid Panel");
|
sim_panel_set_error ("Invalid Panel");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1468,7 +1577,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, 1, NULL, "DEPOSIT %s %s", name, value))
|
if (_panel_sendf (panel, &cmd_stat, NULL, "DEPOSIT %s %s", name, value))
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1487,30 +1596,42 @@ sim_panel_mount (PANEL *panel,
|
||||||
const char *switches,
|
const char *switches,
|
||||||
const char *path)
|
const char *path)
|
||||||
{
|
{
|
||||||
char *response = NULL, *status = NULL;
|
char *response = NULL;
|
||||||
|
OperationalState OrigState;
|
||||||
|
int stat = 0;
|
||||||
|
int cmd_stat;
|
||||||
|
|
||||||
if (!panel || (panel->State == Error)) {
|
if (!panel || (panel->State == Error)) {
|
||||||
sim_panel_set_error ("Invalid Panel");
|
sim_panel_set_error ("Invalid Panel");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (_panel_sendf (panel, 1, &response, "ATTACH %s %s %s", switches, device, path)) {
|
pthread_mutex_lock (&panel->io_lock);
|
||||||
free (response);
|
OrigState = panel->State;
|
||||||
return -1;
|
if (OrigState == Run) {
|
||||||
|
sim_panel_exec_halt (panel);
|
||||||
|
while (panel->State == Run) {
|
||||||
|
pthread_mutex_unlock (&panel->io_lock);
|
||||||
|
msleep (100);
|
||||||
|
pthread_mutex_lock (&panel->io_lock);
|
||||||
}
|
}
|
||||||
if (_panel_sendf (panel, 1, &status, "ECHO %%STATUS%%")) {
|
|
||||||
free (response);
|
|
||||||
free (status);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
if (!status || (strcmp (status, "00000000\r\n"))) {
|
pthread_mutex_unlock (&panel->io_lock);
|
||||||
|
do {
|
||||||
|
if (_panel_sendf (panel, &cmd_stat, &response, "ATTACH %s %s %s", switches, device, path)) {
|
||||||
|
stat = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (cmd_stat) {
|
||||||
sim_panel_set_error (response);
|
sim_panel_set_error (response);
|
||||||
free (response);
|
stat = -1;
|
||||||
free (status);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
} while (0);
|
||||||
|
pthread_mutex_lock (&panel->io_lock);
|
||||||
|
if (OrigState == Run)
|
||||||
|
sim_panel_exec_run (panel);
|
||||||
|
pthread_mutex_unlock (&panel->io_lock);
|
||||||
free (response);
|
free (response);
|
||||||
free (status);
|
return stat;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1523,30 +1644,42 @@ int
|
||||||
sim_panel_dismount (PANEL *panel,
|
sim_panel_dismount (PANEL *panel,
|
||||||
const char *device)
|
const char *device)
|
||||||
{
|
{
|
||||||
char *response = NULL, *status = NULL;
|
char *response = NULL;
|
||||||
|
OperationalState OrigState;
|
||||||
|
int stat = 0;
|
||||||
|
int cmd_stat;
|
||||||
|
|
||||||
if (!panel || (panel->State == Error)) {
|
if (!panel || (panel->State == Error)) {
|
||||||
sim_panel_set_error ("Invalid Panel");
|
sim_panel_set_error ("Invalid Panel");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (_panel_sendf (panel, 1, &response, "DETACH %s", device)) {
|
pthread_mutex_lock (&panel->io_lock);
|
||||||
free (response);
|
OrigState = panel->State;
|
||||||
return -1;
|
if (OrigState == Run) {
|
||||||
|
sim_panel_exec_halt (panel);
|
||||||
|
while (panel->State == Run) {
|
||||||
|
pthread_mutex_unlock (&panel->io_lock);
|
||||||
|
msleep (100);
|
||||||
|
pthread_mutex_lock (&panel->io_lock);
|
||||||
}
|
}
|
||||||
if (_panel_sendf (panel, 1, &status, "ECHO %%STATUS%%")) {
|
|
||||||
free (response);
|
|
||||||
free (status);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
if (!status || (strcmp (status, "00000000\r\n"))) {
|
pthread_mutex_unlock (&panel->io_lock);
|
||||||
|
do {
|
||||||
|
if (_panel_sendf (panel, &cmd_stat, &response, "DETACH %s", device)) {
|
||||||
|
stat = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (cmd_stat) {
|
||||||
sim_panel_set_error (response);
|
sim_panel_set_error (response);
|
||||||
free (response);
|
stat = -1;
|
||||||
free (status);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
} while (0);
|
||||||
|
pthread_mutex_lock (&panel->io_lock);
|
||||||
|
if (OrigState == Run)
|
||||||
|
sim_panel_exec_run (panel);
|
||||||
|
pthread_mutex_unlock (&panel->io_lock);
|
||||||
free (response);
|
free (response);
|
||||||
free (status);
|
return stat;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1683,8 +1816,7 @@ while ((p->sock != INVALID_SOCKET) &&
|
||||||
else {
|
else {
|
||||||
size_t name_len = strlen (p->regs[i].name);
|
size_t name_len = strlen (p->regs[i].name);
|
||||||
|
|
||||||
if ((0 == memcmp (p->regs[i].name, s, name_len), s) &&
|
if ((0 == memcmp (p->regs[i].name, s, name_len)) && (s[name_len] == '[')) {
|
||||||
(s[name_len] == '[')) {
|
|
||||||
size_t array_index = (size_t)atoi (s + name_len + 1);
|
size_t array_index = (size_t)atoi (s + name_len + 1);
|
||||||
size_t end_index = array_index;
|
size_t end_index = array_index;
|
||||||
char *end = strchr (s + name_len + 1, '[');
|
char *end = strchr (s + name_len + 1, '[');
|
||||||
|
@ -1714,22 +1846,23 @@ while ((p->sock != INVALID_SOCKET) &&
|
||||||
*e = ':';
|
*e = ':';
|
||||||
/* Unexpected Register Data Found (or other output containing a : character) */
|
/* Unexpected Register Data Found (or other output containing a : character) */
|
||||||
}
|
}
|
||||||
if (!strcmp (s + strlen (sim_prompt), register_get_echo)) {
|
if (!strcmp (s + strlen (sim_prompt), register_repeat_echo)) {
|
||||||
pthread_mutex_lock (&p->io_lock);
|
|
||||||
--p->io_reg_query_pending;
|
|
||||||
if (p->callback) {
|
if (p->callback) {
|
||||||
pthread_mutex_unlock (&p->io_lock);
|
pthread_mutex_unlock (&p->io_lock);
|
||||||
p->callback (p, p->simulation_time, p->callback_context);
|
p->callback (p, p->simulation_time, p->callback_context);
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
|
if (!strcmp (s + strlen (sim_prompt), register_get_echo)) {
|
||||||
|
pthread_mutex_lock (&p->io_lock);
|
||||||
|
--p->io_reg_query_pending;
|
||||||
p->io_waiting = 0;
|
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);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
pthread_mutex_lock (&p->io_lock);
|
pthread_mutex_lock (&p->io_lock);
|
||||||
if (!strcmp (s + strlen (sim_prompt), command_done_echo)) {
|
if (!strcmp (s + strlen (sim_prompt), command_done_echo)) {
|
||||||
|
_panel_debug (p, DBG_RCV, "Received Command Complete", NULL, 0);
|
||||||
p->io_waiting = 0;
|
p->io_waiting = 0;
|
||||||
pthread_cond_signal (&p->io_done);
|
pthread_cond_signal (&p->io_done);
|
||||||
}
|
}
|
||||||
|
@ -1751,11 +1884,14 @@ while ((p->sock != INVALID_SOCKET) &&
|
||||||
p->io_response = t;
|
p->io_response = t;
|
||||||
p->io_response_size = p->io_response_data + strlen (s) + 3;
|
p->io_response_size = p->io_response_data + strlen (s) + 3;
|
||||||
}
|
}
|
||||||
|
_panel_debug (p, DBG_RCV, "Receive Data Accumulated: '%s'", NULL, 0, s);
|
||||||
strcpy (p->io_response + p->io_response_data, s);
|
strcpy (p->io_response + p->io_response_data, s);
|
||||||
p->io_response_data += strlen(s);
|
p->io_response_data += strlen(s);
|
||||||
strcpy (p->io_response + p->io_response_data, "\r\n");
|
strcpy (p->io_response + p->io_response_data, "\r\n");
|
||||||
p->io_response_data += 2;
|
p->io_response_data += 2;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
_panel_debug (p, DBG_RCV, "Receive Data Discarded: '%s'", NULL, 0, s);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock (&p->io_lock);
|
pthread_mutex_unlock (&p->io_lock);
|
||||||
}
|
}
|
||||||
|
@ -1794,6 +1930,7 @@ struct sched_param sched_priority;
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
size_t buf_data = 0;
|
size_t buf_data = 0;
|
||||||
unsigned int callback_count = 0;
|
unsigned int callback_count = 0;
|
||||||
|
int cmd_stat;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Boost Priority for timer thread so it doesn't compete
|
Boost Priority for timer thread so it doesn't compete
|
||||||
|
@ -1810,31 +1947,78 @@ pthread_cond_signal (&p->startup_cond); /* Signal we're ready to go */
|
||||||
msleep (100);
|
msleep (100);
|
||||||
pthread_mutex_lock (&p->io_lock);
|
pthread_mutex_lock (&p->io_lock);
|
||||||
while ((p->sock != INVALID_SOCKET) &&
|
while ((p->sock != INVALID_SOCKET) &&
|
||||||
(p->callbacks_per_second) &&
|
(p->usecs_between_callbacks) &&
|
||||||
(p->State != Error)) {
|
(p->State != Error)) {
|
||||||
int rate = p->callbacks_per_second;
|
int interval = p->usecs_between_callbacks;
|
||||||
|
int new_register = p->new_register;
|
||||||
|
|
||||||
|
p->new_register = 0;
|
||||||
pthread_mutex_unlock (&p->io_lock);
|
pthread_mutex_unlock (&p->io_lock);
|
||||||
|
|
||||||
++callback_count;
|
if (new_register) /* need to get and send updated register info */
|
||||||
if (1 == callback_count%rate) { /* once a second update the query string */
|
|
||||||
_panel_register_query_string (p, &buf, &buf_data);
|
_panel_register_query_string (p, &buf, &buf_data);
|
||||||
}
|
|
||||||
msleep (1000/rate);
|
/* twice a second activities: */
|
||||||
|
/* 1) update the query string if it has changed */
|
||||||
|
/* (only really happens at startup) */
|
||||||
|
/* 2) update register state by polling if the simulator is halted */
|
||||||
|
msleep (500);
|
||||||
pthread_mutex_lock (&p->io_lock);
|
pthread_mutex_lock (&p->io_lock);
|
||||||
if (((p->State == Run) || ((p->State == Halt) && (0 == callback_count%(5*rate)))) &&
|
if (new_register) {
|
||||||
(p->io_reg_query_pending == 0)) {
|
if (p->io_reg_query_pending == 0) {
|
||||||
++p->io_reg_query_pending;
|
size_t repeat_data = strlen (register_repeat_prefix) + /* prefix */
|
||||||
|
20 + /* max int width */
|
||||||
|
strlen (register_repeat_units) + /* units and spacing */
|
||||||
|
buf_data + /* command contents */
|
||||||
|
1 + /* carriage return */
|
||||||
|
strlen (register_repeat_echo) + /* auto repeat completion */
|
||||||
|
1 + /* carriage return */
|
||||||
|
1; /* NUL */
|
||||||
|
char *repeat = (char *)malloc (repeat_data);
|
||||||
|
char *c;
|
||||||
|
|
||||||
|
sprintf (repeat, "%s%d%s%*.*s", register_repeat_prefix,
|
||||||
|
p->usecs_between_callbacks,
|
||||||
|
register_repeat_units,
|
||||||
|
(int)buf_data, (int)buf_data, buf);
|
||||||
pthread_mutex_unlock (&p->io_lock);
|
pthread_mutex_unlock (&p->io_lock);
|
||||||
if (buf_data != _panel_send (p, buf, buf_data)) {
|
for (c = strchr (repeat, '\r'); c != NULL; c = strchr (c, '\r'))
|
||||||
|
*c = ';'; /* replace carriage returns with semicolons */
|
||||||
|
c = strstr (repeat, register_get_echo); /* remove register_done_echo string and */
|
||||||
|
strcpy (c, register_repeat_echo); /* replace it with the register_repeat_echo string */
|
||||||
|
if (_panel_sendf (p, &cmd_stat, NULL, "%s", repeat)) {
|
||||||
|
pthread_mutex_lock (&p->io_lock);
|
||||||
|
free (repeat);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pthread_mutex_lock (&p->io_lock);
|
||||||
|
free (repeat);
|
||||||
|
}
|
||||||
|
else { /* already busy */
|
||||||
|
p->new_register = 1; /* retry later */
|
||||||
|
_panel_debug (p, DBG_XMT, "Waiting on prior command completion before specifying repeat interval", NULL, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* when halted, we directly poll the halted system to get updated */
|
||||||
|
/* register state which may have changed due to panel activities */
|
||||||
|
if (p->State == Halt) {
|
||||||
|
pthread_mutex_unlock (&p->io_lock);
|
||||||
|
if (_panel_get_registers (p, 1, NULL)) {
|
||||||
pthread_mutex_lock (&p->io_lock);
|
pthread_mutex_lock (&p->io_lock);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pthread_mutex_lock (&p->io_lock);
|
pthread_mutex_lock (&p->io_lock);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
_panel_debug (p, DBG_XMT, "Waiting for prior register query completion", NULL, 0);
|
|
||||||
}
|
}
|
||||||
|
pthread_mutex_unlock (&p->io_lock);
|
||||||
|
/* stop any established repeating activity in the simulator */
|
||||||
|
if (p->parent == NULL) /* Top level panel? */
|
||||||
|
_panel_sendf (p, &cmd_stat, NULL, "%s", register_repeat_stop_all);
|
||||||
|
else {
|
||||||
|
if (p->State == Run)
|
||||||
|
_panel_sendf (p, &cmd_stat, NULL, "%s", register_repeat_stop);
|
||||||
|
}
|
||||||
|
pthread_mutex_lock (&p->io_lock);
|
||||||
p->callback_thread_running = 0;
|
p->callback_thread_running = 0;
|
||||||
pthread_mutex_unlock (&p->io_lock);
|
pthread_mutex_unlock (&p->io_lock);
|
||||||
free (buf);
|
free (buf);
|
||||||
|
@ -1905,13 +2089,13 @@ return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_panel_sendf (PANEL *p, int wait_for_completion, char **response, const char *fmt, ...)
|
_panel_sendf (PANEL *p, int *completion_status, char **response, 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, status_echo_len = 0;
|
||||||
int post_fix_len = wait_for_completion ? 5 + strlen (command_done_echo): 1;
|
int post_fix_len = completion_status ? 7 + sizeof (command_done_echo) + sizeof (command_status) : 1;
|
||||||
va_list arglist;
|
va_list arglist;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -1938,20 +2122,23 @@ while (1) { /* format passed string, arg
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len && (buf[len-1] != '\r')) {
|
if (len && (buf[len-1] != '\r')) {
|
||||||
strcat (buf, "\r"); /* Make sure command line is terminated */
|
strcpy (&buf[len], "\r"); /* Make sure command line is terminated */
|
||||||
++len;
|
++len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wait_for_completion) {
|
pthread_mutex_lock (&p->io_command_lock);
|
||||||
strcat (buf, command_done_echo);
|
++p->command_count;
|
||||||
strcat (buf, "\r");
|
if (completion_status) {
|
||||||
|
sprintf (&buf[len], "%s\r%s\r", command_status, command_done_echo);
|
||||||
|
status_echo_len = strlen (&buf[len]);
|
||||||
pthread_mutex_lock (&p->io_lock);
|
pthread_mutex_lock (&p->io_lock);
|
||||||
p->io_response_data = 0;
|
p->io_response_data = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = (strlen (buf) == _panel_send (p, buf, strlen (buf))) ? 0 : -1;
|
_panel_debug (p, DBG_REQ, "Command %d Request%s: %*.*s", NULL, 0, p->command_count, completion_status ? " (with response)" : "", len, len, buf);
|
||||||
|
ret = ((len + status_echo_len) == _panel_send (p, buf, len + status_echo_len)) ? 0 : -1;
|
||||||
|
|
||||||
if (wait_for_completion) {
|
if (completion_status) {
|
||||||
if (!ret) { /* Sent OK? */
|
if (!ret) { /* Sent OK? */
|
||||||
p->io_waiting = 1;
|
p->io_waiting = 1;
|
||||||
while (p->io_waiting)
|
while (p->io_waiting)
|
||||||
|
@ -1959,16 +2146,33 @@ if (wait_for_completion) {
|
||||||
if (response) {
|
if (response) {
|
||||||
*response = (char *)_panel_malloc (p->io_response_data + 1);
|
*response = (char *)_panel_malloc (p->io_response_data + 1);
|
||||||
if (0 == memcmp (buf, p->io_response + strlen (sim_prompt), len)) {
|
if (0 == memcmp (buf, p->io_response + strlen (sim_prompt), len)) {
|
||||||
|
char *eol, *status;
|
||||||
memcpy (*response, p->io_response + strlen (sim_prompt) + len + 1, p->io_response_data + 1 - (strlen (sim_prompt) + len + 1));
|
memcpy (*response, p->io_response + strlen (sim_prompt) + len + 1, p->io_response_data + 1 - (strlen (sim_prompt) + len + 1));
|
||||||
|
*completion_status = -1;
|
||||||
|
status = strstr (*response, command_status);
|
||||||
|
if (status) {
|
||||||
|
*(status - strlen (sim_prompt)) = '\0';
|
||||||
|
status += strlen (command_status) + 2;
|
||||||
|
eol = strchr (status, '\r');
|
||||||
|
if (eol)
|
||||||
|
*eol = '\0';
|
||||||
|
sscanf (status, "Status:%08X-", completion_status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
memcpy (*response, p->io_response, p->io_response_data + 1);
|
memcpy (*response, p->io_response, p->io_response_data + 1);
|
||||||
|
_panel_debug (p, DBG_RSP, "Command %d Response(Status=%d): '%s'", NULL, 0, p->command_count, *completion_status, *response);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (p->io_response_data)
|
||||||
|
_panel_debug (p, DBG_RSP, "Discarded Unwanted Command %d Response Data:", p->io_response, p->io_response_data, p->command_count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
p->io_response_data = 0;
|
p->io_response_data = 0;
|
||||||
p->io_response[0] = '\0';
|
p->io_response[0] = '\0';
|
||||||
}
|
|
||||||
pthread_mutex_unlock (&p->io_lock);
|
pthread_mutex_unlock (&p->io_lock);
|
||||||
}
|
}
|
||||||
|
pthread_mutex_unlock (&p->io_command_lock);
|
||||||
|
|
||||||
if (buf != stackbuf)
|
if (buf != stackbuf)
|
||||||
free (buf);
|
free (buf);
|
||||||
|
|
|
@ -57,7 +57,7 @@ extern "C" {
|
||||||
|
|
||||||
#if !defined(__VAX) /* Unsupported platform */
|
#if !defined(__VAX) /* Unsupported platform */
|
||||||
|
|
||||||
#define SIM_FRONTPANEL_VERSION 2
|
#define SIM_FRONTPANEL_VERSION 3
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ sim_panel_destroy (PANEL *panel);
|
||||||
simulator.
|
simulator.
|
||||||
|
|
||||||
The registers that a particular frontpanel application mught need
|
The registers that a particular frontpanel application mught need
|
||||||
access to are described by the application by calling:
|
access to are described by the application when it calls:
|
||||||
|
|
||||||
sim_panel_add_register
|
sim_panel_add_register
|
||||||
sim_panel_add_register_array
|
sim_panel_add_register_array
|
||||||
|
@ -175,10 +175,10 @@ sim_panel_add_register_indirect (PANEL *panel,
|
||||||
|
|
||||||
1) The values can be polled (when ever it is desired) by calling
|
1) The values can be polled (when ever it is desired) by calling
|
||||||
sim_panel_get_registers().
|
sim_panel_get_registers().
|
||||||
2) The panel can call sim_panel_set_display_callback() to specify a
|
2) The panel can call sim_panel_set_display_callback_interval() to
|
||||||
callback routine and a periodic rate that the callback routine
|
specify a callback routine and a periodic rate that the callback
|
||||||
should be called. The panel API will make a best effort to deliver
|
routine should be called. The panel API will make a best effort
|
||||||
the current register state at the desired rate.
|
to deliver the current register state at the desired rate.
|
||||||
|
|
||||||
|
|
||||||
Note 1: The buffers described in a panel's register set will be
|
Note 1: The buffers described in a panel's register set will be
|
||||||
|
@ -203,10 +203,10 @@ typedef void (*PANEL_DISPLAY_PCALLBACK)(PANEL *panel,
|
||||||
void *context);
|
void *context);
|
||||||
|
|
||||||
int
|
int
|
||||||
sim_panel_set_display_callback (PANEL *panel,
|
sim_panel_set_display_callback_interval (PANEL *panel,
|
||||||
PANEL_DISPLAY_PCALLBACK callback,
|
PANEL_DISPLAY_PCALLBACK callback,
|
||||||
void *context,
|
void *context,
|
||||||
int callbacks_per_second);
|
int usecs_between_callbacks);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
|
@ -450,6 +450,8 @@ sim_panel_set_debug_file (PANEL *panel, const char *debug_file);
|
||||||
|
|
||||||
#define DBG_XMT 1 /* Transmit Data */
|
#define DBG_XMT 1 /* Transmit Data */
|
||||||
#define DBG_RCV 2 /* Receive Data */
|
#define DBG_RCV 2 /* Receive Data */
|
||||||
|
#define DBG_REQ 4 /* Request Data */
|
||||||
|
#define DBG_RSP 8 /* Response Data */
|
||||||
|
|
||||||
void
|
void
|
||||||
sim_panel_set_debug_mode (PANEL *panel, int debug_bits);
|
sim_panel_set_debug_mode (PANEL *panel, int debug_bits);
|
||||||
|
|
Loading…
Add table
Reference in a new issue