@@ -105,6 +105,8 @@ void hi_rx_local (uint16 line, uint16 txnext, uint16 txcount);
105
105
t_stat hi_reset (DEVICE * dptr );
106
106
t_stat hi_attach (UNIT * uptr , CONST char * cptr );
107
107
t_stat hi_detach (UNIT * uptr );
108
+ t_stat hi_set_convert (UNIT * uptr , int32 val , CONST char * cptr , void * desc );
109
+ t_stat hi_show_convert (FILE * st , UNIT * uptr , int32 val , CONST void * desc );
108
110
109
111
110
112
@@ -115,7 +117,7 @@ t_stat hi_detach (UNIT *uptr);
115
117
// Host interface data blocks ...
116
118
// The HIDB is our own internal data structure for each host. It keeps data
117
119
// about the TCP/IP connection, buffers, etc.
118
- #define HI_HIDB (N ) {FALSE, FALSE, 0, {0}, 0, 0, 0, 0 , FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 0, HI_TXBPS}
120
+ #define HI_HIDB (N ) {FALSE, FALSE, 0, {0}, 0, 0, 0, FALSE, 0, 0, TRUE , FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 0, HI_TXBPS}
119
121
HIDB hi1_db = HI_HIDB (1 ), hi2_db = HI_HIDB (2 );
120
122
HIDB hi3_db = HI_HIDB (3 ), hi4_db = HI_HIDB (4 );
121
123
@@ -161,8 +163,9 @@ REG hi3_reg[] = HI_REG(3), hi4_reg[] = HI_REG(4);
161
163
162
164
// Host Device Modifiers ...
163
165
// These are the modifiers simh uses for the "SET MIxn" and "SHOW MIx" commands.
164
- #define HI_MOD (N ) { \
165
- { 0 } \
166
+ #define HI_MOD (N ) { \
167
+ { MTAB_XTD|MTAB_VDV, 0, NULL, "CONVERT", &hi_set_convert, &hi_show_convert, NULL }, \
168
+ { MTAB_XTD|MTAB_VDV, 1, NULL, "NOCONVERT", &hi_set_convert, &hi_show_convert, NULL }, \
166
169
}
167
170
MTAB hi1_mod [] = HI_MOD (1 ), hi2_mod [] = HI_MOD (2 );
168
171
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};
196
199
DIB * const hi_dibs [HI_NUM ] = {& hi1_dib , & hi2_dib , & hi3_dib , & hi4_dib };
197
200
HIDB * const hi_hidbs [HI_NUM ] = {& hi1_db , & hi2_db , & hi3_db , & hi4_db };
198
201
202
+ // Old message type field set to this to signal new format leader.
203
+ #define NEW_FORMAT_FLAG (15 << 8)
204
+
205
+ // 1822 message types (or subtypes).
206
+ #define LEADER_REGULAR 000
207
+ #define LEADER_UNCONTROLLED 003
208
+ #define LEADER_NOP 004
209
+
210
+ // 1822 new leader flags.
211
+ #define NLEADER_TRACE 010
212
+ #define NLEADER_OCTAL 004
213
+ #define NLEADER_FOR_IMP 252
214
+ #define NLEADER_PRIORITY 0200
215
+
216
+ // 1822 old leader flags.
217
+ #define OLEADER_PRIORITY 010
218
+ #define OLEADER_FOR_IMP 004
219
+ #define OLEADER_TRACE 002
220
+ #define OLEADER_OCTAL 001
199
221
200
222
201
223
////////////////////////////////////////////////////////////////////////////////
@@ -235,6 +257,7 @@ void hi_reset_tx (uint16 host)
235
257
{
236
258
PHIDB (host )-> iloop = PHIDB (host )-> enabled = PHIDB (host )-> full = FALSE;
237
259
PHIDB (host )-> txtotal = 0 ;
260
+ PHIDB (host )-> txfirst = TRUE;
238
261
CLR_TX_IRQ (host ); CLR_TX_IEN (host );
239
262
}
240
263
@@ -309,6 +332,123 @@ void hi_debug_msg (uint16 line, uint16 next, uint16 count, const char *ptext)
309
332
///////////////// T R A N S M I T A N D R E C E I V E //////////////////
310
333
////////////////////////////////////////////////////////////////////////////////
311
334
335
+ // Convert 1822 long header from host, to short leader for IMP.
336
+ static int16 hi_convert_long_to_short (uint16 line , int16 count )
337
+ {
338
+ uint16 nflags , mtype , htype , host , imp , id , stype , length ;
339
+ uint16 oflags ;
340
+ uint16 * data = PHIDB (line )-> rxdata ;
341
+
342
+ if (count == 0 )
343
+ return 0 ;
344
+
345
+ if (count < 7 || (data [1 ] & 0x0F00 ) != NEW_FORMAT_FLAG )
346
+ return count ; // This is not a long leader message.
347
+
348
+ nflags = (data [2 ] & 0x0F00 ) >> 8 ;
349
+ mtype = data [2 ] & 0xFF ;
350
+ htype = (data [3 ] & 0xFF00 ) >> 8 ;
351
+ host = data [3 ] & 0xFF ;
352
+ imp = data [4 ];
353
+ id = (data [5 ] & 0xFFF0 ) >> 4 ;
354
+ stype = data [5 ] & 0x000F ;
355
+ length = data [6 ];
356
+
357
+ // Keep track of padding.
358
+ if (mtype == LEADER_NOP )
359
+ PHIDB (line )-> padding = stype ;
360
+
361
+ // Sorry, can't handle these addresses.
362
+ if (host > 3 )
363
+ return 0 ;
364
+ if (imp > 63 )
365
+ return 0 ;
366
+
367
+ if (mtype == LEADER_REGULAR && stype == LEADER_UNCONTROLLED )
368
+ mtype = LEADER_UNCONTROLLED , stype = 0 ;
369
+ else if (mtype == LEADER_NOP )
370
+ stype = 0 ;
371
+
372
+ oflags = 0 ;
373
+ if (nflags & NLEADER_TRACE )
374
+ oflags |= OLEADER_TRACE ;
375
+ if (nflags & NLEADER_OCTAL )
376
+ oflags |= OLEADER_OCTAL ;
377
+ if (host >= NLEADER_FOR_IMP ) {
378
+ oflags |= OLEADER_FOR_IMP ;
379
+ host -= NLEADER_FOR_IMP ;
380
+ }
381
+ if (htype & NLEADER_PRIORITY )
382
+ oflags |= OLEADER_PRIORITY ;
383
+
384
+ oflags <<= 12 ;
385
+ mtype <<= 8 ;
386
+ host <<= 6 ;
387
+ id <<= 4 ;
388
+ data [1 ] = oflags | mtype | host | imp ;
389
+ data [2 ] = id | stype ;
390
+
391
+ if (mtype == LEADER_REGULAR ) {
392
+ count -= 4 + PHIDB (line )-> padding ;
393
+ memmove (& data [3 ], & data [7 + PHIDB (line )-> padding ], 2 * count );
394
+ } else {
395
+ count = 3 ;
396
+ }
397
+
398
+ return count ;
399
+ }
400
+
401
+ // Convert 1822 short header from IMP, to long leader for host.
402
+ static uint16 hi_convert_short_to_long (uint16 line , uint16 * data , uint16 count )
403
+ {
404
+ uint16 oflags , mtype , host , imp , id , stype ;
405
+ uint16 nflags = 0 , htype = 0 , length = 0 ;
406
+
407
+ oflags = (data [1 ] & 0xF000 ) >> 12 ;
408
+ mtype = (data [1 ] & 0x0F00 ) >> 8 ;
409
+ host = (data [1 ] & 0x00C0 ) >> 6 ;
410
+ imp = data [1 ] & 0x003F ;
411
+ id = (data [2 ] & 0xFFF0 ) >> 4 ;
412
+ stype = data [2 ] & 0x000F ;
413
+
414
+ if (mtype == LEADER_REGULAR ) {
415
+ memmove (& data [7 + PHIDB (line )-> padding ], & data [3 ], 2 * (count - 3 ));
416
+ memset (& data [7 ], 0 , 2 * PHIDB (line )-> padding );
417
+ length = 16 * (count - 3 );
418
+ count += PHIDB (line )-> padding ;
419
+ }
420
+ count += 4 ;
421
+
422
+ if (oflags & OLEADER_PRIORITY )
423
+ htype |= NLEADER_PRIORITY ;
424
+ htype |= 7 ;
425
+ if (oflags & OLEADER_FOR_IMP )
426
+ host += NLEADER_FOR_IMP ;
427
+ if (oflags & OLEADER_TRACE )
428
+ nflags |= NLEADER_TRACE ;
429
+ if (oflags & OLEADER_OCTAL )
430
+ nflags |= OLEADER_OCTAL ;
431
+
432
+ if (mtype == LEADER_REGULAR )
433
+ stype = 0 ;
434
+ else if (mtype == LEADER_UNCONTROLLED )
435
+ mtype = LEADER_REGULAR , stype = LEADER_UNCONTROLLED ;
436
+ else if (mtype == LEADER_NOP )
437
+ stype = 0 ;
438
+
439
+ nflags <<= 8 ;
440
+ htype <<= 8 ;
441
+ id <<= 4 ;
442
+ data [1 ] = NEW_FORMAT_FLAG ;
443
+ data [2 ] = nflags | mtype ;
444
+ data [3 ] = htype | host ;
445
+ data [4 ] = imp ;
446
+ data [5 ] = id | stype ;
447
+ data [6 ] = length ;
448
+
449
+ return count ;
450
+ }
451
+
312
452
// Start the transmitter ...
313
453
void hi_start_tx (uint16 line , uint16 flags )
314
454
{
@@ -337,16 +477,19 @@ void hi_start_tx (uint16 line, uint16 flags)
337
477
// uint16 flags;
338
478
// uint16 data [MAXDATA - 1];
339
479
// Put the packet into a temp buffer for assembly.
340
- uint16 * tmp = ( uint16 * ) malloc (( count + 1 ) * sizeof ( * tmp )) ;
480
+ static uint16 tmp [ 1500 ] ;
341
481
uint16 i ;
342
482
343
483
tmp [0 ] = flags ;
344
484
if (PHIDB (line )-> enabled )
345
485
tmp [0 ] |= PFLG_READY ;
346
486
for (i = 0 ; i < count ; i ++ )
347
487
tmp [i + 1 ] = M [next + i ];
348
- ret = udp_send (PDEVICE (line ), PHIDB (line )-> link , tmp , count + 1 );
349
- free (tmp );
488
+ count ++ ;
489
+ if (PHIDB (line )-> convert && PHIDB (line )-> txfirst )
490
+ count = hi_convert_short_to_long (line , tmp , count );
491
+ PHIDB (line )-> txfirst = !!(flags & PFLG_FINAL );
492
+ ret = udp_send (PDEVICE (line ), PHIDB (line )-> link , tmp , count );
350
493
if (ret != SCPE_OK && ret != 66 ) hi_link_error (line );
351
494
}
352
495
@@ -426,14 +569,15 @@ void hi_poll_rx (uint16 line)
426
569
} else {
427
570
// Get a new UDP packet.
428
571
count = udp_receive (PDEVICE (line ), PHIDB (line )-> link , PHIDB (line )-> rxdata , MAXDATA );
572
+ if (PHIDB (line )-> convert ) count = hi_convert_long_to_short (line , count );
429
573
PHIDB (line )-> eom = FALSE;
430
574
PHIDB (line )-> rxsize = count ;
431
575
if (count == 0 ) { return ; }
432
576
if (count < 0 ) { hi_link_error (line ); return ; }
433
577
// Make note of the host ready bit.
434
578
PHIDB (line )-> ready = !! (PHIDB (line )-> rxdata [0 ] & PFLG_READY );
435
579
// Exclude the flags from the count.
436
- PHIDB (line )-> rxnext = 1 ; count -- ;
580
+ PHIDB (line )-> rxnext = 1 ; count -- ;
437
581
if (count == 0 ) return ;
438
582
PHIDB (line )-> rxtotal ++ ;
439
583
}
@@ -445,10 +589,10 @@ void hi_poll_rx (uint16 line)
445
589
count = maxbuf ;
446
590
}
447
591
hi_update_dmc (PDIB (line )-> rxdmc , count );
448
- hi_debug_msg (line , next , count , "received" );
449
592
450
593
for (i = 0 ; i < count ; i ++ )
451
594
* (pdata + i ) = PHIDB (line )-> rxdata [PHIDB (line )-> rxnext ++ ];
595
+ hi_debug_msg (line , next , count , "received" );
452
596
453
597
// Now would be a good time to worry about whether a receive is pending!
454
598
if (!PHIDB (line )-> rxpending ) {
@@ -682,4 +826,19 @@ t_stat hi_detach (UNIT *uptr)
682
826
}
683
827
684
828
829
+ t_stat hi_set_convert (UNIT * uptr , int32 val , CONST char * cptr , void * desc )
830
+ {
831
+ PHIDB (uptr -> hline )-> convert = !val ;
832
+ return SCPE_OK ;
833
+ }
834
+
835
+ t_stat hi_show_convert (FILE * st , UNIT * uptr , int32 val , CONST void * desc )
836
+ {
837
+ if (PHIDB (uptr -> hline )-> convert )
838
+ fprintf (st , "Convert short leaders" );
839
+ else
840
+ fprintf (st , "Do not convert short leaders" );
841
+ return SCPE_OK ;
842
+ }
843
+
685
844
#endif // #ifdef VM_IMPTIP from the very top
0 commit comments