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:
parent
389a8ade1f
commit
68034af94a
174
H316/h316_hi.c
174
H316/h316_hi.c
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user