1
0
mirror of https://github.com/simh/simh.git synced 2026-01-11 23:52:58 +00:00

H316: Convert IMP long leaders to short, and vice versa.

This commit is contained in:
Lars Brinkhoff 2024-12-09 13:37:22 +01:00 committed by Mark Pizzolato
parent 389a8ade1f
commit 68034af94a
2 changed files with 170 additions and 7 deletions

View File

@ -105,6 +105,8 @@ void hi_rx_local (uint16 line, uint16 txnext, uint16 txcount);
t_stat hi_reset (DEVICE *dptr);
t_stat hi_attach (UNIT *uptr, CONST char *cptr);
t_stat hi_detach (UNIT *uptr);
t_stat hi_set_convert (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat hi_show_convert (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
@ -115,7 +117,7 @@ t_stat hi_detach (UNIT *uptr);
// Host interface data blocks ...
// The HIDB is our own internal data structure for each host. It keeps data
// about the TCP/IP connection, buffers, etc.
#define HI_HIDB(N) {FALSE, FALSE, 0, {0}, 0, 0, 0, 0, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 0, HI_TXBPS}
#define HI_HIDB(N) {FALSE, FALSE, 0, {0}, 0, 0, 0, FALSE, 0, 0, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 0, HI_TXBPS}
HIDB hi1_db = HI_HIDB(1), hi2_db = HI_HIDB(2);
HIDB hi3_db = HI_HIDB(3), hi4_db = HI_HIDB(4);
@ -161,8 +163,9 @@ REG hi3_reg[] = HI_REG(3), hi4_reg[] = HI_REG(4);
// Host Device Modifiers ...
// These are the modifiers simh uses for the "SET MIxn" and "SHOW MIx" commands.
#define HI_MOD(N) { \
{ 0 } \
#define HI_MOD(N) { \
{ MTAB_XTD|MTAB_VDV, 0, NULL, "CONVERT", &hi_set_convert, &hi_show_convert, NULL }, \
{ MTAB_XTD|MTAB_VDV, 1, NULL, "NOCONVERT", &hi_set_convert, &hi_show_convert, NULL }, \
}
MTAB hi1_mod[] = HI_MOD(1), hi2_mod[] = HI_MOD(2);
MTAB hi3_mod[] = HI_MOD(3), hi4_mod[] = HI_MOD(4);
@ -196,6 +199,25 @@ UNIT *const hi_units [HI_NUM] = {&hi1_unit, &hi2_unit, &hi3_unit, &hi4_unit};
DIB *const hi_dibs [HI_NUM] = {&hi1_dib, &hi2_dib, &hi3_dib, &hi4_dib };
HIDB *const hi_hidbs [HI_NUM] = {&hi1_db, &hi2_db, &hi3_db, &hi4_db };
// Old message type field set to this to signal new format leader.
#define NEW_FORMAT_FLAG (15 << 8)
// 1822 message types (or subtypes).
#define LEADER_REGULAR 000
#define LEADER_UNCONTROLLED 003
#define LEADER_NOP 004
// 1822 new leader flags.
#define NLEADER_TRACE 010
#define NLEADER_OCTAL 004
#define NLEADER_FOR_IMP 252
#define NLEADER_PRIORITY 0200
// 1822 old leader flags.
#define OLEADER_PRIORITY 010
#define OLEADER_FOR_IMP 004
#define OLEADER_TRACE 002
#define OLEADER_OCTAL 001
////////////////////////////////////////////////////////////////////////////////
@ -235,6 +257,7 @@ void hi_reset_tx (uint16 host)
{
PHIDB(host)->iloop = PHIDB(host)->enabled = PHIDB(host)->full = FALSE;
PHIDB(host)->txtotal = 0;
PHIDB(host)->txfirst = TRUE;
CLR_TX_IRQ(host); CLR_TX_IEN(host);
}
@ -309,6 +332,123 @@ void hi_debug_msg (uint16 line, uint16 next, uint16 count, const char *ptext)
///////////////// T R A N S M I T A N D R E C E I V E //////////////////
////////////////////////////////////////////////////////////////////////////////
// Convert 1822 long header from host, to short leader for IMP.
static int16 hi_convert_long_to_short(uint16 line, int16 count)
{
uint16 nflags, mtype, htype, host, imp, id, stype, length;
uint16 oflags;
uint16 *data = PHIDB(line)->rxdata;
if (count == 0)
return 0;
if (count < 7 || (data[1] & 0x0F00) != NEW_FORMAT_FLAG)
return count; // This is not a long leader message.
nflags = (data[2] & 0x0F00) >> 8;
mtype = data[2] & 0xFF;
htype = (data[3] & 0xFF00) >> 8;
host = data[3] & 0xFF;
imp = data[4];
id = (data[5] & 0xFFF0) >> 4;
stype = data[5] & 0x000F;
length = data[6];
// Keep track of padding.
if (mtype == LEADER_NOP)
PHIDB(line)->padding = stype;
// Sorry, can't handle these addresses.
if (host > 3)
return 0;
if (imp > 63)
return 0;
if (mtype == LEADER_REGULAR && stype == LEADER_UNCONTROLLED)
mtype = LEADER_UNCONTROLLED, stype = 0;
else if (mtype == LEADER_NOP)
stype = 0;
oflags = 0;
if (nflags & NLEADER_TRACE)
oflags |= OLEADER_TRACE;
if (nflags & NLEADER_OCTAL)
oflags |= OLEADER_OCTAL;
if (host >= NLEADER_FOR_IMP) {
oflags |= OLEADER_FOR_IMP;
host -= NLEADER_FOR_IMP;
}
if (htype & NLEADER_PRIORITY)
oflags |= OLEADER_PRIORITY;
oflags <<= 12;
mtype <<= 8;
host <<= 6;
id <<= 4;
data[1] = oflags | mtype | host | imp;
data[2] = id | stype;
if (mtype == LEADER_REGULAR) {
count -= 4 + PHIDB(line)->padding;
memmove(&data[3], &data[7 + PHIDB(line)->padding], 2 * count);
} else {
count = 3;
}
return count;
}
// Convert 1822 short header from IMP, to long leader for host.
static uint16 hi_convert_short_to_long(uint16 line, uint16 *data, uint16 count)
{
uint16 oflags, mtype, host, imp, id, stype;
uint16 nflags = 0, htype = 0, length = 0;
oflags = (data[1] & 0xF000) >> 12;
mtype = (data[1] & 0x0F00) >> 8;
host = (data[1] & 0x00C0) >> 6;
imp = data[1] & 0x003F;
id = (data[2] & 0xFFF0) >> 4;
stype = data[2] & 0x000F;
if (mtype == LEADER_REGULAR) {
memmove(&data[7 + PHIDB(line)->padding], &data[3], 2 * (count - 3));
memset(&data[7], 0, 2 * PHIDB(line)->padding);
length = 16 * (count - 3);
count += PHIDB(line)->padding;
}
count += 4;
if (oflags & OLEADER_PRIORITY)
htype |= NLEADER_PRIORITY;
htype |= 7;
if (oflags & OLEADER_FOR_IMP)
host += NLEADER_FOR_IMP;
if (oflags & OLEADER_TRACE)
nflags |= NLEADER_TRACE;
if (oflags & OLEADER_OCTAL)
nflags |= OLEADER_OCTAL;
if (mtype == LEADER_REGULAR)
stype = 0;
else if (mtype == LEADER_UNCONTROLLED)
mtype = LEADER_REGULAR, stype = LEADER_UNCONTROLLED;
else if (mtype == LEADER_NOP)
stype = 0;
nflags <<= 8;
htype <<= 8;
id <<= 4;
data[1] = NEW_FORMAT_FLAG;
data[2] = nflags | mtype;
data[3] = htype | host;
data[4] = imp;
data[5] = id | stype;
data[6] = length;
return count;
}
// Start the transmitter ...
void hi_start_tx (uint16 line, uint16 flags)
{
@ -337,7 +477,7 @@ void hi_start_tx (uint16 line, uint16 flags)
// uint16 flags;
// uint16 data [MAXDATA - 1];
// Put the packet into a temp buffer for assembly.
uint16 *tmp = (uint16 *)malloc ((count + 1) * sizeof (*tmp));
uint16 *tmp = (uint16 *)malloc ((count + 1 + 4) * sizeof (*tmp));
uint16 i;
tmp [0] = flags;
@ -345,7 +485,11 @@ void hi_start_tx (uint16 line, uint16 flags)
tmp [0] |= PFLG_READY;
for (i = 0; i < count; i ++)
tmp [i + 1] = M [next+i];
ret = udp_send(PDEVICE(line), PHIDB(line)->link, tmp, count + 1);
count++;
if (PHIDB(line)->convert && PHIDB(line)->txfirst)
count = hi_convert_short_to_long(line, tmp, count);
PHIDB(line)->txfirst = !!(flags & PFLG_FINAL);
ret = udp_send(PDEVICE(line), PHIDB(line)->link, tmp, count);
free (tmp);
if (ret != SCPE_OK && ret != 66) hi_link_error(line);
}
@ -426,6 +570,7 @@ void hi_poll_rx (uint16 line)
} else {
// Get a new UDP packet.
count = udp_receive(PDEVICE(line), PHIDB(line)->link, PHIDB(line)->rxdata, MAXDATA);
if (PHIDB(line)->convert) count = hi_convert_long_to_short(line, count);
PHIDB(line)->eom = FALSE;
PHIDB(line)->rxsize = count;
if (count == 0) { return; }
@ -433,7 +578,7 @@ void hi_poll_rx (uint16 line)
// Make note of the host ready bit.
PHIDB(line)->ready = !! (PHIDB(line)->rxdata[0] & PFLG_READY);
// Exclude the flags from the count.
PHIDB(line)->rxnext = 1; count--;
PHIDB(line)->rxnext = 1; count--;
if (count == 0) return;
PHIDB(line)->rxtotal++;
}
@ -445,10 +590,10 @@ void hi_poll_rx (uint16 line)
count = maxbuf;
}
hi_update_dmc(PDIB(line)->rxdmc, count);
hi_debug_msg (line, next, count, "received");
for (i = 0; i < count; i ++)
* (pdata + i) = PHIDB(line)->rxdata[PHIDB(line)->rxnext++];
hi_debug_msg (line, next, count, "received");
// Now would be a good time to worry about whether a receive is pending!
if (!PHIDB(line)->rxpending) {
@ -682,4 +827,19 @@ t_stat hi_detach (UNIT *uptr)
}
t_stat hi_set_convert (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
PHIDB(uptr->hline)->convert = !val;
return SCPE_OK;
}
t_stat hi_show_convert (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
{
if (PHIDB(uptr->hline)->convert)
fprintf (st, "Convert short leaders");
else
fprintf (st, "Do not convert short leaders");
return SCPE_OK;
}
#endif // #ifdef VM_IMPTIP from the very top

View File

@ -176,9 +176,12 @@ struct _HIDB {
uint16 rxdata[MAXDATA]; // UDP packet received.
uint16 rxnext; // Index to next word in UDP packet.
uint16 rxsize; // Size of UDP packet.
uint16 padding; // Padding for long leaders.
t_bool convert; // Convert between 1822 short/long messages.
// Transmitter (IMP -> HOST) data ...
uint32 txdelay; // RTC ticks until TX done interrupt
uint32 txtotal; // total host messages sent
t_bool txfirst; // First packet in a series
// Other data ...
t_bool iloop; // local loop back enabled
t_bool enabled; // TRUE if the host is enabled