1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-04-09 22:38:45 +00:00

SCP: Updated to current.

This commit is contained in:
Richard Cornwell
2022-01-19 09:46:58 -05:00
parent d5f6e61be5
commit d705087a22
8 changed files with 626 additions and 202 deletions

73
scp.c
View File

@@ -1575,6 +1575,7 @@ static const char simh_help2[] =
"+sh{ow} <unit> {arg,...} show unit parameters\n"
"+sh{ow} ethernet show ethernet devices\n"
"+sh{ow} serial show serial devices\n"
"+sh{ow} synchronous show DDCMP synchronous interface devices\n"
"+sh{ow} multiplexer {dev} show open multiplexer device info\n"
"+sh{ow} video show video capabilities\n"
"+sh{ow} clocks show calibrated timer information\n"
@@ -1603,6 +1604,7 @@ static const char simh_help2[] =
#define HLP_SHOW_ASYNCH "*Commands SHOW"
#define HLP_SHOW_ETHERNET "*Commands SHOW"
#define HLP_SHOW_SERIAL "*Commands SHOW"
#define HLP_SHOW_SYNC "*Commands SHOW"
#define HLP_SHOW_MULTIPLEXER "*Commands SHOW"
#define HLP_SHOW_VIDEO "*Commands SHOW"
#define HLP_SHOW_CLOCKS "*Commands SHOW"
@@ -2643,6 +2645,7 @@ static SHTAB show_glob_tab[] = {
{ "ASYNCH", &sim_show_asynch, 0, HLP_SHOW_ASYNCH },
{ "ETHERNET", &eth_show_devices, 0, HLP_SHOW_ETHERNET },
{ "SERIAL", &sim_show_serial, 0, HLP_SHOW_SERIAL },
{ "SYNCHRONOUS", &tmxr_show_sync_devices, 0, HLP_SHOW_SYNC },
{ "MULTIPLEXER", &tmxr_show_open_devices, 0, HLP_SHOW_MULTIPLEXER },
{ "MUX", &tmxr_show_open_devices, 0, HLP_SHOW_MULTIPLEXER },
{ "VIDEO", &vid_show, 0, HLP_SHOW_VIDEO },
@@ -5844,7 +5847,7 @@ else {
}
}
if (!dptr)
return SCPE_NXDEV; /* no match */
return sim_messagef (SCPE_NXDEV, "Non-existent device: %s\n", gbuf);/* no match */
lvl = MTAB_VDV; /* device match */
uptr = dptr->units; /* first unit */
}
@@ -5865,7 +5868,7 @@ while (*cptr != 0) { /* do all mods */
if (((lvl & mptr->mask) & ~MTAB_XTD) == 0)
return SCPE_ARG;
if ((lvl == MTAB_VUN) && (uptr->flags & UNIT_DIS))
return SCPE_UDIS; /* unit disabled? */
return sim_messagef (SCPE_UDIS, "Unit disabled: %s\n", sim_uname (uptr));
if (mptr->valid) { /* validation rtn? */
if (cvptr && MODMASK(mptr,MTAB_QUOTE)) {
svptr = get_glyph_quoted (svptr, gbuf, ',');
@@ -5895,7 +5898,7 @@ while (*cptr != 0) { /* do all mods */
if (cvptr) /* = value? */
return SCPE_ARG;
if (uptr->flags & UNIT_DIS) /* disabled? */
return SCPE_UDIS;
return sim_messagef (SCPE_UDIS, "Unit disabled: %s\n", sim_uname (uptr));
if ((mptr->valid) && /* invalid? */
((r = mptr->valid (uptr, mptr->match, cvptr, mptr->desc)) != SCPE_OK))
return r;
@@ -5913,7 +5916,7 @@ while (*cptr != 0) { /* do all mods */
}
else if (!dptr->modifiers) /* no modifiers? */
return SCPE_NOPARAM;
else return SCPE_NXPAR;
else return sim_messagef (SCPE_NXPAR, "%s device: Non-existent parameter - %s\n", dptr->name, gbuf);
} /* end if no mat */
} /* end while */
return SCPE_OK; /* done all */
@@ -6191,7 +6194,7 @@ while (*cptr != 0) { /* do all mods */
if (!dptr->modifiers) /* no modifiers? */
return sim_messagef (SCPE_NOPARAM, "%s device has no parameters\n", dptr->name);
else
return sim_messagef (SCPE_NXPAR, "Non-existent parameter: %s\n", gbuf);
return sim_messagef (SCPE_NXPAR, "%s device: Non-existent parameter: %s\n", dptr->name, gbuf);
}
} /* end if */
} /* end while */
@@ -6477,6 +6480,8 @@ const char *cpp = "";
const char *build = "";
const char *arch = "";
#define S_xstr(a) S_str(a)
#define S_str(a) #a
if (cptr && (*cptr != 0))
return SCPE_2MARG;
sprintf (vmaj_s, "%d", vmaj);
@@ -6496,8 +6501,16 @@ if (vdelt) {
fprintf (st, " delta %d", vdelt);
}
#if defined (SIM_VERSION_MODE)
fprintf (st, " %s", SIM_VERSION_MODE);
setenv ("SIM_VERSION_MODE", SIM_VERSION_MODE, 1);
if (1) {
char mode[] = S_xstr(SIM_VERSION_MODE);
if (NULL != strchr (mode, '\"')) { /* Quoted String? */
mode[strlen (mode) - 1] = '\0'; /* strip quotes */
memmove (mode, mode + 1, strlen (mode));
}
fprintf (st, " %s", mode);
setenv ("SIM_VERSION_MODE", mode, 1);
}
#endif
if (flag) {
t_bool idle_capable;
@@ -6541,11 +6554,7 @@ if (flag) {
#elif defined (__DECC_VER)
fprintf (st, "\n Compiler: DEC C %c%d.%d-%03d", ("T SV")[((__DECC_VER/10000)%10)-6], __DECC_VER/10000000, (__DECC_VER/100000)%100, __DECC_VER%10000);
#elif defined (SIM_COMPILER)
#define S_xstr(a) S_str(a)
#define S_str(a) #a
fprintf (st, "\n Compiler: %s", S_xstr(SIM_COMPILER));
#undef S_str
#undef S_xstr
#endif
#if defined(__GNUC__)
#if defined(__OPTIMIZE__)
@@ -6574,19 +6583,11 @@ if (flag) {
#if !defined (SIM_BUILD_OS)
fprintf (st, "\n Simulator Compiled as %s%s%s on %s at %s", cpp, arch, build, __DATE__, __TIME__);
#else
#define S_xstr(a) S_str(a)
#define S_str(a) #a
fprintf (st, "\n Simulator Compiled as %s%s%s on %s at %s %s", cpp, arch, build, __DATE__, __TIME__, S_xstr(SIM_BUILD_OS));
#undef S_str
#undef S_xstr
#endif
#endif
#if defined (SIM_BUILD_TOOL)
#define S_xstr(a) S_str(a)
#define S_str(a) #a
fprintf (st, "\n Build Tool: %s", S_xstr(SIM_BUILD_TOOL));
#undef S_str
#undef S_xstr
#else
fprintf (st, "\n Build Tool: undefined (probably cmake)");
#endif
@@ -6689,8 +6690,6 @@ if (flag) {
setenv ("SIM_OSTYPE", os_type, 1);
}
#if defined(SIM_ARCHIVE_GIT_COMMIT_ID)
#define S_xstr(a) S_str(a)
#define S_str(a) #a
if (NULL == strchr (S_xstr(SIM_ARCHIVE_GIT_COMMIT_ID), '$')) {
const char *extras = strchr (S_xstr(SIM_ARCHIVE_GIT_COMMIT_ID), '+');
@@ -6704,12 +6703,8 @@ if (NULL == strchr (S_xstr(SIM_ARCHIVE_GIT_COMMIT_TIME), '$')) {
fprintf (st, "%ssimh git commit time: %s", "\n ", S_xstr(SIM_ARCHIVE_GIT_COMMIT_TIME));
}
#endif
#undef S_str
#undef S_xstr
#endif
#if defined(SIM_GIT_COMMIT_ID)
#define S_xstr(a) S_str(a)
#define S_str(a) #a
if (1) {
const char *extras = strchr (S_xstr(SIM_GIT_COMMIT_ID), '+');
@@ -6721,19 +6716,15 @@ setenv ("SIM_GIT_COMMIT_TIME", S_xstr(SIM_GIT_COMMIT_TIME), 1);
if (flag)
fprintf (st, "%sgit commit time: %s", "\n ", S_xstr(SIM_GIT_COMMIT_TIME));
#endif
#undef S_str
#undef S_xstr
#endif
#if defined(SIM_BUILD)
#define S_xstr(a) S_str(a)
#define S_str(a) #a
fprintf (st, "%sBuild: %s", flag ? "\n " : " ", S_xstr(SIM_BUILD));
#undef S_str
#undef S_xstr
#endif
fprintf (st, "\n");
if (sim_vm_release_message != NULL) /* if a release message string is defined */
fprintf (st, "\n%s", sim_vm_release_message); /* then display it */
#undef S_str
#undef S_xstr
return SCPE_OK;
}
@@ -7627,7 +7618,7 @@ if (strcmp (gbuf, "ALL") == 0)
return (reset_all (0));
dptr = find_dev (gbuf); /* locate device */
if (dptr == NULL) /* found it? */
return SCPE_NXDEV;
return sim_messagef (SCPE_NXDEV, "Non-existent device: %s\n", gbuf);
if (dptr->reset != NULL)
return dptr->reset (dptr);
else return SCPE_OK;
@@ -7970,7 +7961,7 @@ if (*cptr == 0) /* now eol? */
return SCPE_2FARG;
dptr = find_unit (gbuf, &uptr); /* locate unit */
if (dptr == NULL) /* found dev? */
return SCPE_NXDEV;
return sim_messagef (SCPE_NXDEV, "Non-existent device: %s\n", gbuf);
if (uptr == NULL) /* valid unit? */
return SCPE_NXUN;
if (uptr->flags & UNIT_ATT) { /* already attached? */
@@ -7982,7 +7973,7 @@ if (uptr->flags & UNIT_ATT) { /* already attached? */
}
else {
if (!(uptr->dynflags & UNIT_ATTMULT))
return SCPE_ALATT; /* Already attached */
return sim_messagef (SCPE_ALATT, "%s: Already attached\n", sim_uname (uptr));
}
}
gbuf[sizeof(gbuf)-1] = '\0';
@@ -7996,7 +7987,7 @@ return scp_attach_unit (dptr, uptr, gbuf); /* attach */
t_stat scp_attach_unit (DEVICE *dptr, UNIT *uptr, const char *cptr)
{
if (uptr->flags & UNIT_DIS) /* disabled? */
return SCPE_UDIS;
return sim_messagef (SCPE_UDIS, "Unit disabled: %s\n", sim_uname (uptr));
if (dptr->attach != NULL) /* device routine? */
return dptr->attach (uptr, (CONST char *)cptr); /* call it */
return attach_unit (uptr, (CONST char *)cptr); /* no, std routine */
@@ -8116,7 +8107,7 @@ if (strcmp (gbuf, "ALL") == 0)
return (detach_all (0, FALSE));
dptr = find_unit (gbuf, &uptr); /* locate unit */
if (dptr == NULL) /* found dev? */
return SCPE_NXDEV;
return sim_messagef (SCPE_NXDEV, "Non-existent device: %s\n", gbuf);
if (uptr == NULL) /* valid unit? */
return SCPE_NXUN;
return scp_detach_unit (dptr, uptr); /* detach */
@@ -8237,7 +8228,7 @@ if (*cptr == 0) /* now eol? */
return SCPE_2FARG;
dptr = find_dev (gbuf); /* locate device */
if (dptr == NULL) /* found dev? */
return SCPE_NXDEV;
return sim_messagef (SCPE_NXDEV, "Non-existent device: %s\n", gbuf);
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
if (*cptr != 0) /* must be eol */
return SCPE_2MARG;
@@ -8274,7 +8265,7 @@ if (*cptr != 0) /* now eol? */
return SCPE_2MARG;
dptr = find_dev (gbuf); /* locate device */
if (dptr == NULL) /* found dev? */
return SCPE_NXDEV;
return sim_messagef (SCPE_NXDEV, "Non-existent device: %s\n", gbuf);
return deassign_device (dptr);
}
@@ -9038,13 +9029,13 @@ else if (flag == RU_BOOT) { /* boot */
return SCPE_2MARG;
dptr = find_unit (gbuf, &uptr); /* locate unit */
if (dptr == NULL) /* found dev? */
return SCPE_NXDEV;
return sim_messagef (SCPE_NXDEV, "Non-existent device: %s\n", gbuf);
if (uptr == NULL) /* valid unit? */
return SCPE_NXUN;
if (dptr->boot == NULL) /* can it boot? */
return SCPE_NOFNC;
if (uptr->flags & UNIT_DIS) /* disabled? */
return SCPE_UDIS;
return sim_messagef (SCPE_UDIS, "Unit disabled: %s\n", sim_uname (uptr));
if ((uptr->flags & UNIT_ATTABLE) && /* if attable, att? */
!(uptr->flags & UNIT_ATT))
return SCPE_UNATT;
@@ -9551,7 +9542,7 @@ t_stat reason;
int32 saved_switches = sim_switches;
if (uptr->flags & UNIT_DIS) /* disabled? */
return SCPE_UDIS;
return sim_messagef (SCPE_UDIS, "Unit disabled: %s\n", sim_uname (uptr));
mask = (t_addr) width_mask[dptr->awidth];
if ((low > mask) || (high > mask) || (low > high))
return SCPE_ARG;

View File

@@ -2897,8 +2897,10 @@ if (!sim_rem_master_mode) {
}
}
tmxr_poll_rx (&sim_con_tmxr); /* poll for input */
if ((c = (t_stat)tmxr_getc_ln (&sim_con_ldsc))) /* any char? */
if ((c = (t_stat)tmxr_getc_ln (&sim_con_ldsc))) { /* any char? */
sim_debug (DBG_RCV, &sim_con_telnet, "sim_poll_kbd() tmxr_getc_ln() returning: '%c' (0x%02X)\n", sim_isprint (c & 0xFF) ? c & 0xFF : '.', c);
return (c & (SCPE_BREAK | 0377)) | SCPE_KFLAG;
}
return SCPE_OK;
}

View File

@@ -383,6 +383,9 @@
/* Internal routine - forward declaration */
static int _eth_get_system_id (char *buf, size_t buf_size);
static void eth_get_nic_hw_addr(ETH_DEV* dev, const char *devname, int set_on);
static const unsigned char framer_oui[3] = { 0xaa, 0x00, 0x03 };
/*============================================================================*/
/* OS-independant ethernet routines */
@@ -780,13 +783,11 @@ return eth_show (st, uptr, val, NULL);
}
#if defined (USE_NETWORK) || defined (USE_SHARED)
/* Internal routine - forward declaration */
static int _eth_devices (int max, ETH_LIST* dev); /* get ethernet devices on host */
static const char* _eth_getname(int number, char* name, char *desc)
{
ETH_LIST list[ETH_MAX_DEVICE];
int count = _eth_devices(ETH_MAX_DEVICE, list);
int count = eth_devices(ETH_MAX_DEVICE, list, FALSE);
if ((number < 0) || (count <= number))
return NULL;
@@ -803,7 +804,7 @@ static const char* _eth_getname(int number, char* name, char *desc)
const char* eth_getname_bydesc(const char* desc, char* name, char *ndesc)
{
ETH_LIST list[ETH_MAX_DEVICE];
int count = _eth_devices(ETH_MAX_DEVICE, list);
int count = eth_devices(ETH_MAX_DEVICE, list, FALSE);
int i;
size_t j=strlen(desc);
@@ -829,7 +830,7 @@ const char* eth_getname_bydesc(const char* desc, char* name, char *ndesc)
char* eth_getname_byname(const char* name, char* temp, char *desc)
{
ETH_LIST list[ETH_MAX_DEVICE];
int count = _eth_devices(ETH_MAX_DEVICE, list);
int count = eth_devices(ETH_MAX_DEVICE, list, FALSE);
size_t n;
int i, found;
@@ -849,7 +850,7 @@ char* eth_getname_byname(const char* name, char* temp, char *desc)
char* eth_getdesc_byname(char* name, char* temp)
{
ETH_LIST list[ETH_MAX_DEVICE];
int count = _eth_devices(ETH_MAX_DEVICE, list);
int count = eth_devices(ETH_MAX_DEVICE, list, FALSE);
size_t n;
int i, found;
@@ -894,7 +895,7 @@ t_stat eth_show (FILE* st, UNIT* uptr, int32 val, CONST void* desc)
ETH_LIST list[ETH_MAX_DEVICE];
int number;
number = _eth_devices(ETH_MAX_DEVICE, list);
number = eth_devices(ETH_MAX_DEVICE, list, FALSE);
fprintf(st, "ETH devices:\n");
if (number == -1)
fprintf(st, " network support not available in simulator\n");
@@ -965,6 +966,8 @@ t_stat eth_filter_hash (ETH_DEV* dev, int addr_count, ETH_MAC* const addresses,
{return SCPE_NOFNC;}
const char *eth_version (void)
{return NULL;}
int eth_devices(int max, ETH_LIST* list, ETH_BOOL framers)
{return 0;}
void eth_show_dev (FILE* st, ETH_DEV* dev)
{}
t_stat eth_show (FILE* st, UNIT* uptr, int32 val, CONST void* desc)
@@ -1112,13 +1115,14 @@ for (i=0; i<used; i++) {
return used;
}
static int _eth_devices(int max, ETH_LIST* list)
int eth_devices(int max, ETH_LIST* list, ETH_BOOL framers)
{
int used = 0;
char errbuf[PCAP_ERRBUF_SIZE] = "";
#ifndef DONT_USE_PCAP_FINDALLDEVS
pcap_if_t* alldevs;
pcap_if_t* dev;
ETH_DEV edev;
memset(list, 0, max*sizeof(*list));
errbuf[0] = '\0';
@@ -1129,7 +1133,11 @@ if (pcap_findalldevs(&alldevs, errbuf) == -1) {
}
else {
/* copy device list into the passed structure */
for (used=0, dev=alldevs; dev && (used < max); dev=dev->next, ++used) {
for (used=0, dev=alldevs; dev && (used < max); dev=dev->next) {
edev.eth_api = ETH_API_PCAP;
eth_get_nic_hw_addr (&edev, dev->name, 0);
if ((memcmp (edev.host_nic_phy_hw_addr, framer_oui, 3) == 0) != framers)
continue;
if ((dev->flags & PCAP_IF_LOOPBACK) || (!strcmp("any", dev->name)))
continue;
strlcpy(list[used].name, dev->name, sizeof(list[used].name));
@@ -1137,6 +1145,7 @@ else {
strlcpy(list[used].desc, dev->description, sizeof(list[used].desc));
else
strlcpy(list[used].desc, "No description available", sizeof(list[used].desc));
++used;
}
/* free device list */
@@ -1152,6 +1161,9 @@ if ((used == 0) && (errbuf[0])) {
sim_printf ("Eth: pcap_findalldevs warning: %s\n", errbuf);
}
if (framers)
return used; /* don't add pseudo-ethernet devices */
#ifdef HAVE_TAP_NETWORK
if (used < max) {
#if defined(__OpenBSD__)
@@ -1736,7 +1748,7 @@ static int pcap_mac_if_vms(const char *AdapterName, unsigned char MACAddress[6])
}
#endif /* defined (__VMS) && !defined(__VAX) */
static void eth_get_nic_hw_addr(ETH_DEV* dev, const char *devname)
static void eth_get_nic_hw_addr(ETH_DEV* dev, const char *devname, int set_on)
{
memset(&dev->host_nic_phy_hw_addr, 0, sizeof(dev->host_nic_phy_hw_addr));
dev->have_host_nic_phy_addr = 0;
@@ -1755,24 +1767,26 @@ static void eth_get_nic_hw_addr(ETH_DEV* dev, const char *devname)
int i;
char tool[CBUFSIZE];
const char *turnon[] = {
"ip link set dev %.*s up",
"ifconfig %.*s up",
"ip link set dev %.*s up 2>/dev/null",
"ifconfig %.*s up 2>/dev/null",
NULL};
const char *patterns[] = {
"ip link show %.*s | grep [0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]",
"ip link show %.*s | egrep [0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]",
"ifconfig %.*s | grep [0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]",
"ifconfig %.*s | egrep [0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]",
"ip link show %.*s 2>/dev/null | grep [0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]",
"ip link show %.*s 2>/dev/null | egrep [0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]",
"ifconfig %.*s 2>/dev/null | grep [0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]",
"ifconfig %.*s 2>/dev/null | egrep [0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]",
NULL};
memset(command, 0, sizeof(command));
/* try to force an otherwise unused interface to be turned on */
for (i=0; turnon[i]; ++i) {
snprintf(command, sizeof(command), turnon[i], (int)(sizeof(command) - (2 + strlen(patterns[i]))), devname);
get_glyph_nc (command, tool, 0);
if (sim_get_tool_path (tool)[0]) {
if (NULL != (f = popen(command, "r")))
pclose(f);
if (set_on) {
/* try to force an otherwise unused interface to be turned on */
for (i=0; turnon[i]; ++i) {
snprintf(command, sizeof(command), turnon[i], (int)(sizeof(command) - (2 + strlen(patterns[i]))), devname);
get_glyph_nc (command, tool, 0);
if (sim_get_tool_path (tool)[0]) {
if (NULL != (f = popen(command, "r")))
pclose(f);
}
}
}
for (i=0; patterns[i] && (0 == dev->have_host_nic_phy_addr); ++i) {
@@ -2500,12 +2514,13 @@ if (bufsz < ETH_MAX_JUMBO_FRAME)
/* initialize device */
eth_zero(dev);
/* translate name of type "ethX" to real device name */
if ((strlen(name) == 4)
/* translate name of type "eth<num>" to real device name */
if ((strlen(name) == 4 || strlen(name) == 5)
&& (tolower(name[0]) == 'e')
&& (tolower(name[1]) == 't')
&& (tolower(name[2]) == 'h')
&& isdigit(name[3])
&& (strlen(name) == 4 || isdigit(name[4]))
) {
num = atoi(&name[3]);
savname = _eth_getname(num, temp, desc);
@@ -2545,7 +2560,7 @@ if (!strcmp (desc, "No description available"))
sim_messagef (SCPE_OK, "Eth: opened OS device %s%s%s\n", savname, desc[0] ? " - " : "", desc);
/* get the NIC's hardware MAC address */
eth_get_nic_hw_addr(dev, savname);
eth_get_nic_hw_addr(dev, savname, 1);
/* save name of device */
dev->name = (char *)malloc(strlen(savname)+1);
@@ -4368,7 +4383,7 @@ int bpf_compile_skip_count = 0;
memset (&eth_tst, 0, sizeof(eth_tst));
eth_device_count = _eth_devices(ETH_MAX_DEVICE, eth_list);
eth_device_count = eth_devices(ETH_MAX_DEVICE, eth_list, FALSE);
eth_opened = 0;
for (eth_num=0; eth_num<eth_device_count; eth_num++) {
char eth_name[32];

View File

@@ -232,6 +232,8 @@ struct eth_queue {
struct eth_item* item;
};
typedef unsigned char ETH_MAC[6];
struct eth_list {
char name[ETH_DEV_NAME_MAX];
char desc[ETH_DEV_DESC_MAX];
@@ -239,7 +241,6 @@ struct eth_list {
};
typedef int ETH_BOOL;
typedef unsigned char ETH_MAC[6];
typedef unsigned char ETH_MULTIHASH[8];
typedef struct eth_packet ETH_PACK;
typedef void (*ETH_PCALLBACK)(int status);
@@ -368,6 +369,7 @@ t_stat eth_show (FILE* st, UNIT* uptr, /* show ethernet devices
int32 val, CONST void* desc);
t_stat eth_show_devices (FILE* st, DEVICE *dptr, /* show ethernet devices */
UNIT* uptr, int32 val, CONST char* desc);
int eth_devices (int max, ETH_LIST* dev, ETH_BOOL framers); /* get ethernet devices on host */
void eth_show_dev (FILE*st, ETH_DEV* dev); /* show ethernet device state */
void eth_mac_fmt (ETH_MAC* const add, char* buffer); /* format ethernet mac address */

View File

@@ -582,7 +582,7 @@ COMMCONFIG commdefault;
DWORD error;
DWORD commsize = sizeof (commdefault);
COMMTIMEOUTS cto;
char dosname[1028];
char win32name[1028];
if (!GetDefaultCommConfig (name, &commdefault, &commsize)) { /* get default comm parameters */
error = GetLastError (); /* function failed; get error */
@@ -593,10 +593,8 @@ if (!GetDefaultCommConfig (name, &commdefault, &commsize)) { /* get default c
return INVALID_HANDLE; /* indicate bad port name */
}
strncpy(dosname, "\\\\.\\", 4);
strncat(dosname, name, sizeof(dosname));
hPort = CreateFile (dosname, GENERIC_READ | GENERIC_WRITE, /* open the port */
snprintf (win32name, sizeof (win32name), "\\\\.\\%s", name);
hPort = CreateFile (win32name, GENERIC_READ | GENERIC_WRITE, /* open the port */
0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
if (hPort == INVALID_HANDLE_VALUE) { /* open failed? */
@@ -966,18 +964,19 @@ if (1) {
strcmp(namelist[i]->d_name, "..")) {
char path[1024], devicepath[1024], driverpath[1024];
sprintf (path, "/sys/class/tty/%s", namelist[i]->d_name);
sprintf (devicepath, "/sys/class/tty/%s/device", namelist[i]->d_name);
sprintf (driverpath, "/sys/class/tty/%s/device/driver", namelist[i]->d_name);
snprintf (path, sizeof (path), "/sys/class/tty/%s", namelist[i]->d_name);
snprintf (devicepath, sizeof (devicepath), "/sys/class/tty/%s/device", namelist[i]->d_name);
snprintf (driverpath, sizeof (driverpath), "/sys/class/tty/%s/device/driver", namelist[i]->d_name);
if ((lstat(devicepath, &st) == 0) && S_ISLNK(st.st_mode)) {
char buffer[1024];
memset (buffer, 0, sizeof(buffer));
if (readlink(driverpath, buffer, sizeof(buffer)) > 0) {
sprintf (list[ports].name, "/dev/%s", basename (path));
snprintf (list[ports].name, sizeof (list[ports].name), "/dev/%s", basename (path));
port = open (list[ports].name, O_RDWR | O_NOCTTY | O_NONBLOCK); /* open the port */
if (port != -1) { /* open OK? */
if (isatty (port)) /* is device a TTY? */
if ((ports < max) && /* room for another? */
(isatty (port))) /* is device a TTY? */
++ports;
close (port);
}
@@ -990,7 +989,7 @@ if (1) {
}
#elif defined(__hpux)
for (i=0; (ports < max) && (i < 64); ++i) {
sprintf (list[ports].name, "/dev/tty%dp%d", i/8, i%8);
snprintf (list[ports].name, sizeof (list[ports].name), "/dev/tty%dp%d", i/8, i%8);
port = open (list[ports].name, O_RDWR | O_NOCTTY | O_NONBLOCK); /* open the port */
if (port != -1) { /* open OK? */
if (isatty (port)) /* is device a TTY? */
@@ -999,44 +998,27 @@ for (i=0; (ports < max) && (i < 64); ++i) {
}
}
#else /* Non Linux/HP-UX, just try some well known device names */
/* modern UNIX serial port names - usually USB */
static char *serial_unix_serial_names[] = { "S", "U", "USB", ".serial", ".usbserial", NULL};
char **sp;
for (sp = serial_unix_serial_names; *sp; sp++) {
for (i=0; (ports < max) && (i <= 64); ++i) {
if (i < 64)
snprintf (list[ports].name, sizeof (list[ports].name), "/dev/tty%s%d", *sp, i);
else /* no trailing number */
snprintf (list[ports].name, sizeof (list[ports].name), "/dev/tty%s", *sp);
port = open (list[ports].name, O_RDWR | O_NOCTTY | O_NONBLOCK); /* open the port */
if (port != -1) { /* open OK? */
if (isatty (port)) /* is device a TTY? */
++ports;
close (port);
}
}
}
/* now the traditional UNIX serial port names */
for (i=0; (ports < max) && (i < 64); ++i) {
sprintf (list[ports].name, "/dev/ttyS%d", i);
port = open (list[ports].name, O_RDWR | O_NOCTTY | O_NONBLOCK); /* open the port */
if (port != -1) { /* open OK? */
if (isatty (port)) /* is device a TTY? */
++ports;
close (port);
}
}
for (i=0; (ports < max) && (i < 64); ++i) {
sprintf (list[ports].name, "/dev/ttyUSB%d", i);
port = open (list[ports].name, O_RDWR | O_NOCTTY | O_NONBLOCK); /* open the port */
if (port != -1) { /* open OK? */
if (isatty (port)) /* is device a TTY? */
++ports;
close (port);
}
}
for (i=1; (ports < max) && (i < 64); ++i) {
sprintf (list[ports].name, "/dev/tty.serial%d", i);
port = open (list[ports].name, O_RDWR | O_NOCTTY | O_NONBLOCK); /* open the port */
if (port != -1) { /* open OK? */
if (isatty (port)) /* is device a TTY? */
++ports;
close (port);
}
}
for (i=0; (ports < max) && (i < 64); ++i) {
sprintf (list[ports].name, "/dev/tty%02d", i);
port = open (list[ports].name, O_RDWR | O_NOCTTY | O_NONBLOCK); /* open the port */
if (port != -1) { /* open OK? */
if (isatty (port)) /* is device a TTY? */
++ports;
close (port);
}
}
for (i=0; (ports < max) && (i < 8); ++i) {
sprintf (list[ports].name, "/dev/ttyU%d", i);
snprintf (list[ports].name, sizeof (list[ports].name), "/dev/tty%02d", i);
port = open (list[ports].name, O_RDWR | O_NOCTTY | O_NONBLOCK); /* open the port */
if (port != -1) { /* open OK? */
if (isatty (port)) /* is device a TTY? */
@@ -1044,6 +1026,7 @@ for (i=0; (ports < max) && (i < 8); ++i) {
close (port);
}
}
#endif
return ports;
}
@@ -1127,10 +1110,6 @@ if (tcgetattr (port, &tio)) { /* get the terminal attr
return INVALID_HANDLE; /* and return failure to caller */
}
// which of these methods is best?
#if 1
tio.c_iflag = (tio.c_iflag & ~i_clear) | i_set; /* configure the serial line for raw mode */
tio.c_oflag = (tio.c_oflag & ~o_clear) | o_set;
tio.c_cflag = (tio.c_cflag & ~c_clear) | c_set;
@@ -1142,24 +1121,6 @@ tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 0;
#endif
#elif 0
tio.c_iflag &= ~(IGNBRK | BRKINT | INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF);
tio.c_iflag |= PARMRK | IGNPAR;
tio.c_oflag &= ~(OPOST);
tio.c_cflag &= ~(HUPCL);
tio.c_cflag |= CREAD | CLOCAL;
tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL | NOFLSH | TOSTOP | IEXTEN);
#elif 0
tio.c_iflag = PARMRK | IGNPAR;
tio.c_oflag = 0;
tio.c_cflag = tio.c_cflag | CLOCAL | CREAD;
tio.c_lflag = 0;
#endif
if (tcsetattr (port, TCSANOW, &tio)) { /* set the terminal attributes */
sim_error_serial ("tcsetattr", errno); /* function failed; report unexpected error */
close (port); /* close the port */

View File

@@ -336,6 +336,7 @@
#include "sim_sock.h"
#include "sim_timer.h"
#include "sim_tmxr.h"
#include "sim_ether.h"
#include "scp.h"
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
@@ -422,6 +423,43 @@
#define TNOS_DONT 001 /* Don't has been sent */
#define TNOS_WONT 002 /* Won't has been sent */
/* Lifted from ddcmp.c in the framer firmware */
struct status_msg_t
{
uint8 dc1;
uint8 on; /* "on" flags */
uint16 mflags;
uint32 speed;
uint32 txspeed;
uint32 rxframes;
uint32 rxbytes;
uint32 txframes;
uint32 txbytes;
uint32 hcrc_err;
uint32 crc_err;
uint32 len_err;
uint32 nobuf_err;
uint32 last_cmd_sts; /* Response code from last command */
uint32 freq; /* Measured frequency */
char version[64];
};
#define ON_ACT 1
#define ON_SYN 2
#define ON_CLKOK 4
/* This struct is internal to sim_tmxr, used when a line is attached
* to a DDCMP synchronous framer device (a USB peripheral that looks
* like an Ethernet interface).
*/
typedef struct framer_data {
ETH_DEV *eth; /* Ethernet device pointer if framer */
uint16 fmode; /* Framer mode from attach command */
uint32 fspeed; /* Framer link speed from attach command */
struct status_msg_t status; /* Last received status message */
int status_cnt; /* Count of status messages seen */
t_bool connect_pending; /* True if connected not yet reported */
} FRAMER;
static BITFIELD tmxr_modem_bits[] = {
BIT(DTR), /* Data Terminal Ready */
BIT(RTS), /* Request To Send */
@@ -445,6 +483,9 @@ static u_char mantra[] = { /* Telnet Option Negotiation Mantra
#define TMXR_LINE_DISABLED (-1)
/* Local routines */
static void tmxr_setup_framer(TMLN *line, ETH_PACK *packet, int len);
static int tmxr_framer_read (TMLN *line, char *buf, int nbytes);
static int tmxr_framer_write (TMLN *line, const char *buf, int32 length);
static void tmxr_add_to_open_list (TMXR* mux);
@@ -685,8 +726,12 @@ if (lp->loopback)
return loop_read (lp, &(lp->rxb[i]), length);
if (lp->serport) /* serial port connection? */
return sim_read_serial (lp->serport, &(lp->rxb[i]), length, &(lp->rbr[i]));
else /* Telnet connection */
return sim_read_sock (lp->sock, &(lp->rxb[i]), length);
else {
if (lp->framer)
return tmxr_framer_read (lp, &(lp->rxb[i]), length);
else /* Telnet connection */
return sim_read_sock (lp->sock, &(lp->rxb[i]), length);
}
}
@@ -712,23 +757,27 @@ if (lp->serport) { /* serial port connectio
written = sim_write_serial (lp->serport, &(lp->txb[i]), length);
}
else {
if (lp->sock) { /* Telnet connection */
written = sim_write_sock (lp->sock, &(lp->txb[i]), length);
if (written == SOCKET_ERROR) { /* did an error occur? */
lp->txdone = TRUE;
if (lp->datagram)
return written; /* ignore errors on datagram sockets */
else
return -1; /* return error indication */
}
}
if (lp->framer)
written = tmxr_framer_write (lp, &(lp->txb[i]), length);
else {
if ((lp->conn == TMXR_LINE_DISABLED) ||
((lp->conn == 0) && lp->txbfd)){
written = length; /* Count here output timing is correct */
if (lp->conn == TMXR_LINE_DISABLED)
lp->txdrp += length; /* Record as having been dropped on the floor */
if (lp->sock) { /* Telnet connection */
written = sim_write_sock (lp->sock, &(lp->txb[i]), length);
if (written == SOCKET_ERROR) { /* did an error occur? */
lp->txdone = TRUE;
if (lp->datagram)
return written; /* ignore errors on datagram sockets */
else
return -1; /* return error indication */
}
}
else {
if ((lp->conn == TMXR_LINE_DISABLED) ||
((lp->conn == 0) && lp->txbfd)){
written = length; /* Count here output timing is correct */
if (lp->conn == TMXR_LINE_DISABLED)
lp->txdrp += length; /* Record as having been dropped on the floor */
}
}
}
}
@@ -1091,6 +1140,9 @@ if (mp->master) {
for (j = 0; j < mp->lines; j++, i++) { /* find next avail line */
lp = mp->ldsc + j; /* get pointer to line descriptor */
if (lp->framer)
continue;
if ((lp->conn == FALSE) && /* is the line available? */
(lp->destination == NULL) &&
(lp->master == 0) &&
@@ -1172,6 +1224,17 @@ for (i = 0; i < mp->lines; i++) { /* check each line in se
return i;
}
/* Framer: report connected. */
if (lp->framer) {
if (lp->framer->connect_pending) {
/* Say "connected" when first asked */
lp->framer->connect_pending = FALSE;
lp->conn = TRUE; /* record connection */
return i;
}
continue;
}
/* Don't service network connections for loopbacked lines */
if (lp->loopback)
@@ -1660,10 +1723,14 @@ return SCPE_OK;
Implementation note:
If a line is connected to a serial port, then these values affect
and reflect the state of the serial port. If the line is connected
to a network socket (or could be) then the network session state is
set, cleared and/or returned.
If a line is connected to a serial port, then these values
affect and reflect the state of the serial port. If the line
is connected to a network socket (or could be) then the network
session state is set, cleared and/or returned. If the line is
connected to a DDCMP sync framer, only DTR and RTS set/clear
are acted on, and the returned modem state bits are constructed
based on the framer state. For the framer, setting DTR starts
the framer, and clearing DTR stops it.
*/
t_stat tmxr_set_get_modem_bits (TMLN *lp, int32 bits_to_set, int32 bits_to_clear, int32 *status_bits)
{
@@ -1676,6 +1743,37 @@ if ((bits_to_set & ~(TMXR_MDM_OUTGOING)) || /* Assure only settable bits
(bits_to_clear & ~(TMXR_MDM_OUTGOING)) ||
(bits_to_set & bits_to_clear)) /* and can't set and clear the same bits */
return SCPE_ARG;
if (lp->framer) {
/* DDCMP framer attached, ignore set except for DTR and RTS.
* Given the most recently received framer status, report DSR if
* the framer is currently on, and CTS and Carrier Detect if a
* carrier has been received.
*/
bits_to_set &= TMXR_MDM_DTR | TMXR_MDM_RTS;
bits_to_clear &= TMXR_MDM_DTR | TMXR_MDM_RTS;
if ((bits_to_set & TMXR_MDM_DTR) && !(lp->modembits & TMXR_MDM_DTR)) {
/* DTR being set, start framer if we're using one. Use DMC
* mode for now.
*/
tmxr_start_framer (lp, TRUE);
}
else {
if ((bits_to_clear & TMXR_MDM_DTR) && (lp->modembits & TMXR_MDM_DTR))
/* DTR being cleared, stop framer if we're using one. */
tmxr_stop_framer (lp);
}
incoming_state = lp->modembits | bits_to_set;
incoming_state &= ~bits_to_clear;
if (lp->framer->status.on)
incoming_state |= TMXR_MDM_DSR;
if (lp->framer->status.on & ON_SYN)
/* Carrier detected */
incoming_state |= TMXR_MDM_CTS | TMXR_MDM_DCD;
lp->modembits = incoming_state;
if (status_bits)
*status_bits = incoming_state;
return SCPE_OK;
}
before_modem_bits = lp->modembits;
lp->modembits |= bits_to_set;
lp->modembits &= ~bits_to_clear;
@@ -2023,7 +2121,7 @@ TMLN *lp;
tmxr_debug_trace (mp, "tmxr_poll_rx()");
for (i = 0; i < mp->lines; i++) { /* loop thru lines */
lp = mp->ldsc + i; /* get line desc */
if (!(lp->sock || lp->serport || lp->loopback) ||
if (!(lp->sock || lp->serport || lp->loopback || lp->framer) ||
!(lp->rcve)) /* skip if not connected */
continue;
@@ -2031,9 +2129,11 @@ for (i = 0; i < mp->lines; i++) { /* loop thru lines */
if (lp->rxbpi == 0) /* need input? */
nbytes = tmxr_read (lp, /* yes, read */
lp->rxbsz - TMXR_GUARD); /* leave spc for Telnet cruft */
else if (lp->tsta) /* in Telnet seq? */
nbytes = tmxr_read (lp, /* yes, read to end */
lp->rxbsz - lp->rxbpi);
else {
if (lp->tsta) /* in Telnet seq? */
nbytes = tmxr_read (lp, /* yes, read to end */
lp->rxbsz - lp->rxbpi);
}
if (nbytes < 0) { /* line error? */
if (!lp->datagram) { /* ignore errors reading UDP sockets */
@@ -2538,6 +2638,17 @@ return 0; /* not done */
static void _mux_detach_line (TMLN *lp, t_bool close_listener, t_bool close_connecting)
{
if (lp->framer) {
/* DDCMP framer in use, close that up. Begin by making sure it is
* stopped.
*/
tmxr_stop_framer (lp);
/* Finished with the framer's Ethernet interface */
eth_close (lp->framer->eth);
free (lp->framer->eth);
free (lp->framer);
lp->framer = NULL;
}
if (close_listener && lp->master) {
sim_close_sock (lp->master);
lp->master = 0;
@@ -2700,6 +2811,21 @@ if (lp->o_uptr)
return SCPE_OK;
}
static const char* _tmxr_getname(int number, char* name)
{
ETH_LIST list[ETH_MAX_DEVICE];
int count = eth_devices(ETH_MAX_DEVICE, list, TRUE);
if ((number < 0) || (count <= number))
return NULL;
if (list[number].eth_api != ETH_API_PCAP) {
sim_printf ("Tmxr: Synchronous line device not found. You may need to run as root\n");
return NULL;
}
strcpy(name, list[number].name);
return name;
}
/* Open a master listening socket (and all of the other variances of connections).
@@ -2719,6 +2845,12 @@ int32 i, line, nextline = -1;
char tbuf[CBUFSIZE], listen[CBUFSIZE], destination[CBUFSIZE],
logfiletmpl[CBUFSIZE], buffered[CBUFSIZE], hostport[CBUFSIZE],
port[CBUFSIZE], option[CBUFSIZE], speed[CBUFSIZE], dev_name[CBUFSIZE];
char framer[CBUFSIZE],fr_eth[CBUFSIZE];
int num;
int8 fr_mode;
int32 fr_speed;
FRAMER *framer_s;
ETH_DEV *eth;
SOCKET sock;
SERHANDLE serport;
CONST char *tptr = cptr;
@@ -2752,6 +2884,7 @@ while (*tptr) {
memset(port, '\0', sizeof(port));
memset(option, '\0', sizeof(option));
memset(speed, '\0', sizeof(speed));
memset(framer, '\0', sizeof(framer));
nolog = loopback = disabled = FALSE;
datagram = mp->datagram;
packet = mp->packet;
@@ -2852,6 +2985,13 @@ while (*tptr) {
strlcpy (destination, cptr, sizeof(destination));
continue;
}
if (0 == MATCH_CMD (gbuf, "SYNC")) {
if ((NULL == cptr) || ('\0' == *cptr))
return sim_messagef (SCPE_2FARG, "Missing Framer Specifier\n");
strlcpy (framer, cptr, sizeof(framer));
nomessage = notelnet = datagram = TRUE;
continue;
}
if (0 == MATCH_CMD (gbuf, "DISABLED")) {
if ((NULL != cptr) && ('\0' != *cptr))
return sim_messagef (SCPE_2FARG, "Unexpected Disabled Specifier: %s\n", cptr);
@@ -2922,11 +3062,13 @@ while (*tptr) {
}
}
if (disabled) {
if (destination[0] || listen[0] || loopback)
return sim_messagef (SCPE_ARG, "Can't disable line with%s%s%s%s%s\n", destination[0] ? " CONNECT=" : "", destination, listen[0] ? " " : "", listen, loopback ? " LOOPBACK" : "");
if (destination[0] || listen[0] || loopback || framer[0])
return sim_messagef (SCPE_ARG, "Can't disable line with%s%s%s%s%s%s%s\n", destination[0] ? " CONNECT=" : "", destination, listen[0] ? " " : "", listen, loopback ? " LOOPBACK" : "", framer[0] ? " SYNC=" : "", framer);
}
if (destination[0]) {
/* Validate destination */
if (framer[0])
return sim_messagef (SCPE_ARG, "Can't combine CONNECT=%s with SYNC=%s\n", destination, framer);
serport = sim_open_serial (destination, NULL, &r);
if (serport != INVALID_HANDLE) {
sim_close_serial (serport);
@@ -2961,9 +3103,62 @@ while (*tptr) {
return sim_messagef (SCPE_ARG, "Invalid destination: %s\n", hostport);
}
}
if (framer[0]) {
if (listen[0] || loopback || (!notelnet) || (!datagram))
return sim_messagef (SCPE_ARG, "Can't combined SYNC=%s with%s%s%s%s%s\n", framer,
listen[0] ? " " : "", listen, loopback ? " LOOPBACK" : "",
notelnet ? "" : " TELNET",
datagram ? "" : " STREAM");
/* Validate framer spec */
cptr = get_glyph_nc (framer, fr_eth, ':');
cptr = get_glyph (cptr, option, ':');
if (0 == MATCH_CMD (option, "INTEGRAL") ||
0 == MATCH_CMD (option, "COAX"))
fr_mode = 1;
else {
if (0 == MATCH_CMD (option, "LOOPBACK"))
fr_mode = 1 | 4; /* Integral modem, loopback */
else
if (0 == MATCH_CMD (option, "RS232_DCE"))
fr_mode = 2;
else
if (0 == MATCH_CMD (option, "RS232_DTE"))
fr_mode = 0;
else
return sim_messagef (SCPE_ARG, "Invalid framer mode: %s\n", cptr);
}
/* Speed is a third value in the SYNC argument. We don't
* use the SPEED parameter because that only accepts the
* standard UART rates, which for the most part are not normal
* DDCMP line rates.
*/
fr_speed = 0;
if (cptr)
fr_speed = atoi (cptr);
/* Note that the framer ignores the speed parameter for DTE
* mode, but we require it here in order to have a speed value
* to control the scheduling machinery. It would be possible
* to make it optional and default it to some useable value
* like 56k, or to default it that way and then later set it
* according to the measured data rate reported by the framer.
* For now, don't bother.
*
* Also, while the minimum speed is usually 500 bps, it is 56k
* for integral modem mode -- the transformer coupling does
* not work reliably at speeds lower than that, and this
* matches the lowest speed supported by DEC hardware for that
* interface type.
*/
if (fr_speed < 500 || fr_speed > 1000000 ||
(fr_speed < 56000 && (fr_mode & 1))) {
return sim_messagef (SCPE_ARG, "Invalid framer speed %d\n", fr_speed);
}
}
if (line == -1) {
if (disabled)
return sim_messagef (SCPE_ARG, "Must specify line to disable\n");
if (framer[0])
return sim_messagef (SCPE_ARG, "Must specify line for framer\n");
if (modem_control != mp->modem_control)
return SCPE_ARG;
if (logfiletmpl[0]) {
@@ -3016,6 +3211,8 @@ while (*tptr) {
}
}
}
if (lp->framer)
continue; /* skip framer lines */
if ((listen[0]) && (!datagram)) {
sock = sim_master_sock (listen, &r); /* make master socket */
if (r)
@@ -3145,6 +3342,57 @@ while (*tptr) {
else { /* line specific attach */
lp = &mp->ldsc[line];
lp->mp = mp;
if (framer[0]) {
/* translate name of type "sync<num>" to real eth device name */
if ((strlen(fr_eth) == 5 || strlen(fr_eth) == 6)
&& (tolower(fr_eth[0]) == 's')
&& (tolower(fr_eth[1]) == 'y')
&& (tolower(fr_eth[2]) == 'n')
&& (tolower(fr_eth[3]) == 'c')
&& isdigit(fr_eth[4])
&& (strlen(fr_eth) == 5 || isdigit(fr_eth[5]))
) {
num = atoi(&fr_eth[4]);
if (_tmxr_getname(num, fr_eth) == NULL) /* didn't translate */
return SCPE_OPENERR;
}
/* Open the Ethernet device */
framer_s = (FRAMER *)malloc (sizeof (FRAMER));
memset (framer_s, 0, sizeof (*framer_s));
eth = (ETH_DEV *)malloc (sizeof (ETH_DEV));
memset (eth, 0, sizeof (*eth));
eth->dptr = mp->dptr;
framer_s->eth = eth;
framer_s->connect_pending = TRUE;
r = eth_open (eth, fr_eth, mp->dptr, 0);
if (r != SCPE_OK) {
sim_messagef (r, "Eth open error %d\n", r);
free (eth);
free (framer_s);
return r;
}
/* Set the filters: our address, not all multi, not promiscuous */
r = eth_filter (eth, 1, &(eth->host_nic_phy_hw_addr), 0, 0);
if (r != SCPE_OK) {
sim_messagef (r, "Eth set address filter error %d\n", r);
eth_close (eth);
free (eth);
free (framer_s);
return r;
}
lp = &mp->ldsc[line];
lp->framer = framer_s;
lp->datagram = lp->notelnet = TRUE;
/* Remember these parameters for later; the framer is
* started separately; in the DMC/DMP emulation this is
* done at DDCMP startup to allow a DMP driver to select
* the mode via the device API. */
framer_s->fmode = fr_mode;
framer_s->fspeed = fr_speed;
/* Set the scheduling parameters from the line speed */
lp->txdeltausecs = lp->rxdeltausecs = (uint32) (8000000 / fr_speed);
tmxr_init_line (lp); /* initialize line state */
}
if (logfiletmpl[0]) {
sim_close_logfile (&lp->txlogref);
lp->txlog = NULL;
@@ -3182,7 +3430,7 @@ while (*tptr) {
}
if ((listen[0]) && (!datagram)) {
if ((mp->lines == 1) && (mp->master))
return sim_messagef (SCPE_ARG, "Single Line MUX can have either line specific OR MUS listener but NOT both\n");
return sim_messagef (SCPE_ARG, "Single Line MUX can have either line specific OR MUX listener but NOT both\n");
sock = sim_master_sock (listen, &r); /* make master socket */
if (r)
return sim_messagef (SCPE_ARG, "Invalid Listen Specification: %s\n", listen);
@@ -3219,34 +3467,36 @@ while (*tptr) {
tmxr_report_connection (mp, lp); /* report the connection to the line */
}
else {
lp->datagram = datagram;
if (datagram) {
if (listen[0]) {
lp->port = (char *)realloc (lp->port, 1 + strlen (listen));
strcpy (lp->port, listen); /* save port */
if (!lp->framer) {
lp->datagram = datagram;
if (datagram) {
if (listen[0]) {
lp->port = (char *)realloc (lp->port, 1 + strlen (listen));
strcpy (lp->port, listen); /* save port */
}
else
return sim_messagef (SCPE_ARG, "Missing listen port for Datagram socket\n");
}
sock = sim_connect_sock_ex (datagram ? listen : NULL, hostport, "localhost", NULL, (datagram ? SIM_SOCK_OPT_DATAGRAM : 0) |
(packet ? SIM_SOCK_OPT_NODELAY : 0));
if (sock != INVALID_SOCKET) {
_mux_detach_line (lp, FALSE, TRUE);
lp->destination = (char *)malloc(1+strlen(hostport));
strcpy (lp->destination, hostport);
if (!lp->modem_control || (lp->modembits & TMXR_MDM_DTR)) {
lp->connecting = sock;
lp->ipad = (char *)malloc (1 + strlen (lp->destination));
strcpy (lp->ipad, lp->destination);
}
else
sim_close_sock (sock);
lp->notelnet = notelnet;
lp->nomessage = nomessage;
tmxr_init_line (lp); /* init the line state */
}
else
return sim_messagef (SCPE_ARG, "Missing listen port for Datagram socket\n");
return sim_messagef (SCPE_ARG, "Can't open %s socket on %s%s%s\n", datagram ? "Datagram" : "Stream", datagram ? listen : "", datagram ? "<->" : "", hostport);
}
sock = sim_connect_sock_ex (datagram ? listen : NULL, hostport, "localhost", NULL, (datagram ? SIM_SOCK_OPT_DATAGRAM : 0) |
(packet ? SIM_SOCK_OPT_NODELAY : 0));
if (sock != INVALID_SOCKET) {
_mux_detach_line (lp, FALSE, TRUE);
lp->destination = (char *)malloc(1+strlen(hostport));
strcpy (lp->destination, hostport);
if (!lp->modem_control || (lp->modembits & TMXR_MDM_DTR)) {
lp->connecting = sock;
lp->ipad = (char *)malloc (1 + strlen (lp->destination));
strcpy (lp->ipad, lp->destination);
}
else
sim_close_sock (sock);
lp->notelnet = notelnet;
lp->nomessage = nomessage;
tmxr_init_line (lp); /* init the line state */
}
else
return sim_messagef (SCPE_ARG, "Can't open %s socket on %s%s%s\n", datagram ? "Datagram" : "Stream", datagram ? listen : "", datagram ? "<->" : "", hostport);
}
}
if (loopback) {
@@ -4305,7 +4555,7 @@ TMLN *lp;
for (i = 0; i < mp->lines; i++) { /* loop thru conn */
lp = mp->ldsc + i;
if (!lp->destination && lp->sock) { /* not serial and is connected? */
if (!lp->destination && lp->sock) { /* not serial and is connected? */
tmxr_report_disconnection (lp); /* report disconnection */
tmxr_reset_ln (lp); /* disconnect line */
}
@@ -4978,7 +5228,7 @@ static const char *dsab = "off";
if (ln >= 0)
fprintf (st, "Line %d:", ln);
if ((!lp->sock) && (!lp->connecting) && (!lp->serport))
if ((!lp->sock) && (!lp->connecting) && (!lp->serport) && (!lp->framer))
fprintf (st, " not connected\n");
else {
if (ln >= 0)
@@ -5410,6 +5660,35 @@ if (any == 0)
return SCPE_OK;
}
/* Show synchronous devices */
t_stat tmxr_show_sync_devices (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char *desc)
{
return tmxr_show_sync (st, uptr, val, NULL);
}
t_stat tmxr_show_sync (FILE* st, UNIT* uptr, int32 val, CONST void *desc)
{
ETH_LIST list[ETH_MAX_DEVICE];
int number, fcnt = 0;
number = eth_devices(ETH_MAX_DEVICE, list, TRUE);
fprintf(st, "DDCMP synchronous link devices:\n");
if (number == -1)
fprintf(st, " network support not available in simulator\n");
else
if (number == 0)
fprintf(st, " no dddcmp synchronous link devices are available\n");
else {
int i;
for (i=0; i<number; i++) {
fprintf(st," sync%d\t%s\n", i, list[i].name);
fcnt++;
}
}
return SCPE_OK;
}
/* Show number of lines */
t_stat tmxr_show_lines (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
@@ -5782,3 +6061,159 @@ if (tmxr->lines > 1) {
}
return stat;
}
static int framer_await_status (TMLN *line, int cnt)
{
int i, stat, xtry, flen;
ETH_PACK framer_rpkt;
i = line->framer->status_cnt;
xtry = 0;
while (xtry < 5) {
stat = eth_read (line->framer->eth, &framer_rpkt, NULL);
if (stat) {
flen = framer_rpkt.msg[14] + (framer_rpkt.msg[15] << 8);
if (framer_rpkt.msg[18] == 021) {
/* DC1, so it's a framer status message. Save it. */
if (flen > sizeof (struct status_msg_t))
flen = sizeof (struct status_msg_t);
memcpy (&line->framer->status, framer_rpkt.msg + 18, flen);
line->framer->status_cnt++;
continue;
}
}
if (i != line->framer->status_cnt)
return 1;
xtry++;
sim_os_ms_sleep (50);
}
tmxr_debug_trace_line (line, "no status received\n");
return 0;
}
static void tmxr_setup_framer(TMLN *line, ETH_PACK *packet, int len)
{
/* First clear everything */
memset (packet, 0, sizeof (*packet));
/* Set up the MAC header */
memcpy (&packet->msg[0], line->framer->eth->physical_addr, 6);
memcpy (&packet->msg[6], line->framer->eth->physical_addr, 6);
/* Framer address is one higher than host interface MAC address */
packet->msg[5]++;
/* Set ethertype 60-06 */
packet->msg[12] = 0x60;
packet->msg[13] = 0x06;
/* Set length */
packet->msg[14] = len & 0xff;
packet->msg[15] = len >> 8;
/* Set length and padded length */
len += 16; /* Add in header length */
if (len < 60)
len = 60;
packet->len = len;
packet->crc_len = len + 4;
}
void tmxr_start_framer (TMLN *line, int dmc_mode)
{
t_stat ret;
int cnt;
ETH_PACK framer_start;
if (!line->framer)
/* Not a framer line, NOP */
return;
tmxr_setup_framer (line, &framer_start, 8);
framer_start.msg[16] = 0x11;
framer_start.msg[17] = 1; /* Command 1: start framer */
/* Set DMC mode (DDCMP 3.1) if requested */
if (dmc_mode)
line->framer->fmode |= 32;
else
line->framer->fmode &= ~32;
/* Set mode in the command buffer */
framer_start.msg[18] = line->framer->fmode & 0xff;
framer_start.msg[19] = line->framer->fmode >> 8;
/* Set speed in the command buffer */
framer_start.msg[20] = line->framer->fspeed & 0xff;
framer_start.msg[21] = (line->framer->fspeed >> 8) & 0xff;
framer_start.msg[22] = (line->framer->fspeed >> 16) & 0xff;
framer_start.msg[23] = line->framer->fspeed >> 24;
/* Send the request */
cnt = line->framer->status_cnt;
ret = eth_write (line->framer->eth, &framer_start, NULL);
framer_await_status (line, cnt);
}
void tmxr_stop_framer (TMLN *line)
{
t_stat ret;
int cnt;
ETH_PACK framer_stop;
if (!line->framer)
/* Not a framer line, NOP */
return;
tmxr_setup_framer (line, &framer_stop, 2);
framer_stop.msg[16] = 0x11;
framer_stop.msg[17] = 2; /* Command 2: stop framer */
/* Send the request */
cnt = line->framer->status_cnt;
ret = eth_write (line->framer->eth, &framer_stop, NULL);
/* Mark the framer off right now */
line->framer->status.on = 0;
framer_await_status (line, cnt);
}
static int tmxr_framer_read (TMLN *line, char *buf, int nbytes)
{
int stat, flen, fstat;
ETH_PACK framer_rpkt;
while (1) {
stat = eth_read (line->framer->eth, &framer_rpkt, NULL);
if (!stat)
return 0;
/* Size reported by framer includes status, subtract that */
flen = (framer_rpkt.msg[14] + (framer_rpkt.msg[15] << 8)) - 2;
fstat = framer_rpkt.msg[16] + (framer_rpkt.msg[17] << 8);
if (framer_rpkt.msg[18] == 021) {
/* DC1, so it's a framer status message. Save it. */
if (flen > sizeof (struct status_msg_t))
flen = sizeof (struct status_msg_t);
memcpy (&line->framer->status,
framer_rpkt.msg + 18, flen);
/* report interesting bits */
sim_debug (TMXR_DBG_RCV, line->dptr,
"framer status, on %d, last_cmd_sts %d\n",
line->framer->status.on,
line->framer->status.last_cmd_sts);
line->framer->status_cnt++;
/* Look for another packet */
continue;
}
else {
/* Real DDCMP packet. Pass the buffer pointer/len */
if (flen > nbytes)
flen = nbytes;
memcpy (buf, framer_rpkt.msg + 18, flen);
return flen;
}
}
}
static int tmxr_framer_write (TMLN *line, const char *buf, int32 length)
{
t_stat ret;
ETH_PACK framer_tx;
tmxr_setup_framer (line, &framer_tx, length);
memcpy (&framer_tx.msg[16], buf, length);
/* Send the request */
ret = eth_write (line->framer->eth, &framer_tx, NULL);
/* Always report the whole thing was written */
return length;
}

View File

@@ -123,7 +123,8 @@ typedef struct SERPORT *SERHANDLE;
#define TMLN_SPD_80000_BPS 125 /* usec per character */
#define TMLN_SPD_115200_BPS 86 /* usec per character */
/* Internal struct */
struct framer_data;
typedef struct tmln TMLN;
typedef struct tmxr TMXR;
@@ -206,6 +207,7 @@ struct tmln {
DEVICE *dptr; /* line specific device */
EXPECT expect; /* Expect rules */
SEND send; /* Send input state */
struct framer_data *framer; /* ddcmp framer data */
};
struct tmxr {
@@ -297,6 +299,8 @@ t_stat tmxr_show_summ (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat tmxr_show_cstat (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat tmxr_show_lines (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat tmxr_show_open_devices (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char* desc);
t_stat tmxr_show_sync_devices (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char *desc);
t_stat tmxr_show_sync (FILE* st, UNIT* uptr, int32 val, CONST void *desc);
t_stat tmxr_flush_log_files (void);
t_stat tmxr_activate (UNIT *uptr, int32 interval);
t_stat tmxr_activate_abs (UNIT *uptr, int32 interval);
@@ -317,6 +321,10 @@ t_stat tmxr_shutdown (void);
t_stat tmxr_sock_test (DEVICE *dptr);
t_stat tmxr_start_poll (void);
t_stat tmxr_stop_poll (void);
/* Framer support. These are a NOP if called on a non-framer line. */
void tmxr_start_framer (TMLN *line, int dmc_mode);
void tmxr_stop_framer (TMLN *line);
void _tmxr_debug (uint32 dbits, TMLN *lp, const char *msg, char *buf, int bufsize);
#define tmxr_debug(dbits, lp, msg, buf, bufsize) do {if (sim_deb && (lp)->mp && (lp)->mp->dptr && ((dbits) & (lp)->mp->dptr->dctrl)) _tmxr_debug (dbits, lp, msg, buf, bufsize); } while (0)
#define tmxr_debug_msg(dbits, lp, msg) do {if (sim_deb && (lp)->mp && (lp)->mp->dptr && ((dbits) & (lp)->mp->dptr->dctrl)) sim_debug (dbits, (lp)->mp->dptr, "%s", msg); } while (0)

View File

@@ -2044,15 +2044,25 @@ while (vid_active) {
/* EVENT_SCREENSHOT to take a screenshot */
/* EVENT_BEEP to emit a beep sound */
while (vid_active && event.user.code) {
vptr = vid_get_event_window (&event, event.user.windowID);
if (vptr == NULL)
/* Handle Beep first since it isn't a window oriented event */
if (event.user.code == EVENT_BEEP) {
vid_beep_event ();
event.user.code = 0; /* Mark as done */
continue;
}
vptr = vid_get_event_window (&event, event.user.windowID);
if (vptr == NULL) {
sim_debug (SIM_VID_DBG_VIDEO, vptr->vid_dev, "vid_thread() - Ignored event not bound to a window\n");
event.user.code = 0; /* Mark as done */
break;
}
if (event.user.code == EVENT_REDRAW) {
vid_update (vptr);
event.user.code = 0; /* Mark as done */
if (0) while (SDL_PeepEvents (&event, 1, SDL_GETEVENT, SDL_USEREVENT, SDL_USEREVENT)) {
if (event.user.code == EVENT_REDRAW) {
/* Only do a single video update between waiting for events */
while (SDL_PeepEvents (&event, 1, SDL_GETEVENT, SDL_USEREVENT, SDL_USEREVENT)) {
if ((event.user.code == EVENT_REDRAW) &&
(vptr == vid_get_event_window (&event, event.user.windowID))) {
/* Only do a single video update to the same window between waiting for events */
sim_debug (SIM_VID_DBG_VIDEO, vptr->vid_dev, "vid_thread() - Ignored extra REDRAW Event\n");
event.user.code = 0; /* Mark as done */
continue;