mirror of
https://github.com/open-simh/simh.git
synced 2026-05-04 15:16:06 +00:00
FRONTPANEL: Merged simulator panel and device panel constructors.
This commit is contained in:
334
sim_frontpanel.c
334
sim_frontpanel.c
@@ -445,108 +445,125 @@ for (i=0; i<panel_count; i++) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PANEL *
|
static PANEL *
|
||||||
sim_panel_start_simulator (const char *sim_path,
|
_sim_panel_create (const char *sim_path,
|
||||||
const char *sim_config,
|
const char *sim_config,
|
||||||
size_t device_panel_count)
|
size_t device_panel_count,
|
||||||
{
|
PANEL *simulator_panel,
|
||||||
return sim_panel_start_simulator_debug (sim_path, sim_config, device_panel_count, NULL);
|
const char *device_name,
|
||||||
}
|
const char *debug_file)
|
||||||
|
|
||||||
PANEL *
|
|
||||||
sim_panel_start_simulator_debug (const char *sim_path,
|
|
||||||
const char *sim_config,
|
|
||||||
size_t device_panel_count,
|
|
||||||
const char *debug_file)
|
|
||||||
{
|
{
|
||||||
PANEL *p = NULL;
|
PANEL *p = NULL;
|
||||||
FILE *fIn = NULL;
|
FILE *fIn = NULL;
|
||||||
FILE *fOut = NULL;
|
FILE *fOut = NULL;
|
||||||
struct stat statb;
|
struct stat statb;
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
int port, i;
|
int port;
|
||||||
|
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;
|
||||||
|
|
||||||
end_test.i = 1; /* test endian-ness */
|
if (simulator_panel) {
|
||||||
little_endian = (end_test.c[0] != 0);
|
for (device_num=0; device_num < simulator_panel->device_count; ++device_num)
|
||||||
sim_init_sock ();
|
if (simulator_panel->devices[device_num] == NULL)
|
||||||
for (port=1024; port < 2048; port++) {
|
|
||||||
SOCKET sock;
|
|
||||||
|
|
||||||
sprintf (hostport, "%d", port);
|
|
||||||
sock = sim_connect_sock_ex (NULL, hostport, NULL, NULL, SIM_SOCK_OPT_NODELAY | SIM_SOCK_OPT_BLOCKING);
|
|
||||||
if (sock != INVALID_SOCKET) {
|
|
||||||
int sta = 0;
|
|
||||||
while (!sta) {
|
|
||||||
msleep (10);
|
|
||||||
sta = sim_check_conn (sock, 1);
|
|
||||||
}
|
|
||||||
sim_close_sock (sock);
|
|
||||||
if (sta == -1)
|
|
||||||
break;
|
break;
|
||||||
|
if (device_num == simulator_panel->device_count) {
|
||||||
|
sim_panel_set_error ("No free panel devices slots available %s simulator. All %d slots are used.", simulator_panel->path, (int)simulator_panel->device_count);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
else
|
p = (PANEL *)_panel_malloc (sizeof(*p));
|
||||||
break;
|
if (p == NULL)
|
||||||
|
goto Error_Return;
|
||||||
|
memset (p, 0, sizeof(*p));
|
||||||
|
p->device_name = (char *)_panel_malloc (1 + strlen (device_name));
|
||||||
|
if (p->device_name == NULL)
|
||||||
|
goto Error_Return;
|
||||||
|
strcpy (p->device_name, device_name);
|
||||||
|
p->parent = simulator_panel;
|
||||||
|
strcpy (p->hostport, simulator_panel->hostport);
|
||||||
|
p->sock = INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
if (stat (sim_config, &statb) < 0) {
|
else {
|
||||||
sim_panel_set_error ("Can't stat simulator configuration '%s': %s", sim_config, strerror(errno));
|
end_test.i = 1; /* test endian-ness */
|
||||||
goto Error_Return;
|
little_endian = (end_test.c[0] != 0);
|
||||||
|
sim_init_sock ();
|
||||||
|
for (port=1024; port < 2048; port++) {
|
||||||
|
SOCKET sock;
|
||||||
|
|
||||||
|
sprintf (hostport, "%d", port);
|
||||||
|
sock = sim_connect_sock_ex (NULL, hostport, NULL, NULL, SIM_SOCK_OPT_NODELAY | SIM_SOCK_OPT_BLOCKING);
|
||||||
|
if (sock != INVALID_SOCKET) {
|
||||||
|
int sta = 0;
|
||||||
|
while (!sta) {
|
||||||
|
msleep (10);
|
||||||
|
sta = sim_check_conn (sock, 1);
|
||||||
|
}
|
||||||
|
sim_close_sock (sock);
|
||||||
|
if (sta == -1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
if (stat (sim_config, &statb) < 0) {
|
||||||
|
sim_panel_set_error ("Can't stat simulator configuration '%s': %s", sim_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';
|
||||||
|
p = (PANEL *)_panel_malloc (sizeof(*p));
|
||||||
|
if (p == NULL)
|
||||||
|
goto Error_Return;
|
||||||
|
memset (p, 0, sizeof(*p));
|
||||||
|
p->sock = INVALID_SOCKET;
|
||||||
|
p->path = (char *)_panel_malloc (strlen (sim_path) + 1);
|
||||||
|
if (p->path == NULL)
|
||||||
|
goto Error_Return;
|
||||||
|
strcpy (p->path, sim_path);
|
||||||
|
p->config = (char *)_panel_malloc (strlen (sim_config) + 1);
|
||||||
|
if (p->config == NULL)
|
||||||
|
goto Error_Return;
|
||||||
|
strcpy (p->config, sim_config);
|
||||||
|
fIn = fopen (sim_config, "r");
|
||||||
|
if (fIn == NULL) {
|
||||||
|
sim_panel_set_error ("Can't open configuration file '%s': %s", sim_config, strerror(errno));
|
||||||
|
goto Error_Return;
|
||||||
|
}
|
||||||
|
p->temp_config = (char *)_panel_malloc (strlen (sim_config) + 40);
|
||||||
|
if (p->temp_config == NULL)
|
||||||
|
goto Error_Return;
|
||||||
|
sprintf (p->temp_config, "%s-Panel-%d", sim_config, getpid());
|
||||||
|
fOut = fopen (p->temp_config, "w");
|
||||||
|
if (fOut == NULL) {
|
||||||
|
sim_panel_set_error ("Can't create temporary configuration file '%s': %s", p->temp_config, strerror(errno));
|
||||||
|
goto Error_Return;
|
||||||
|
}
|
||||||
|
fprintf (fOut, "# Temporary FrontPanel generated simh configuration file\n");
|
||||||
|
fprintf (fOut, "# Original Configuration File: %s\n", p->config);
|
||||||
|
fprintf (fOut, "# Simulator Path: %s\n", sim_path);
|
||||||
|
while (fgets (buf, statb.st_size, fIn))
|
||||||
|
fputs (buf, fOut);
|
||||||
|
free (buf);
|
||||||
|
buf = NULL;
|
||||||
|
fclose (fIn);
|
||||||
|
fIn = NULL;
|
||||||
|
fprintf (fOut, "set remote notelnet\n");
|
||||||
|
if (device_panel_count)
|
||||||
|
fprintf (fOut, "set remote connections=%d\n", (int)device_panel_count+1);
|
||||||
|
fprintf (fOut, "set remote -u telnet=%s\n", hostport);
|
||||||
|
fprintf (fOut, "set remote master\n");
|
||||||
|
fclose (fOut);
|
||||||
|
fOut = NULL;
|
||||||
}
|
}
|
||||||
buf = (char *)_panel_malloc (statb.st_size+1);
|
|
||||||
if (buf == NULL)
|
|
||||||
goto Error_Return;
|
|
||||||
buf[statb.st_size] = '\0';
|
|
||||||
p = (PANEL *)_panel_malloc (sizeof(*p));
|
|
||||||
if (p == NULL)
|
|
||||||
goto Error_Return;
|
|
||||||
memset (p, 0, sizeof(*p));
|
|
||||||
p->sock = INVALID_SOCKET;
|
|
||||||
p->path = (char *)_panel_malloc (strlen (sim_path) + 1);
|
|
||||||
if (p->path == NULL)
|
|
||||||
goto Error_Return;
|
|
||||||
strcpy (p->path, sim_path);
|
|
||||||
p->config = (char *)_panel_malloc (strlen (sim_config) + 1);
|
|
||||||
if (p->config == NULL)
|
|
||||||
goto Error_Return;
|
|
||||||
strcpy (p->config, sim_config);
|
|
||||||
fIn = fopen (sim_config, "r");
|
|
||||||
if (fIn == NULL) {
|
|
||||||
sim_panel_set_error ("Can't open configuration file '%s': %s", sim_config, strerror(errno));
|
|
||||||
goto Error_Return;
|
|
||||||
}
|
|
||||||
p->temp_config = (char *)_panel_malloc (strlen (sim_config) + 40);
|
|
||||||
if (p->temp_config == NULL)
|
|
||||||
goto Error_Return;
|
|
||||||
sprintf (p->temp_config, "%s-Panel-%d", sim_config, getpid());
|
|
||||||
fOut = fopen (p->temp_config, "w");
|
|
||||||
if (fOut == NULL) {
|
|
||||||
sim_panel_set_error ("Can't create temporary configuration file '%s': %s", p->temp_config, strerror(errno));
|
|
||||||
goto Error_Return;
|
|
||||||
}
|
|
||||||
fprintf (fOut, "# Temporary FrontPanel generated simh configuration file\n");
|
|
||||||
fprintf (fOut, "# Original Configuration File: %s\n", p->config);
|
|
||||||
fprintf (fOut, "# Simulator Path: %s\n", sim_path);
|
|
||||||
while (fgets (buf, statb.st_size, fIn))
|
|
||||||
fputs (buf, fOut);
|
|
||||||
free (buf);
|
|
||||||
buf = NULL;
|
|
||||||
fclose (fIn);
|
|
||||||
fIn = NULL;
|
|
||||||
fprintf (fOut, "set remote notelnet\n");
|
|
||||||
if (device_panel_count)
|
|
||||||
fprintf (fOut, "set remote connections=%d\n", (int)device_panel_count+1);
|
|
||||||
fprintf (fOut, "set remote -u telnet=%s\n", hostport);
|
|
||||||
fprintf (fOut, "set remote master\n");
|
|
||||||
fclose (fOut);
|
|
||||||
fOut = NULL;
|
|
||||||
if (debug_file) {
|
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 (1) {
|
if (!simulator_panel) {
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
char cmd[2048];
|
char cmd[2048];
|
||||||
PROCESS_INFORMATION ProcessInfo;
|
PROCESS_INFORMATION ProcessInfo;
|
||||||
@@ -584,23 +601,28 @@ if (1) {
|
|||||||
goto Error_Return;
|
goto Error_Return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
strcpy (p->hostport, hostport);
|
||||||
}
|
}
|
||||||
for (i=0; i<100; i++) { /* Allow up to 10 seconds waiting for simulator to start up */
|
for (i=0; i<100; i++) { /* Allow up to 10 seconds waiting for simulator to start up */
|
||||||
p->sock = sim_connect_sock_ex (NULL, hostport, NULL, NULL, SIM_SOCK_OPT_NODELAY | SIM_SOCK_OPT_BLOCKING);
|
p->sock = sim_connect_sock_ex (NULL, p->hostport, NULL, NULL, SIM_SOCK_OPT_NODELAY | SIM_SOCK_OPT_BLOCKING);
|
||||||
if (p->sock == INVALID_SOCKET)
|
if (p->sock == INVALID_SOCKET)
|
||||||
msleep (100);
|
msleep (100);
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (p->sock == INVALID_SOCKET) {
|
if (p->sock == INVALID_SOCKET) {
|
||||||
if (stat (sim_path, &statb) < 0)
|
if (simulator_panel) {
|
||||||
sim_panel_set_error ("Can't stat simulator '%s': %s", sim_path, strerror(errno));
|
sim_panel_set_error ("Can't connect to simulator Remote Console on port %s", p->hostport);
|
||||||
else
|
}
|
||||||
sim_panel_set_error ("Can't connect to simulator Remote Console on port %s", hostport);
|
else {
|
||||||
|
if (stat (sim_path, &statb) < 0)
|
||||||
|
sim_panel_set_error ("Can't stat simulator '%s': %s", sim_path, strerror(errno));
|
||||||
|
else
|
||||||
|
sim_panel_set_error ("Can't connect to simulator Remote Console on port %s", p->hostport);
|
||||||
|
}
|
||||||
goto Error_Return;
|
goto Error_Return;
|
||||||
}
|
}
|
||||||
strcpy (p->hostport, hostport);
|
_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 at %s after %dms\n", NULL, 0, hostport, 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_cond_init (&p->io_done, NULL);
|
pthread_cond_init (&p->io_done, NULL);
|
||||||
@@ -622,26 +644,30 @@ if (1) {
|
|||||||
pthread_mutex_unlock (&p->io_lock);
|
pthread_mutex_unlock (&p->io_lock);
|
||||||
pthread_cond_destroy (&p->startup_cond);
|
pthread_cond_destroy (&p->startup_cond);
|
||||||
}
|
}
|
||||||
if (device_panel_count) {
|
if (simulator_panel) {
|
||||||
p->devices = (PANEL **)_panel_malloc (device_panel_count*sizeof(*p->devices));
|
simulator_panel->devices[device_num] = p;
|
||||||
if (p->devices == NULL)
|
}
|
||||||
|
else {
|
||||||
|
if (device_panel_count) {
|
||||||
|
p->devices = (PANEL **)_panel_malloc (device_panel_count*sizeof(*p->devices));
|
||||||
|
if (p->devices == NULL)
|
||||||
|
goto Error_Return;
|
||||||
|
memset (p->devices, 0, device_panel_count*sizeof(*p->devices));
|
||||||
|
p->device_count = device_panel_count;
|
||||||
|
}
|
||||||
|
/* Validate sim_frontpanel API version */
|
||||||
|
if (_panel_sendf (p, 1, &p->simulator_version, "SHOW VERSION\r"))
|
||||||
goto Error_Return;
|
goto Error_Return;
|
||||||
memset (p->devices, 0, device_panel_count*sizeof(*p->devices));
|
if (1) {
|
||||||
p->device_count = device_panel_count;
|
int api_version = 0;
|
||||||
}
|
char *c = strstr (p->simulator_version, "FrontPanel API Version");
|
||||||
/* Validate sim_frontpanel API version */
|
|
||||||
if (_panel_sendf (p, 1, &p->simulator_version, "SHOW VERSION\r")) {
|
|
||||||
goto Error_Return;
|
|
||||||
}
|
|
||||||
if (1) {
|
|
||||||
int api_version = 0;
|
|
||||||
char *c = strstr (p->simulator_version, "FrontPanel API Version");
|
|
||||||
|
|
||||||
if ((!c) ||
|
if ((!c) ||
|
||||||
(1 != sscanf (c, "FrontPanel API Version %d", &api_version)) ||
|
(1 != sscanf (c, "FrontPanel API Version %d", &api_version)) ||
|
||||||
(api_version != SIM_FRONTPANEL_VERSION)) {
|
(api_version != SIM_FRONTPANEL_VERSION)) {
|
||||||
sim_panel_set_error ("Inconsistent sim_frontpanel API version %d in simulator. Version %d needed.-", api_version, SIM_FRONTPANEL_VERSION);
|
sim_panel_set_error ("Inconsistent sim_frontpanel API version %d in simulator. Version %d needed.-", api_version, SIM_FRONTPANEL_VERSION);
|
||||||
goto Error_Return;
|
goto Error_Return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_panel_register_panel (p);
|
_panel_register_panel (p);
|
||||||
@@ -668,74 +694,36 @@ if (1) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PANEL *
|
||||||
|
sim_panel_start_simulator_debug (const char *sim_path,
|
||||||
|
const char *sim_config,
|
||||||
|
size_t device_panel_count,
|
||||||
|
const char *debug_file)
|
||||||
|
{
|
||||||
|
return _sim_panel_create (sim_path, sim_config, device_panel_count, NULL, NULL, debug_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
PANEL *
|
||||||
|
sim_panel_start_simulator (const char *sim_path,
|
||||||
|
const char *sim_config,
|
||||||
|
size_t device_panel_count)
|
||||||
|
{
|
||||||
|
return sim_panel_start_simulator_debug (sim_path, sim_config, device_panel_count, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
PANEL *
|
||||||
|
sim_panel_add_device_panel_debug (PANEL *simulator_panel,
|
||||||
|
const char *device_name,
|
||||||
|
const char *debug_file)
|
||||||
|
{
|
||||||
|
return _sim_panel_create (NULL, NULL, 0, simulator_panel, device_name, debug_file);
|
||||||
|
}
|
||||||
|
|
||||||
PANEL *
|
PANEL *
|
||||||
sim_panel_add_device_panel (PANEL *simulator_panel,
|
sim_panel_add_device_panel (PANEL *simulator_panel,
|
||||||
const char *device_name)
|
const char *device_name)
|
||||||
{
|
{
|
||||||
size_t i, device_num;
|
return sim_panel_add_device_panel_debug (simulator_panel, device_name, NULL);
|
||||||
PANEL *p = NULL;
|
|
||||||
|
|
||||||
if (!simulator_panel) {
|
|
||||||
sim_panel_set_error ("Invalid Panel");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
for (device_num=0; device_num < simulator_panel->device_count; ++device_num)
|
|
||||||
if (simulator_panel->devices[device_num] == NULL)
|
|
||||||
break;
|
|
||||||
if (device_num == simulator_panel->device_count) {
|
|
||||||
sim_panel_set_error ("No free panel devices slots available %s simulator. All %d slots are used.", simulator_panel->path, (int)simulator_panel->device_count);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
p = (PANEL *)_panel_malloc (sizeof(*p));
|
|
||||||
if (p == NULL)
|
|
||||||
goto Error_Return;
|
|
||||||
memset (p, 0, sizeof(*p));
|
|
||||||
p->device_name = (char *)_panel_malloc (1 + strlen (device_name));
|
|
||||||
if (p->device_name == NULL)
|
|
||||||
goto Error_Return;
|
|
||||||
strcpy (p->device_name, device_name);
|
|
||||||
p->parent = simulator_panel;
|
|
||||||
p->sock = INVALID_SOCKET;
|
|
||||||
for (i=0; i<100; i++) {
|
|
||||||
p->sock = sim_connect_sock_ex (NULL, simulator_panel->hostport, NULL, NULL, SIM_SOCK_OPT_NODELAY | SIM_SOCK_OPT_BLOCKING);
|
|
||||||
if (p->sock == INVALID_SOCKET)
|
|
||||||
msleep (100);
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (p->sock == INVALID_SOCKET) {
|
|
||||||
sim_panel_set_error ("Can't connect to simulator Remote Console on port %s", simulator_panel->hostport);
|
|
||||||
goto Error_Return;
|
|
||||||
}
|
|
||||||
strcpy (p->hostport, simulator_panel->hostport);
|
|
||||||
pthread_mutex_init (&p->io_lock, NULL);
|
|
||||||
pthread_mutex_init (&p->io_send_lock, NULL);
|
|
||||||
pthread_cond_init (&p->io_done, NULL);
|
|
||||||
pthread_cond_init (&p->startup_cond, NULL);
|
|
||||||
if (sizeof(mantra) != _panel_send (p, (char *)mantra, sizeof(mantra))) {
|
|
||||||
sim_panel_set_error ("Error sending Telnet mantra (options): %s", sim_get_err_sock ("send"));
|
|
||||||
goto Error_Return;
|
|
||||||
}
|
|
||||||
if (1) {
|
|
||||||
pthread_attr_t attr;
|
|
||||||
|
|
||||||
pthread_attr_init(&attr);
|
|
||||||
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
|
|
||||||
pthread_mutex_lock (&p->io_lock);
|
|
||||||
pthread_create (&p->io_thread, &attr, _panel_reader, (void *)p);
|
|
||||||
pthread_attr_destroy(&attr);
|
|
||||||
while (!p->io_thread_running)
|
|
||||||
pthread_cond_wait (&p->startup_cond, &p->io_lock); /* Wait for thread to stabilize */
|
|
||||||
pthread_mutex_unlock (&p->io_lock);
|
|
||||||
pthread_cond_destroy (&p->startup_cond);
|
|
||||||
}
|
|
||||||
simulator_panel->devices[device_num] = p;
|
|
||||||
_panel_register_panel (p);
|
|
||||||
return p;
|
|
||||||
|
|
||||||
Error_Return:
|
|
||||||
sim_panel_destroy (p);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|||||||
Reference in New Issue
Block a user