-
Notifications
You must be signed in to change notification settings - Fork 20
/
kl10_fe.c
2497 lines (2279 loc) · 87.3 KB
/
kl10_fe.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* kl10_fe.c: KL-10 front end (console terminal) simulator
Copyright (c) 2019-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
RICHARD CORNWELL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Richard Cornwell shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Richard Cornwell
*/
#include "kx10_defs.h"
#include "sim_sock.h"
#include "sim_tmxr.h"
#include <ctype.h>
#if KL
#define UNIT_DUMMY (1 << UNIT_V_UF)
#define DTE_DEVNUM 0200
#define DEV_V_OS (DEV_V_UF + 1) /* Type RSX10/RSX20 */
#define DEV_M_OS (1 << DEV_V_OS)
#define TYPE_RSX10 (0 << DEV_V_OS)
#define TYPE_RSX20 (1 << DEV_V_OS)
/* DTE10 CONI bits */
#define DTE_RM 00100000 /* Restricted mode */
#define DTE_D11 00040000 /* Dead-11 */
#define DTE_11DB 00020000 /* TO11 Door bell request */
#define DTE_10DB 00001000 /* TO10 Door bell request */
#define DTE_11ER 00000400 /* Error during TO11 transfer */
#define DTE_11DN 00000100 /* TO 11 transfer done */
#define DTE_10DN 00000040 /* TO 10 transfer done */
#define DTE_10ER 00000020 /* Error during TO10 transfer */
#define DTE_PIE 00000010 /* PIO enabled */
#define DTE_PIA 00000007 /* PI channel assigment */
/* internal flags */
#define DTE_11RELD 01000000 /* Reload 11. */
#define DTE_TO11 02000000 /* Transfer to 11 */
#define DTE_SEC 04000000 /* In secondary protocol */
#define DTE_IND 010000000 /* Next transfer will be indirect */
#define DTE_SIND 020000000 /* Send indirect data next */
/* DTE CONO bits */
#define DTE_CO11DB 0020000 /* Set TO11 Door bell */
#define DTE_CO11CR 0010000 /* Clear reload 11 button */
#define DTE_CO11SR 0004000 /* Set reload 11 button */
#define DTE_CO10DB 0001000 /* Clear TO10 Door bell */
#define DTE_CO11CL 0000100 /* Clear TO11 done and error */
#define DTE_CO10CL 0000040 /* Clear TO10 done and error */
#define DTE_PIENB 0000020 /* Load PI and enable bit */
/* DTE DATAO */
#define DTE_TO10IB 010000 /* Interrupt after transfer */
#define DTE_TO10BC 007777 /* Byte count for transfer */
/* Secondary protocol addresses */
#define SEC_DTFLG 0444 /* Operation complete flag */
#define SEC_DTCLK 0445 /* Clock interrupt flag */
#define SEC_DTCI 0446 /* Clock interrupt instruction */
#define SEC_DTT11 0447 /* 10 to 11 argument */
#define SEC_DTF11 0450 /* 10 from 11 argument */
#define SEC_DTCMD 0451 /* To 11 command word */
#define SEC_DTSEQ 0452 /* Operation sequence number */
#define SEC_DTOPR 0453 /* Operational DTE # */
#define SEC_DTCHR 0454 /* Last typed character */
#define SEC_DTMTD 0455 /* Monitor tty output complete flag */
#define SEC_DTMTI 0456 /* Monitor tty input flag */
#define SEC_DTSWR 0457 /* 10 switch register */
#define SEC_PGMCTL 00400
#define SEC_ENDPASS 00404
#define SEC_LOOKUP 00406
#define SEC_RDWRD 00407
#define SEC_RDBYT 00414
#define SEC_ESEC 00440
#define SEC_EPRI 00500
#define SEC_ERTM 00540
#define SEC_CLKCTL 01000
#define SEC_CLKOFF 01000
#define SEC_CLKON 01001
#define SEC_CLKWT 01002
#define SEC_CLKRD 01003
#define SEC_RDSW 01400
#define SEC_CLRDDT 03000
#define SEC_SETDDT 03400
#define SEC_MONO 04000
#define SEC_MONON 04400
#define SEC_SETPRI 05000
#define SEC_RTM 05400
#define SEC_CMDMSK 07400
#define DTE_MON 00000001 /* Save in unit1 STATUS */
#define SEC_CLK 00000002 /* Clock enabled */
#define ITS_ON 00000004 /* ITS Is alive */
/* Primary or Queued protocol addresses */
#define PRI_CMTW_0 0
#define PRI_CMTW_PPT 1 /* Pointer to com region */
#define PRI_CMTW_STS 2 /* Status word */
#define PRI_CMT_PWF SMASK /* Power failure */
#define PRI_CMT_L11 BIT1 /* Load 11 */
#define PRI_CMT_INI BIT2 /* Init */
#define PRI_CMT_TST BIT3 /* Valid examine bit */
#define PRI_CMT_QP 020000000LL /* Do Queued protocol */
#define PRI_CMT_FWD 001000000LL /* Do full word transfers */
#define PRI_CMT_IP RSIGN /* Indirect transfer */
#define PRI_CMT_TOT 0200000LL /* TOIT bit */
#define PRI_CMT_10IC 0177400LL /* TO10 IC for queued transfers */
#define PRI_CMT_11IC 0000377LL /* TO11 IC for queued transfers */
#define PRI_CMTW_CNT 3 /* Queue Count */
#define PRI_CMTW_KAC 5 /* Keep alive count */
#define PRI_IND_FLG 0100000 /* Flag function as indirect */
#define PRI_EM2EI 001 /* Initial message to 11 */
#define PRI_EM2TI 002 /* Replay to initial message. */
#define PRI_EMSTR 003 /* String data */
#define PRI_EMLNC 004 /* Line-Char */
#define PRI_EMRDS 005 /* Request device status */
#define PRI_EMOPS 006
#define PRI_EMHDS 007 /* Here is device status */
#define PRI_EMRDT 011 /* Request Date/Time */
#define PRI_EMHDR 012 /* Here is date and time */
#define PRI_EMFLO 013 /* Flush output */
#define PRI_EMSNA 014 /* Send all (ttys) */
#define PRI_EMDSC 015 /* Dataset connect */
#define PRI_EMHUD 016 /* Hang up dataset */
#define PRI_EMLBE 017 /* Acknowledge line */
#define PRI_EMXOF 020 /* XOFF line */
#define PRI_EMXON 021 /* XON line */
#define PRI_EMHLS 022 /* Here is line speeds */
#define PRI_EMHLA 023 /* Here is line allocation */
#define PRI_EMRBI 024 /* Reboot information */
#define PRI_EMAKA 025 /* Ack ALL */
#define PRI_EMTDO 026 /* Turn device On/Off */
#define PRI_EMEDR 027 /* Enable/Disable line */
#define PRI_EMLDR 030 /* Load LP RAM */
#define PRI_EMLDV 031 /* Load LP VFU */
#define PRI_EMCTY 001 /* Device code for CTY */
#define PRI_EMDL1 002 /* DL11 */
#define PRI_EMDH1 003 /* DH11 #1 */
#define PRI_EMDLS 004 /* DLS (all ttys combined) */
#define PRI_EMLPT 005 /* Front end LPT */
#define PRI_EMCDR 006 /* CDR */
#define PRI_EMCLK 007 /* Clock */
#define PRI_EMFED 010 /* Front end device */
#define PRI_CTYDV 000 /* Line number for CTY */
#define NUM_DLS 5 /* Number of first DH Line */
#if KL_ITS
/* ITS Timesharing protocol locations */
#define ITS_DTEVER 0400 /* Protocol version and number of devices */
#define ITS_DTECHK 0401 /* Increment at 60Hz. Ten setom 2 times per second */
#define ITS_DTEINP 0402 /* Input from 10 to 11. Line #, Count */
#define ITS_DTEOUT 0403 /* Output from 10 to 11 Line #, Count */
#define ITS_DTELSP 0404 /* Line # to set speed of */
#define ITS_DTELPR 0405 /* Parameter */
#define ITS_DTEOST 0406 /* Line # to start output on */
#define ITS_DTETYI 0410 /* Received char (Line #, char) */
#define ITS_DTEODN 0411 /* Output done (Line #, buffer size) */
#define ITS_DTEHNG 0412 /* Hangup/dialup */
#endif
extern int32 tmxr_poll;
t_stat dte_devio(uint32 dev, uint64 *data);
t_addr dte_devirq(uint32 dev, t_addr addr);
void dte_second(UNIT *uptr);
void dte_primary(UNIT *uptr);
#if KL_ITS
void dte_its(UNIT *uptr);
#endif
void dte_transfer(UNIT *uptr);
void dte_function(UNIT *uptr);
void dte_input();
int dte_start(UNIT *uptr);
int dte_queue(int func, int dev, int dcnt, uint16 *data);
t_stat dtei_svc (UNIT *uptr);
t_stat dte_svc (UNIT *uptr);
t_stat dteo_svc (UNIT *uptr);
t_stat dtertc_srv(UNIT * uptr);
t_stat dte_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat dte_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat dte_reset (DEVICE *dptr);
t_stat dte_stop_os (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat tty_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat dte_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
const char *dte_description (DEVICE *dptr);
extern uint64 SW; /* Switch register */
CONST char *pri_name[] = { "(0)", "EM2EI", "EM2TI", "EMSTR", "EMLNC", "EMRDS", "(6)",
"EMHDS", "(10)", "EMRDT", "EMHDR", "EMFLO", "EMSNA", "EMDSC", "EMHUD",
"EMLBE", "EMXOF", "EMXON", "EMHLS", "EMHLA", "EMRBI", "EMAKA", "EMTDO",
"EMEDR", "EMLDR", "EMLDV" };
#if KL_ITS
#define QITS (cpu_unit[0].flags & UNIT_ITSPAGE)
#else
#define QITS 0
#endif
#define STATUS u3
#define CNT u4
extern uint32 eb_ptr;
static int32 rtc_tps = 60;
uint16 rtc_tick;
uint16 rtc_wait = 0;
struct _dte_queue {
int dptr; /* Pointer to working item */
uint16 cnt; /* Number of bytes in packet */
uint16 func; /* Function code */
uint16 dev; /* Dev code */
uint16 spare; /* Dev code */
uint16 dcnt; /* Data count */
uint16 data[258]; /* Data packet */
uint16 sdev; /* Secondary device code */
uint16 sz; /* Byte size */
} dte_in[16], dte_out[16];
int32 dte_in_ptr;
int32 dte_in_cmd;
int32 dte_out_ptr;
int32 dte_out_res;
int32 dte_base; /* Base */
int32 dte_off; /* Our offset */
int32 dte_dt10_off; /* Offset to 10 deposit region */
int32 dte_et10_off; /* Offset to 10 examine region */
int32 dte_et11_off; /* Offset to 11 examine region */
int32 dte_proc_num; /* Our processor number */
struct _buffer {
int in_ptr; /* Insert pointer */
int out_ptr; /* Remove pointer */
char buff[256]; /* Buffer */
} cty_in, cty_out;
int32 cty_done;
#define full(q) ((((q)->in_ptr + 1) & 0xff) == (q)->out_ptr)
#define empty(q) ((q)->in_ptr == (q)->out_ptr)
#define not_empty(q) ((q)->in_ptr != (q)->out_ptr)
#define inco(q) (q)->out_ptr = ((q)->out_ptr + 1) & 0xff
#define inci(q) (q)->in_ptr = ((q)->in_ptr + 1) & 0xff
DIB dte_dib[] = {
{ DTE_DEVNUM|000, 1, dte_devio, dte_devirq},
};
MTAB dte_mod[] = {
{ UNIT_DUMMY, 0, NULL, "STOP", &dte_stop_os },
{ TT_MODE, TT_MODE_UC, "UC", "UC", &tty_set_mode },
{ TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode },
{ TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode },
{ TT_MODE, TT_MODE_7P, "7p", "7P", &tty_set_mode },
{MTAB_XTD|MTAB_VDV, TYPE_RSX10, NULL, "RSX10", &dte_set_type, NULL,
NULL, "Sets DTE to RSX10 mode"},
{MTAB_XTD|MTAB_VDV, TYPE_RSX20, "RSX20", "RSX20", &dte_set_type, &dte_show_type,
NULL, "Sets DTE to RSX20 mode"},
{ 0 }
};
UNIT dte_unit[] = {
{ UDATA (&dte_svc, TT_MODE_7B, 0), 100},
{ UDATA (&dteo_svc, TT_MODE_7B, 0), 100},
{ UDATA (&dtei_svc, TT_MODE_7B|UNIT_DIS, 0), 1000 },
{ UDATA (&dtertc_srv, UNIT_IDLE|UNIT_DIS, 0), 1000 }
};
REG dte_reg[] = {
{SAVEDATA(IN, dte_in) },
{SAVEDATA(OUT, dte_out) },
{HRDATA(IN_PTR, dte_in_ptr, 32), REG_HRO},
{HRDATA(IN_CMD, dte_in_cmd, 32), REG_HRO},
{HRDATA(OUT_PTR, dte_out_ptr, 32), REG_HRO},
{HRDATA(OUT_RES, dte_out_res, 32), REG_HRO},
{HRDATA(BASE, dte_base, 32), REG_HRO},
{HRDATA(OFF, dte_off, 32), REG_HRO},
{HRDATA(DTOFF, dte_dt10_off, 32), REG_HRO},
{HRDATA(ETOFF, dte_et10_off, 32), REG_HRO},
{HRDATA(E1OFF, dte_et11_off, 32), REG_HRO},
{HRDATA(PROC, dte_proc_num, 32), REG_HRO},
{SAVEDATA(CTYIN, cty_in) },
{SAVEDATA(CTYOUT, cty_out) },
{HRDATA(DONE, cty_done, 8), REG_HRO},
{HRDATAD(WRU, sim_int_char, 8, "interrupt character") },
{ 0 },
};
DEVICE dte_dev = {
"CTY", dte_unit, dte_reg, dte_mod,
4, 10, 31, 1, 8, 8,
NULL, NULL, &dte_reset,
NULL, NULL, NULL, &dte_dib, DEV_DEBUG, 0, dev_debug,
NULL, NULL, &dte_help, NULL, NULL, &dte_description
};
#ifndef NUM_DEVS_LP20
#define NUM_DEVS_LP20 0
#endif
#if (NUM_DEVS_LP20 > 0)
#define COL u4
#define POS u5
#define LINE u6
#define LPST us9
#define LPCNT us10
#define EOFFLG 001 /* Tops 20 wants EOF */
#define HDSFLG 002 /* Tell Tops 20 The current device status */
#define ACKFLG 004 /* Post an acknowwledge message */
#define INTFLG 010 /* Send interrupt */
#define DELFLG 020 /* Previous character was delimiter */
#define MARGIN 6
#define UNIT_V_CT (UNIT_V_UF + 0)
#define UNIT_UC (1 << UNIT_V_CT)
#define UNIT_CT (3 << UNIT_V_CT)
t_stat lp20_svc (UNIT *uptr);
t_stat lp20_reset (DEVICE *dptr);
t_stat lp20_attach (UNIT *uptr, CONST char *cptr);
t_stat lp20_detach (UNIT *uptr);
t_stat lp20_setlpp(UNIT *, int32, CONST char *, void *);
t_stat lp20_getlpp(FILE *, UNIT *, int32, CONST void *);
t_stat lp20_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag,
const char *cptr);
const char *lp20_description (DEVICE *dptr);
char lp20_buffer[134 * 3];
#define LP20_RAM_RAP 010000 /* RAM Parity */
#define LP20_RAM_INT 04000 /* Interrrupt bit */
#define LP20_RAM_DEL 02000 /* Delimiter bit */
#define LP20_RAM_TRN 01000 /* Translation bite */
#define LP20_RAM_PI 00400 /* Paper Instruction */
#define LP20_RAM_CHR 00377 /* Character translation */
uint16 lp20_vfu[256];
uint16 lp20_ram[256];
uint16 lp20_dvfu[] = { /* Default VFU */
/* 66 line page with 6 line margin */
00377, /* Line 0 8 7 6 5 4 3 2 1 */
00220, /* Line 1 8 5 */
00224, /* Line 2 8 5 3 */
00230, /* Line 3 8 5 4 */
00224, /* Line 4 8 5 3 */
00220, /* Line 5 8 5 */
00234, /* Line 6 8 5 4 3 */
00220, /* Line 7 8 5 */
00224, /* Line 8 8 5 3 */
00230, /* Line 9 8 5 4 */
00264, /* Line 10 8 6 5 3 */
00220, /* Line 11 8 5 */
00234, /* Line 12 8 5 4 3 */
00220, /* Line 13 8 5 */
00224, /* Line 14 8 5 3 */
00230, /* Line 15 8 5 4 */
00224, /* Line 16 8 5 3 */
00220, /* Line 17 8 5 */
00234, /* Line 18 8 5 4 3 */
00220, /* Line 19 8 5 */
00364, /* Line 20 8 7 6 5 3 */
00230, /* Line 21 8 5 4 */
00224, /* Line 22 8 5 3 */
00220, /* Line 23 8 5 */
00234, /* Line 24 8 5 4 3 */
00220, /* Line 25 8 5 */
00224, /* Line 26 8 5 3 */
00230, /* Line 27 8 5 4 */
00224, /* Line 28 8 5 3 */
00220, /* Line 29 8 5 */
00276, /* Line 30 8 6 5 4 3 2 */
00220, /* Line 31 8 5 */
00224, /* Line 32 8 5 3 */
00230, /* Line 33 8 5 4 */
00224, /* Line 34 8 5 3 */
00220, /* Line 35 8 5 */
00234, /* Line 36 8 5 4 3 */
00220, /* Line 37 8 5 */
00224, /* Line 38 8 5 3 */
00230, /* Line 39 8 5 4 */
00364, /* Line 40 8 7 6 5 3 */
00220, /* Line 41 8 5 */
00234, /* Line 42 8 5 4 3 */
00220, /* Line 43 8 5 */
00224, /* Line 44 8 5 3 */
00230, /* Line 45 8 5 4 */
00224, /* Line 46 8 5 3 */
00220, /* Line 47 8 5 */
00234, /* Line 48 8 5 4 3 */
00220, /* Line 49 8 5 */
00264, /* Line 50 8 6 5 3 */
00230, /* Line 51 8 5 4 */
00224, /* Line 52 8 5 3 */
00220, /* Line 53 8 5 */
00234, /* Line 54 8 5 4 3 */
00220, /* Line 55 8 5 */
00224, /* Line 56 8 5 3 */
00230, /* Line 57 8 5 4 */
00224, /* Line 58 8 5 3 */
00220, /* Line 59 8 5 */
00020, /* Line 60 5 */
00020, /* Line 61 5 */
00020, /* Line 62 5 */
00020, /* Line 63 5 */
00020, /* Line 64 5 */
04020, /* Line 65 12 5 */
010000, /* End of form */
};
struct _buffer lp20_queue;
/* LPT data structures
lp20_dev LPT device descriptor
lp20_unit LPT unit descriptor
lp20_reg LPT register list
*/
UNIT lp20_unit = {
UDATA (&lp20_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_TEXT, 66), 100
};
REG lp20_reg[] = {
{BRDATA(BUFFER, lp20_buffer, 16, 8, sizeof(lp20_buffer)), REG_HRO},
{BRDATA(VFU, lp20_vfu, 16, 16, (sizeof(lp20_vfu)/sizeof(uint16))), REG_HRO},
{BRDATA(RAM, lp20_ram, 16, 16, (sizeof(lp20_ram)/sizeof(uint16))), REG_HRO},
{SAVEDATA(QUEUE, lp20_queue) },
{ NULL }
};
MTAB lp20_mod[] = {
{UNIT_CT, 0, "Lower case", "LC", NULL},
{UNIT_CT, UNIT_UC, "Upper case", "UC", NULL},
{MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "LINESPERPAGE", "LINESPERPAGE",
&lp20_setlpp, &lp20_getlpp, NULL, "Number of lines per page"},
{ 0 }
};
DEVICE lp20_dev = {
"LP20", &lp20_unit, lp20_reg, lp20_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &lp20_reset,
NULL, &lp20_attach, &lp20_detach,
NULL, DEV_DISABLE | DEV_DEBUG, 0, dev_debug,
NULL, NULL, &lp20_help, NULL, NULL, &lp20_description
};
#endif
#ifndef NUM_DEVS_TTY
#define NUM_DEVS_TTY 0
#endif
#if (NUM_DEVS_TTY > 0)
struct _buffer tty_out[NUM_LINES_TTY], tty_in[NUM_LINES_TTY];
TMLN tty_ldsc[NUM_LINES_TTY] = { 0 }; /* Line descriptors */
TMXR tty_desc = { NUM_LINES_TTY, 0, 0, tty_ldsc };
int32 tty_connect[NUM_LINES_TTY];
int32 tty_done[NUM_LINES_TTY];
int tty_enable = 0;
extern int32 tmxr_poll;
t_stat ttyi_svc (UNIT *uptr);
t_stat ttyo_svc (UNIT *uptr);
t_stat tty_reset (DEVICE *dptr);
t_stat tty_set_modem (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat tty_show_modem (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat tty_setnl (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat tty_set_log (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat tty_set_nolog (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat tty_show_log (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat tty_attach (UNIT *uptr, CONST char *cptr);
t_stat tty_detach (UNIT *uptr);
t_stat tty_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag,
const char *cptr);
const char *tty_description (DEVICE *dptr);
/* TTY data structures
tty_dev TTY device descriptor
tty_unit TTY unit descriptor
tty_reg TTY register list
*/
UNIT tty_unit[] = {
{ UDATA (&ttyi_svc, TT_MODE_7B+UNIT_IDLE+UNIT_DISABLE+UNIT_ATTABLE, 0), KBD_POLL_WAIT},
{ UDATA (&ttyo_svc, TT_MODE_7B+UNIT_IDLE+UNIT_DIS, 0), KBD_POLL_WAIT},
};
REG tty_reg[] = {
{ DRDATA (TIME, tty_unit[0].wait, 24), REG_NZ + PV_LEFT },
{ SAVEDATA (OUT, tty_out) },
{ SAVEDATA (IN, tty_in) },
{ BRDATA (CONN, tty_connect, 8, 32, sizeof(tty_connect)/sizeof(int32)), REG_HRO },
{ BRDATA (DONE, tty_done, 8, 32, sizeof(tty_done)/sizeof(int32)), REG_HRO },
{ ORDATA (EN, tty_enable, 1), REG_HRO },
{ 0 }
};
MTAB tty_mod[] = {
{ TT_MODE, TT_MODE_KSR, "KSR", "KSR", NULL },
{ TT_MODE, TT_MODE_7B, "7b", "7B", NULL },
{ TT_MODE, TT_MODE_8B, "8b", "8B", NULL },
{ TT_MODE, TT_MODE_7P, "7p", "7P", NULL },
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 1, NULL, "DISCONNECT",
&tmxr_dscln, NULL, &tty_desc, "Disconnect a specific line" },
{ UNIT_ATT, UNIT_ATT, "SUMMARY", NULL,
NULL, &tmxr_show_summ, (void *) &tty_desc, "Display a summary of line states" },
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 1, "CONNECTIONS", NULL,
NULL, &tmxr_show_cstat, (void *) &tty_desc, "Display current connections" },
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "STATISTICS", NULL,
NULL, &tmxr_show_cstat, (void *) &tty_desc, "Display multiplexer statistics" },
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "LINES", "LINES=n",
&tty_setnl, &tmxr_show_lines, (void *) &tty_desc, "Set number of lines" },
{ MTAB_XTD|MTAB_VDV|MTAB_NC, 0, NULL, "LOG=n=file",
&tty_set_log, NULL, (void *)&tty_desc },
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, NULL, "NOLOG",
&tty_set_nolog, NULL, (void *)&tty_desc, "Disable logging on designated line" },
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "LOG", NULL,
NULL, &tty_show_log, (void *)&tty_desc, "Display logging for all lines" },
{ 0 }
};
DEVICE tty_dev = {
"TTY", tty_unit, tty_reg, tty_mod,
2, 10, 31, 1, 8, 8,
&tmxr_ex, &tmxr_dep, &tty_reset,
NULL, &tty_attach, &tty_detach,
NULL, DEV_MUX | DEV_DISABLE | DEV_DEBUG, 0, dev_debug,
NULL, NULL, &tty_help, NULL, NULL, &tty_description
};
#endif
t_stat dte_devio(uint32 dev, uint64 *data) {
uint32 res;
switch(dev & 3) {
case CONI:
*data = (uint64)(dte_unit[0].STATUS) & RMASK;
sim_debug(DEBUG_CONI, &dte_dev, "CTY %03o CONI %06o\n", dev, (uint32)*data);
break;
case CONO:
res = (uint32)(*data & RMASK);
clr_interrupt(dev);
if (res & DTE_PIENB) {
dte_unit[0].STATUS &= ~(DTE_PIA|DTE_PIE);
dte_unit[0].STATUS |= res & (DTE_PIA|DTE_PIE);
}
if (res & DTE_CO11CL)
dte_unit[0].STATUS &= ~(DTE_11DN|DTE_11ER);
if (res & DTE_CO10CL) {
dte_unit[0].STATUS &= ~(DTE_10DN|DTE_10ER);
dte_start(&dte_unit[0]);
}
if (res & DTE_CO10DB)
dte_unit[0].STATUS &= ~(DTE_10DB);
if (res & DTE_CO11CR)
dte_unit[0].STATUS &= ~(DTE_11RELD);
if (res & DTE_CO11SR)
dte_unit[0].STATUS |= (DTE_11RELD);
if (res & DTE_CO11DB) {
sim_debug(DEBUG_CONO, &dte_dev, "CTY Ring 11 DB\n");
dte_unit[0].STATUS |= DTE_11DB;
sim_activate(&dte_unit[0], 100);
}
if (dte_unit[0].STATUS & (DTE_10DB|DTE_11DN|DTE_10DN|DTE_11ER|DTE_10ER))
set_interrupt(dev, dte_unit[0].STATUS);
sim_debug(DEBUG_CONO, &dte_dev, "CTY %03o CONO %06o %06o\n", dev,
(uint32)*data, PC);
break;
case DATAI:
sim_debug(DEBUG_DATAIO, &dte_dev, "CTY %03o DATAI %06o\n", dev,
(uint32)*data);
break;
case DATAO:
sim_debug(DEBUG_DATAIO, &dte_dev, "CTY %03o DATAO %06o\n", dev,
(uint32)*data);
if (*data == 01365) {
dte_unit[0].STATUS |= DTE_SEC|DTE_10ER;
dte_unit[0].STATUS &= ~(DTE_10DB|DTE_IND|DTE_11DB);
break;
}
dte_unit[0].CNT = (*data & (DTE_TO10IB|DTE_TO10BC));
dte_unit[0].STATUS |= DTE_TO11;
sim_activate(&dte_unit[0], 10);
break;
}
return SCPE_OK;
}
/* Handle KL style interrupt vectors */
t_addr
dte_devirq(uint32 dev, t_addr addr) {
return 0142;
}
/* Handle TO11 interrupts */
t_stat dte_svc (UNIT *uptr)
{
/* Did the 10 knock? */
if (uptr->STATUS & DTE_11DB) {
/* If in secondary mode, do that protocol */
if (uptr->STATUS & DTE_SEC)
dte_second(uptr);
else
dte_primary(uptr); /* Retrieve data */
} else if (uptr->STATUS & DTE_TO11) {
/* Does 10 want us to send it what we have? */
dte_transfer(uptr);
}
return SCPE_OK;
}
/* Handle secondary protocol */
void dte_second(UNIT *uptr) {
uint64 word;
int32 ch;
uint32 base = 0;
#if KI_22BIT
#if KL_ITS
if (!QITS)
#endif
base = eb_ptr;
#endif
/* read command */
word = M[SEC_DTCMD + base];
#if KL_ITS
if (word == 0 && QITS && (uptr->STATUS & ITS_ON) != 0) {
dte_its(uptr);
uptr->STATUS &= ~DTE_11DB;
return;
}
#endif
/* Do it */
sim_debug(DEBUG_DETAIL, &dte_dev, "CTY secondary %012llo\n", word);
switch(word & SEC_CMDMSK) {
default:
case SEC_MONO: /* Ouput character in monitor mode */
ch = (int32)(word & 0177);
if (full(&cty_out)) {
sim_activate(uptr, 200);
return;
}
if (ch != 0) {
cty_out.buff[cty_out.in_ptr] = ch & 0x7f;
inci(&cty_out);
if (!sim_is_active(&dte_unit[1]))
sim_activate(&dte_unit[1], 200);
}
M[SEC_DTCHR + base] = ch;
M[SEC_DTMTD + base] = FMASK;
break;
case SEC_SETPRI:
enter_pri:
if (Mem_examine_word(0, 0, &word))
break;
dte_proc_num = (word >> 24) & 037;
dte_base = dte_proc_num + 1;
dte_off = dte_base + (word & 0177777);
dte_dt10_off = 16;
dte_et10_off = dte_dt10_off + 16;
dte_et11_off = dte_base + 16;
uptr->STATUS &= ~DTE_SEC;
dte_in_ptr = dte_out_ptr = 0;
dte_in_cmd = dte_out_res = 0;
cty_done = 0;
/* Start input process */
M[SEC_DTCMD + base] = 0;
M[SEC_DTFLG + base] = FMASK;
uptr->STATUS &= ~DTE_11DB;
tty_reset(&tty_dev);
return;
case SEC_SETDDT: /* Read character from console */
if (empty(&cty_in)) {
M[SEC_DTF11 + base] = 0;
M[SEC_DTMTI + base] = FMASK;
break;
}
ch = cty_in.buff[cty_in.out_ptr];
inco(&cty_in);
M[SEC_DTF11 + base] = 0177 & ch;
M[SEC_DTMTI + base] = FMASK;
break;
case SEC_CLRDDT: /* Clear DDT input mode */
uptr->STATUS &= ~DTE_MON;
break;
case SEC_MONON:
uptr->STATUS |= DTE_MON;
break;
case SEC_RDSW: /* Read switch register */
M[SEC_DTSWR + base] = SW;
M[SEC_DTF11 + base] = SW;
break;
case SEC_PGMCTL: /* Program control: Used by KLDCP */
switch(word) {
case SEC_ENDPASS:
case SEC_LOOKUP:
case SEC_RDWRD:
case SEC_RDBYT:
break;
case SEC_ESEC:
goto enter_pri;
case SEC_EPRI:
case SEC_ERTM:
break;
}
break;
case SEC_CLKCTL: /* Clock control: Used by KLDCP */
switch(word) {
case SEC_CLKOFF:
dte_unit[3].STATUS &= ~SEC_CLK;
break;
case SEC_CLKWT:
rtc_wait = (uint16)(M[SEC_DTT11 + base] & 0177777);
/* Fall Through */
case SEC_CLKON:
dte_unit[3].STATUS |= SEC_CLK;
rtc_tick = 0;
break;
case SEC_CLKRD:
M[SEC_DTF11+base] = rtc_tick;
break;
}
break;
}
/* Acknowledge command */
M[SEC_DTCMD + base] = 0;
M[SEC_DTFLG + base] = FMASK;
uptr->STATUS &= ~DTE_11DB;
if (dte_dev.flags & TYPE_RSX20) {
uptr->STATUS |= DTE_10DB;
set_interrupt(DTE_DEVNUM, dte_unit[0].STATUS);
}
}
#if KL_ITS
/* Process ITS Ioeleven locations */
void dte_its(UNIT *uptr) {
uint64 word;
char ch;
uint16 data;
int cnt;
int ln;
/* Check for input Start */
word = M[ITS_DTEINP];
if ((word & SMASK) == 0) {
M[ITS_DTEINP] = FMASK;
sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEINP = %012llo\n", word);
}
/* Check for output Start */
word = M[ITS_DTEOUT];
if ((word & SMASK) == 0) {
cnt = word & 017777;
ln = ((word >> 18) & 077) - 1;
sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEOUT = %012llo\n", word);
while (cnt > 0) {
if (ln < 0) {
if (full(&cty_out))
return;
if (!Mem_read_byte(0, &data, 1))
return;
ch = data & 0177;
sim_debug(DEBUG_DETAIL, &dte_dev, "CTY queue %x\n", ch);
cty_out.buff[cty_out.in_ptr] = ch;
inci(&cty_out);
cnt--;
if (! sim_is_active(&dte_unit[1]))
sim_activate(&dte_unit[1], 50);
#if (NUM_DEVS_TTY > 0)
} else {
struct _buffer *otty = &tty_out[ln];
if (full(otty))
return;
if (!Mem_read_byte(0, &data, 1))
return;
ch = data & 0177;
sim_debug(DEBUG_DETAIL, &dte_dev, "TTY queue %x %d\n", ch, ln);
otty->buff[otty->in_ptr] = ch;
inci(otty);
cnt--;
#endif
}
}
M[ITS_DTEOUT] = FMASK;
uptr->STATUS |= DTE_11DN;
set_interrupt(DTE_DEVNUM, uptr->STATUS);
sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEOUT = %012llo\n", word);
}
/* Check for line speed */
word = M[ITS_DTELSP];
if ((word & SMASK) == 0) { /* Ready? */
M[ITS_DTELSP] = FMASK;
sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTELSP = %012llo %012llo\n", word, M[ITS_DTELPR]);
}
dte_input();
/* Check for output Start */
word = M[ITS_DTEOST];
if ((word & SMASK) == 0) {
if (word == 0)
cty_done++;
#if (NUM_DEVS_TTY > 0)
else if (word > 0 && word < (uint64)tty_desc.lines) {
tty_done[word-1] = 1;
}
#endif
M[ITS_DTEOST] = FMASK;
sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEOST = %012llo\n", word);
}
}
#endif
/* Handle primary protocol */
void dte_primary(UNIT *uptr) {
uint64 word, iword;
int s;
int cnt;
struct _dte_queue *in;
uint16 data1, *dp;
if ((uptr->STATUS & DTE_11DB) == 0)
return;
/* Check if there is room for another packet */
if (((dte_in_ptr + 1) & 0xf) == dte_in_cmd) {
/* If not reschedule ourselves */
sim_activate(uptr, 100);
return;
}
uptr->STATUS &= ~(DTE_11DB);
clr_interrupt(DTE_DEVNUM);
/* Check status word to see if valid */
if (Mem_examine_word(0, dte_et11_off + PRI_CMTW_STS, &word)) {
uint32 base;
error:
base = 0;
#if KI_22BIT
#if KL_ITS
if (!QITS)
#endif
base = eb_ptr;
#endif
/* If we can't read it, go back to secondary */
M[SEC_DTFLG + base] = FMASK;
uptr->STATUS |= DTE_SEC;
uptr->STATUS &= ~DTE_11DB;
if (dte_dev.flags & TYPE_RSX20) {
uptr->STATUS |= DTE_10DB;
set_interrupt(DTE_DEVNUM, dte_unit[0].STATUS);
}
sim_debug(DEBUG_DETAIL, &dte_dev, "DTE: error %012llo\n", word);
return;
}
sim_debug(DEBUG_DETAIL, &dte_dev, "DTE: status word %012llo\n", word);
if ((word & PRI_CMT_QP) == 0) {
goto error;
}
in = &dte_in[dte_in_ptr];
/* Check if indirect */
if ((word & PRI_CMT_IP) != 0) {
/* Transfer from 10 */
if ((uptr->STATUS & DTE_IND) == 0) {
fprintf(stderr, "DTE out of sync\r\n");
return;
}
/* Get size of transfer */
if (Mem_examine_word(0, dte_et11_off + PRI_CMTW_CNT, &iword))
goto error;
sim_debug(DEBUG_EXP, &dte_dev, "DTE: count: %012llo\n", iword);
in->dcnt = (uint16)(iword & 0177777);
/* Read in data */
dp = &in->data[0];
for (cnt = in->dcnt; cnt > 0; cnt --) {
/* Read in data */
s = Mem_read_byte(0, dp, 0);
if (s == 0)
goto error;
in->sz = s;
sim_debug(DEBUG_DATA, &dte_dev,
"DTE: Read Idata: %06o %03o %03o %06o cnt=%o\n",
*dp, *dp >> 8, *dp & 0377,
((*dp & 0377) << 8) | ((*dp >> 8) & 0377), cnt);
dp++;
if (s <= 8)
cnt--;
}
uptr->STATUS &= ~DTE_IND;
dte_in_ptr = (dte_in_ptr + 1) & 0xf;
} else {
/* Transfer from 10 */
in->dptr = 0;
in->dcnt = 0;
/* Read in count */
if (!Mem_read_byte(0, &data1, 0))
goto error;
in->cnt = data1;
cnt = in->cnt-2;
if (!Mem_read_byte(0, &data1, 0))
goto error;
in->func = data1;
cnt -= 2;
if (!Mem_read_byte(0, &data1, 0))
goto error;
in->dev = data1;
cnt -= 2;
if (!Mem_read_byte(0, &data1, 0))
goto error;
in->spare = data1;
cnt -= 2;
sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read CMD: %o c=%o f=%o %s d=%o\n",
dte_in_ptr, in->cnt, in->func,
((in->func & 0377) > PRI_EMLDV)?"***":
pri_name[in->func & 0377], in->dev);
dp = &in->data[0];
for (; cnt > 0; cnt -=2) {
/* Read in data */
if (!Mem_read_byte(0, dp, 0))
goto error;
sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read data: %06o %03o %03o\n",
*dp, *dp >> 8, *dp & 0377);
dp++;
in->dcnt += 2;
}
if (in->func & PRI_IND_FLG) {
uptr->STATUS |= DTE_IND;
in->dcnt = in->data[0];
in->sdev = (in->dcnt >> 8) & 0377;
in->dcnt &= 0377;
word |= PRI_CMT_TOT;
if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_STS, &word))
goto error;
} else {
dte_in_ptr = (dte_in_ptr + 1) & 0xf;
}
}
word &= ~PRI_CMT_TOT;
if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_STS, &word))
goto error;
uptr->STATUS |= DTE_11DN;
set_interrupt(DTE_DEVNUM, uptr->STATUS);
dte_function(uptr);
}
/* Process primary protocol packets */
void
dte_function(UNIT *uptr)
{
uint16 data1[32];
int32 ch;
struct _dte_queue *cmd;
int func;
int dev;
/* Check if queue is empty */
while (dte_in_cmd != dte_in_ptr) {
if (((dte_out_res + 1) & 0xf) == dte_out_ptr) {
sim_debug(DEBUG_DATA, &dte_dev, "DTE: func out full %d %d\n",
dte_out_res, dte_out_ptr);
return;
}