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:
73
scp.c
73
scp.c
@@ -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", ð_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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
69
sim_ether.c
69
sim_ether.c
@@ -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 (ð_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];
|
||||
|
||||
@@ -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 */
|
||||
|
||||
101
sim_serial.c
101
sim_serial.c
@@ -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 */
|
||||
|
||||
547
sim_tmxr.c
547
sim_tmxr.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
10
sim_tmxr.h
10
sim_tmxr.h
@@ -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)
|
||||
|
||||
20
sim_video.c
20
sim_video.c
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user