-
Notifications
You must be signed in to change notification settings - Fork 107
/
Copy pathpdp11_rp.c
1527 lines (1312 loc) · 63.4 KB
/
pdp11_rp.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
/* pdp11_rp.c - RP04/05/06/07 RM02/03/05/80 Massbus disk controller
Copyright (c) 1993-2017, Robert M Supnik
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
ROBERT M SUPNIK 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 Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
rp RH/RP/RM moving head disks
13-Mar-17 RMS Annotated intentional fall through in switch
23-Oct-13 RMS Revised for new boot setup routine
06-Mar-11 MP Converted to using sim_disk library and refactored
for Asynch I/O.
Set STIME value to default of 26 which allows VMS V4.x
to boot.
17-May-07 RMS CS1 DVA resides in device, not MBA
21-Nov-05 RMS Enable/disable device also enables/disables Massbus adapter
12-Nov-05 RMS Fixed DriveClear, does not clear disk address
16-Aug-05 RMS Fixed C++ declaration and cast problems
18-Mar-05 RMS Added attached test to detach routine
12-Sep-04 RMS Cloned from pdp11_rp.c
Note: The VMS driver and the RP controller documentation state that
ER2 = offset 8
SN = offset 12
But the TOPS-10 and TOPS-20 drivers, and the RP schematics state that
SN = offset 8
ER2 = offset 12
The simulation follows the schematics. The VMS drivers defines but does
not use these offsets, and the error logger follows the schematics.
*/
#if defined (VM_PDP10)
#error "PDP-10 uses pdp10_rp.c!"
#elif defined (VM_PDP11)
#include "pdp11_defs.h"
#define INIT_DTYPE RM03_DTYPE
#define INIT_SIZE RM03_SIZE
#elif defined (VM_VAX)
#include "vax_defs.h"
#define INIT_DTYPE RP06_DTYPE
#define INIT_SIZE RP06_SIZE
#define DMASK 0xFFFF
#if (!UNIBUS)
#error "Qbus not supported!"
#endif
#endif
#include "sim_disk.h"
#include <math.h>
#define RP_CTRL 0 /* ctrl is RP */
#define RM_CTRL 1 /* ctrl is RM */
#define RP_NUMDR 8 /* #drives */
#define RP_NUMWD 256 /* words/sector */
#define RP_MAXFR (1 << 16) /* max transfer */
#define GET_SECTOR(x,d) ((int) fmod (sim_gtime() / ((double) (x)), \
((double) drv_tab[d].sect)))
#define RM_OF (MBA_RMASK + 1)
/* Flags in the unit flags word */
#define UNIT_V_DTYPE (DKUF_V_UF + 0) /* disk type */
#define UNIT_M_DTYPE 7
#define UNIT_V_AUTO (DKUF_V_UF + 3) /* autosize */
#define UNIT_V_DUMMY (DKUF_V_UF + 4) /* dummy flag */
#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE)
#define UNIT_AUTO (1 << UNIT_V_AUTO)
#define UNIT_DUMMY (1 << UNIT_V_DUMMY)
#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE)
/* Parameters in the unit descriptor */
#define CYL u3 /* current cylinder */
#define sectsread u4 /* sectors read */
#define io_status u5 /* io status from callback */
#define io_complete u6 /* io completion flag */
/* RPCS1, RMCS1 - control/status 1 - offset 0 */
#define RP_CS1_OF 0
#define RM_CS1_OF (0 + RM_OF)
#define CS1_GO CSR_GO /* go */
#define CS1_V_FNC 1 /* function pos */
#define CS1_M_FNC 037 /* function mask */
#define CS1_N_FNC (CS1_M_FNC + 1)
#define FNC_NOP 000 /* no operation */
#define FNC_UNLOAD 001 /* unload */
#define FNC_SEEK 002 /* seek */
#define FNC_RECAL 003 /* recalibrate */
#define FNC_DCLR 004 /* drive clear */
#define FNC_RELEASE 005 /* port release */
#define FNC_OFFSET 006 /* offset */
#define FNC_RETURN 007 /* return to center */
#define FNC_PRESET 010 /* read-in preset */
#define FNC_PACK 011 /* pack acknowledge */
#define FNC_SEARCH 014 /* search */
#define FNC_XFER 024 /* >=? data xfr */
#define FNC_WCHK 024 /* write check */
#define FNC_WRITE 030 /* write */
#define FNC_WRITEH 031 /* write w/ headers */
#define FNC_READ 034 /* read */
#define FNC_READH 035 /* read w/ headers */
#define CS1_RW 076
#define CS1_DVA 04000 /* drive avail */
#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC)
static const char *rp_fname[CS1_N_FNC] = {
"NOP", "UNLD", "SEEK", "RECAL", "DCLR", "RLS", "OFFS", "RETN",
"PRESET", "PACK", "12", "13", "SEARCH", "15", "16", "17",
"20", "21", "22", "23", "WRCHK", "25", "26", "27",
"WRITE", "WRHDR", "32", "33", "READ", "RDHDR", "36", "37"
};
BITFIELD rp_cs1_bits[] = {
BIT(GO), /* Go */
BITFNAM(FUNC,5,rp_fname), /* Function Code */
BIT(IE), /* Interrupt Enable */
BIT(RDY), /* Drive Ready */
BIT(A16), /* Bus Address Extension Bit 16 */
BIT(A17), /* Bus Address Extension Bit 17 */
BIT(PSEL), /* Port Select */
BIT(DVA), /* Drive Available */
BITNCF(1), /* 12 Reserved */
BIT(MCPE), /* Massbus Control Parity Error */
BIT(TRE), /* Transfer Error */
BIT(SC), /* Special Condition */
ENDBITS
};
/* RPDS, RMDS - drive status - offset 1 */
#define RP_DS_OF 1
#define RM_DS_OF (1 + RM_OF)
#define DS_OFM 0000001 /* offset mode */
#define DS_VV 0000100 /* volume valid */
#define DS_RDY 0000200 /* drive ready */
#define DS_DPR 0000400 /* drive present */
#define DS_PGM 0001000 /* programable NI */
#define DS_LST 0002000 /* last sector */
#define DS_WRL 0004000 /* write locked */
#define DS_MOL 0010000 /* medium online */
#define DS_PIP 0020000 /* pos in progress */
#define DS_ERR 0040000 /* error */
#define DS_ATA 0100000 /* attention active */
#define DS_MBZ 0000076
BITFIELD rp_ds_bits[] = {
BIT(OM), /* offset mode */
BITF(MBZ,5), /* must be zero */
BIT(VV), /* volume valid */
BIT(RDY), /* drive ready */
BIT(DPR), /* drive present */
BIT(PGM), /* programmable NI */
BIT(LST), /* write clk fail NI */
BIT(WRL), /* ECC hard err NI */
BIT(MOL), /* hdr comp err NI */
BIT(PIP), /* hdr CRC err NI */
BIT(ERR), /* addr ovflo err */
BIT(ATA), /* invalid addr err */
ENDBITS
};
/* RPER1, RMER1 - error status 1 - offset 2 */
#define RP_ER1_OF 2
#define RM_ER1_OF (2 + RM_OF)
#define ER1_ILF 0000001 /* illegal func */
#define ER1_ILR 0000002 /* illegal register */
#define ER1_RMR 0000004 /* reg mod refused */
#define ER1_PAR 0000010 /* parity err */
#define ER1_FER 0000020 /* format err NI */
#define ER1_WCF 0000040 /* write clk fail NI */
#define ER1_ECH 0000100 /* ECC hard err NI */
#define ER1_HCE 0000200 /* hdr comp err NI */
#define ER1_HCR 0000400 /* hdr CRC err NI */
#define ER1_AOE 0001000 /* addr ovflo err */
#define ER1_IAE 0002000 /* invalid addr err */
#define ER1_WLE 0004000 /* write lock err */
#define ER1_DTE 0010000 /* drive time err NI */
#define ER1_OPI 0020000 /* op incomplete */
#define ER1_UNS 0040000 /* drive unsafe */
#define ER1_DCK 0100000 /* data check NI */
BITFIELD rp_er1_bits[] = {
BIT(ILF), /* Illegal Function */
BIT(ILR), /* Illegal Register */
BIT(RMR), /* reg mod refused */
BIT(PAR), /* parity err */
BIT(FER), /* format err NI */
BIT(WCF), /* write clk fail NI */
BIT(ECH), /* ECC hard err NI */
BIT(HCE), /* hdr comp err NI */
BIT(HCR), /* hdr CRC err NI */
BIT(AOE), /* addr ovflo err */
BIT(IAE), /* invalid addr err */
BIT(WLE), /* write lock err */
BIT(DTE), /* drive time err NI */
BIT(OPI), /* op incomplete */
BIT(UNS), /* drive unsafe */
BIT(DCK), /* data check NI */
ENDBITS
};
/* RPMR, RMMR - maintenace register - offset 3*/
#define RP_MR_OF 3
#define RM_MR_OF (3 + RM_OF)
BITFIELD rp_mr_bits[] = {
BITF(MR,16), /* Maintenance Register */
ENDBITS
};
/* RPAS, RMAS - attention summary - offset 4 */
#define RP_AS_OF 4
#define RM_AS_OF (4 + RM_OF)
#define AS_U0 0000001 /* unit 0 flag */
BITFIELD rp_as_bits[] = {
BIT(ATA0), /* Drive 0 Attention */
BIT(ATA1), /* Drive 1 Attention */
BIT(ATA2), /* Drive 2 Attention */
BIT(ATA3), /* Drive 3 Attention */
BIT(ATA4), /* Drive 4 Attention */
BIT(ATA5), /* Drive 5 Attention */
BIT(ATA6), /* Drive 6 Attention */
BIT(ATA7), /* Drive 7 Attention */
BITNCF(8), /* 08:15 Reserved */
ENDBITS
};
/* RPDA, RMDA - sector/track - offset 5 */
#define RP_DA_OF 5
#define RM_DA_OF (5 + RM_OF)
#define DA_V_SC 0 /* sector pos */
#define DA_M_SC 077 /* sector mask */
#define DA_V_SF 8 /* track pos */
#define DA_M_SF 077 /* track mask */
#define DA_MBZ 0140300
#define GET_SC(x) (((x) >> DA_V_SC) & DA_M_SC)
#define GET_SF(x) (((x) >> DA_V_SF) & DA_M_SF)
BITFIELD rp_da_bits[] = {
BITF(SA,5), /* Sector Address */
BITNCF(3), /* 05:07 Reserved */
BITF(TA,5), /* Track Address */
BITNCF(3), /* 13:15 Reserved */
ENDBITS
};
/* RPDT, RMDT - drive type - offset 6 */
#define RP_DT_OF 6
#define RM_DT_OF (6 + RM_OF)
BITFIELD rp_dt_bits[] = {
BITF(DT,9), /* Drive Type */
BITNCF(2), /* 09:10 Reserved */
BIT(DRQ), /* Drive Request Required */
BITNCF(1), /* 12 Reserved */
BIT(MOH), /* Moving Head */
BITNCF(2), /* 14:15 Reserved */
ENDBITS
};
/* RPLA, RMLA - look ahead register - offset 7 */
#define RP_LA_OF 7
#define RM_LA_OF (7 + RM_OF)
#define LA_V_SC 6 /* sector pos */
BITFIELD rp_la_bits[] = {
BITNCF(6), /* 00:05 Reserved */
BITF(SC,5), /* sector pos */
BITNCF(5), /* 12:15 Reserved */
ENDBITS
};
/* RPSN, RMSN - serial number - offset 8 */
#define RP_SN_OF 8
#define RM_SN_OF (8 + RM_OF)
BITFIELD rp_sn_bits[] = {
BITF(SN,16), /* Serial Number */
ENDBITS
};
/* RPOF, RMOF - offset register - offset 9 */
#define RP_OF_OF 9
#define RM_OF_OF (9 + RM_OF)
#define OF_HCI 0002000 /* hdr cmp inh NI */
#define OF_ECI 0004000 /* ECC inhibit NI */
#define OF_F22 0010000 /* format NI */
#define OF_MBZ 0161400
BITFIELD rp_of_bits[] = {
BITNCF(7), /* 00:06 Reserved */
BIT(OFFDIR), /* Offset Direction */
BITNCF(2), /* 08:09 Reserved */
BIT(HCI), /* hdr comp inh NI */
BIT(ECI), /* ECC inh NI */
BIT(FMT), /* format NI */
BITNCF(3), /* 13:15 Reserved */
ENDBITS
};
/* RPDC, RMDC - desired cylinder - offset 10 */
#define RP_DC_OF 10
#define RM_DC_OF (10 + RM_OF)
#define DC_V_CY 0 /* cylinder pos */
#define DC_M_CY 01777 /* cylinder mask */
#define DC_MBZ 0176000
#define GET_CY(x) (((x) >> DC_V_CY) & DC_M_CY)
#define GET_DA(c,fs,d) ((((GET_CY (c) * drv_tab[d].surf) + \
GET_SF (fs)) * drv_tab[d].sect) + GET_SC (fs))
BITFIELD rp_dc_bits[] = {
BITF(DC,10), /* Offset Direction */
BITNCF(6), /* 10:15 Unused */
ENDBITS
};
/* RPCC - current cylinder - offset 11
RMHR - holding register - offset 11 */
#define RP_CC_OF 11
#define RM_HR_OF (11 + RM_OF)
BITFIELD rp_cc_bits[] = {
BITF(CC,16), /* current cylinder */
ENDBITS
};
/* RPER2 - error status 2 - drive unsafe conditions - unimplemented - offset 12
RMMR2 - maintenance register - unimplemented - offset 12 */
#define RP_ER2_OF 12
#define RM_MR2_OF (12 + RM_OF)
BITFIELD rp_er2_bits[] = {
BITNCF(3), /* 00:02 Unused */
BIT(DPE), /* data parity error */
BITNCF(3), /* 04:06 Unused */
BIT(DVC), /* device check */
BITNCF(2), /* 08:09 Unused */
BIT(LBC), /* Loss of bit clock */
BIT(LSC), /* Loss of system clock */
BIT(IVC), /* Invalid Command */
BIT(OPE), /* Operator Plug Error */
BIT(SKI), /* Seek Incomplete */
BIT(BSE), /* Bad Sector Error */
ENDBITS
};
/* RPER3 - error status 3 - more unsafe conditions - unimplemented - offset 13
RMER2 - error status 2 - unimplemented - offset 13 */
#define RP_ER3_OF 13
#define RM_ER2_OF (13 + RM_OF)
BITFIELD rp_er3_bits[] = {
BITNCF(3), /* 00:02 Unused */
BIT(DPE), /* data parity error */
BITNCF(3), /* 04:06 Unused */
BIT(DVC), /* device check */
BITNCF(2), /* 08:09 Unused */
BIT(LBC), /* Loss of bit clock */
BIT(LSC), /* Loss of system clock */
BIT(IVC), /* Invalid Command */
BIT(OPE), /* Operator Plug Error */
BIT(SKI), /* Seek Incomplete */
BIT(BSE), /* Bad Sector Error */
ENDBITS
};
/* RPEC1, RMEC1 - ECC status 1 - unimplemented - offset 14 */
#define RP_EC1_OF 14
#define RM_EC1_OF (14 + RM_OF)
BITFIELD rp_ec1_bits[] = {
BITF(P,13), /* ECC Position Register */
BITNCF(3), /* 13:15 Unused */
ENDBITS
};
/* RPEC2, RMEC1 - ECC status 2 - unimplemented - offset 15 */
#define RP_EC2_OF 15
#define RM_EC2_OF (15 + RM_OF)
BITFIELD rp_ec2_bits[] = {
BITF(PAT,11), /* ECC Pattern Register */
BITNCF(5), /* 11:15 Unused */
ENDBITS
};
BITFIELD *rp_reg_bits[] = {
rp_cs1_bits,
rp_ds_bits,
rp_er1_bits,
rp_mr_bits,
rp_as_bits,
rp_da_bits,
rp_dt_bits,
rp_la_bits,
rp_sn_bits,
rp_of_bits,
rp_dc_bits,
rp_cc_bits,
rp_er2_bits,
rp_er3_bits,
rp_ec1_bits,
rp_ec2_bits,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
rp_cs1_bits,
rp_ds_bits,
rp_er1_bits,
rp_mr_bits,
rp_as_bits,
rp_da_bits,
rp_dt_bits,
rp_la_bits,
rp_sn_bits,
rp_of_bits,
rp_dc_bits,
rp_cc_bits,
rp_er2_bits,
rp_er3_bits,
rp_ec1_bits,
rp_ec2_bits,
};
/* This controller supports many different disk drive types:
type #sectors/ #surfaces/ #cylinders/
surface cylinder drive
RM02/3 32 5 823 =67MB
RP04/5 22 19 411 =88MB
RM80 31 14 559 =124MB
RP05 22 19 411 =88MB
RP06 22 19 815 =176MB
RM05 32 19 823 =256MB
RP07 50 32 630 =516MB
In theory, each drive can be a different type. The size field in
each unit selects the drive capacity for each drive and thus the
drive type. DISKS MUST BE DECLARED IN ASCENDING SIZE.
Note: the RP07, despite its designation, belongs to the RM family
*/
#define RM03_DTYPE 0
#define RM03_SECT 32
#define RM03_SURF 5
#define RM03_CYL 823
#define RM03_DEC144 1
#define RM03_DEV 020024
#define RM03_SIZE (RM03_SECT * RM03_SURF * RM03_CYL * RP_NUMWD)
#define RP04_DTYPE 1
#define RP04_SECT 22
#define RP04_SURF 19
#define RP04_CYL 411
#define RP04_DEC144 0
#define RP04_DEV 020020
#define RP04_SIZE (RP04_SECT * RP04_SURF * RP04_CYL * RP_NUMWD)
#define RP05_DTYPE 2
#define RP05_SECT 22
#define RP05_SURF 19
#define RP05_CYL 411
#define RP05_DEC144 0
#define RP05_DEV 020021
#define RP05_SIZE (RP05_SECT * RP05_SURF * RP05_CYL * RP_NUMWD)
#define RM80_DTYPE 3
#define RM80_SECT 31
#define RM80_SURF 14
#define RM80_CYL 559
#define RM80_DEC144 1
#define RM80_DEV 020026
#define RM80_SIZE (RM80_SECT * RM80_SURF * RM80_CYL * RP_NUMWD)
#define RP06_DTYPE 4
#define RP06_SECT 22
#define RP06_SURF 19
#define RP06_CYL 815
#define RP06_DEC144 0
#define RP06_DEV 020022
#define RP06_SIZE (RP06_SECT * RP06_SURF * RP06_CYL * RP_NUMWD)
#define RM05_DTYPE 5
#define RM05_SECT 32
#define RM05_SURF 19
#define RM05_CYL 823
#define RM05_DEC144 1
#define RM05_DEV 020027
#define RM05_SIZE (RM05_SECT * RM05_SURF * RM05_CYL * RP_NUMWD)
#define RP07_DTYPE 6
#define RP07_SECT 50
#define RP07_SURF 32
#define RP07_CYL 630
#define RP07_DEC144 1
#define RP07_DEV 020042
#define RP07_SIZE (RP07_SECT * RP07_SURF * RP07_CYL * RP_NUMWD)
struct drvtyp {
int32 sect; /* sectors */
int32 surf; /* surfaces */
int32 cyl; /* cylinders */
int32 size; /* #blocks */
int32 devtype; /* device type */
int32 dec144; /* DEC Std 144 bad block */
int32 ctrl; /* ctrl type */
const char *name; /* device type name */
};
static struct drvtyp drv_tab[] = {
{ RM03_SECT, RM03_SURF, RM03_CYL, RM03_SIZE, RM03_DEV, RM03_DEC144, RM_CTRL, "RM03" },
{ RP04_SECT, RP04_SURF, RP04_CYL, RP04_SIZE, RP04_DEV, RP04_DEC144, RP_CTRL, "RP04" },
{ RP05_SECT, RP05_SURF, RP05_CYL, RP05_SIZE, RP05_DEV, RP05_DEC144, RP_CTRL, "RP05" },
{ RM80_SECT, RM80_SURF, RM80_CYL, RM80_SIZE, RM80_DEV, RM80_DEC144, RM_CTRL, "RM80" },
{ RP06_SECT, RP06_SURF, RP06_CYL, RP06_SIZE, RP06_DEV, RP06_DEC144, RP_CTRL, "RP06" },
{ RM05_SECT, RM05_SURF, RM05_CYL, RM05_SIZE, RM05_DEV, RM05_DEC144, RM_CTRL, "RM05" },
{ RP07_SECT, RP07_SURF, RP07_CYL, RP07_SIZE, RP07_DEV, RP07_DEC144, RM_CTRL, "RP07" },
{ 0 }
};
uint16 *rpxb[RP_NUMDR] = { 0 }; /* xfer buffer */
uint16 rpcs1[RP_NUMDR] = { 0 }; /* control/status 1 */
uint16 rpda[RP_NUMDR] = { 0 }; /* track/sector */
uint16 rpds[RP_NUMDR] = { 0 }; /* drive status */
uint16 rper1[RP_NUMDR] = { 0 }; /* error status 1 */
uint16 rmhr[RP_NUMDR] = { 0 }; /* holding reg */
uint16 rpmr[RP_NUMDR] = { 0 }; /* maint reg */
uint16 rmmr2[RP_NUMDR] = { 0 }; /* maint reg 2 */
uint16 rpof[RP_NUMDR] = { 0 }; /* offset */
uint16 rpdc[RP_NUMDR] = { 0 }; /* cylinder */
uint16 rper2[RP_NUMDR] = { 0 }; /* error status 2 */
uint16 rper3[RP_NUMDR] = { 0 }; /* error status 3 */
uint16 rpec1[RP_NUMDR] = { 0 }; /* ECC correction 1 */
uint16 rpec2[RP_NUMDR] = { 0 }; /* ECC correction 2 */
uint16 rpxbc[RP_NUMDR] = { 0 }; /* Byte Count Copy */
int32 rp_stopioe = 1; /* stop on error */
int32 rp_swait = 26; /* seek time */
int32 rp_rwait = 10; /* rotate time */
t_stat rp_mbrd (int32 *data, int32 ofs, int32 drv);
t_stat rp_mbwr (int32 data, int32 ofs, int32 drv);
t_stat rp_svc (UNIT *uptr);
t_stat rp_reset (DEVICE *dptr);
t_stat rp_attach (UNIT *uptr, CONST char *cptr);
t_stat rp_detach (UNIT *uptr);
t_stat rp_boot (int32 unitno, DEVICE *dptr);
void rp_set_er (int16 flg, int32 drv);
void rp_clr_as (int32 mask);
void rp_update_ds (uint16 flg, int32 drv);
t_stat rp_go (int32 drv);
t_stat rp_set_type (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat rp_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat rp_set_bad (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
int32 rp_abort (void);
t_stat rp_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
const char *rp_description (DEVICE *dptr);
/* RP data structures
rp_dev RP device descriptor
rp_unit RP unit list
rp_reg RP register list
rp_mod RP modifier list
*/
#define IOLN_RP 054
DIB rp_dib = { MBA_AUTO, IOLN_RP, &rp_mbrd, &rp_mbwr, 0, 0, 0, { &rp_abort } };
UNIT rp_unit[] = {
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
UNIT_ROABLE+(INIT_DTYPE << UNIT_V_DTYPE), INIT_SIZE) }
};
REG rp_reg[] = {
{ BRDATADF (CS1, rpcs1, DEV_RDX, 16, RP_NUMDR, "current operation", rp_cs1_bits) },
{ BRDATADF (DA, rpda, DEV_RDX, 16, RP_NUMDR, "desired surface, sector", rp_da_bits) },
{ BRDATADF (DS, rpds, DEV_RDX, 16, RP_NUMDR, "drive status", rp_ds_bits) },
{ BRDATADF (ER1, rper1, DEV_RDX, 16, RP_NUMDR, "drive errors", rp_er1_bits) },
{ BRDATAD (HR, rmhr, DEV_RDX, 16, RP_NUMDR, "holding register") },
{ BRDATADF (OF, rpof, DEV_RDX, 16, RP_NUMDR, "offset", rp_of_bits) },
{ BRDATADF (DC, rpdc, DEV_RDX, 16, RP_NUMDR, "desired cylinder", rp_dc_bits) },
{ BRDATADF (ER2, rper2, DEV_RDX, 16, RP_NUMDR, "error status 2", rp_er2_bits) },
{ BRDATADF (ER3, rper3, DEV_RDX, 16, RP_NUMDR, "error status 3", rp_er3_bits) },
{ BRDATADF (EC1, rpec1, DEV_RDX, 16, RP_NUMDR, "ECC syndrome 1", rp_ec1_bits) },
{ BRDATADF (EC2, rpec2, DEV_RDX, 16, RP_NUMDR, "ECC syndrome 2", rp_ec2_bits) },
{ BRDATADF (MR, rpmr, DEV_RDX, 16, RP_NUMDR, "maintenance register", rp_mr_bits) },
{ BRDATAD (MR2, rmmr2, DEV_RDX, 16, RP_NUMDR, "maintenance register 2 (RM only)") },
{ DRDATAD (STIME, rp_swait, 24, "seek time, per cylinder"), REG_NZ + PV_LEFT },
{ DRDATAD (RTIME, rp_rwait, 24, "rotational delay"), REG_NZ + PV_LEFT },
{ URDATA (CAPAC, rp_unit[0].capac, 10, T_ADDR_W, 0,
RP_NUMDR, PV_LEFT | REG_HRO) },
{ FLDATAD (STOP_IOE, rp_stopioe, 0, "stop on I/O error") },
{ GRDATA (CTRLTYPE, rp_dib.lnt, DEV_RDX, 16, 0), REG_HRO },
{ NULL }
};
MTAB rp_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "MASSBUS", NULL,
NULL, &mba_show_num, NULL, "Display Massbus number" },
{ MTAB_XTD|MTAB_VUN, 0, "write enabled", "WRITEENABLED",
&set_writelock, &show_writelock, NULL, "Write enable disk drive" },
{ MTAB_XTD|MTAB_VUN, 1, NULL, "LOCKED",
&set_writelock, NULL, NULL, "Write lock disk drive" },
{ UNIT_DUMMY, 0, NULL, "BADBLOCK",
&rp_set_bad, NULL, NULL, "write bad block table on last track" },
{ MTAB_XTD|MTAB_VUN, RM03_DTYPE, NULL, "RM03",
&rp_set_type, NULL, NULL, "Set RM03 Disk Type" },
{ MTAB_XTD|MTAB_VUN, RP04_DTYPE, NULL, "RP04",
&rp_set_type, NULL, NULL, "Set RP04 Disk Type" },
{ MTAB_XTD|MTAB_VUN, RP05_DTYPE, NULL, "RP05",
&rp_set_type, NULL, NULL, "Set RP05 Disk Type" },
{ MTAB_XTD|MTAB_VUN, RM80_DTYPE, NULL, "RM80",
&rp_set_type, NULL, NULL, "Set RM80 Disk Type" },
{ MTAB_XTD|MTAB_VUN, RP06_DTYPE, NULL, "RP06",
&rp_set_type, NULL, NULL, "Set RP06 Disk Type" },
{ MTAB_XTD|MTAB_VUN, RM05_DTYPE, NULL, "RM05",
&rp_set_type, NULL, NULL, "Set RM05 Disk Type" },
{ MTAB_XTD|MTAB_VUN, RP07_DTYPE, NULL, "RP07",
&rp_set_type, NULL, NULL, "Set RP07 Disk Type" },
{ MTAB_XTD|MTAB_VUN, 0, "TYPE", NULL,
NULL, &rp_show_type, NULL, "Display device type" },
{ UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE",
NULL, NULL, NULL, "Set type based on file size at attach" },
{ UNIT_AUTO, 0, "noautosize", "NOAUTOSIZE",
NULL, NULL, NULL, "Disable disk autosize on attach" },
{ MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "FORMAT", "FORMAT={AUTO|SIMH|VHD|RAW}",
&sim_disk_set_fmt, &sim_disk_show_fmt, NULL, "Set/Display disk format" },
{ 0 }
};
/* debugging bitmaps */
#define DBG_TRC 0x0001 /* trace routine calls */
#define DBG_REG 0x0002 /* trace read/write registers */
#define DBG_REQ 0x0004 /* display transfer requests */
#define DBG_DSK 0x0008 /* display sim_disk activities */
#define DBG_DAT 0x0010 /* display transfer data */
DEBTAB rp_debug[] = {
{"TRACE", DBG_TRC, "trace routine calls"},
{"REG", DBG_REG, "trace read/write registers"},
{"REQ", DBG_REQ, "display transfer requests"},
{"DISK", DBG_DSK, "display sim_disk activities"},
{"DATA", DBG_DAT, "display transfer data"},
{0}
};
DEVICE rp_dev = {
"RP", rp_unit, rp_reg, rp_mod,
RP_NUMDR, DEV_RDX, 30, 1, DEV_RDX, 16,
NULL, NULL, &rp_reset,
&rp_boot, &rp_attach, &rp_detach,
&rp_dib, DEV_DISABLE | DEV_UBUS | DEV_QBUS | DEV_MBUS | DEV_DEBUG | DEV_DISK,
0, rp_debug, NULL, NULL, &rp_help, NULL, NULL,
&rp_description
};
const char *rp_regnam[] =
{
"RP_CS1", /* 0 */
"RP_DS", /* 1 */
"RP_ER1", /* 2 */
"RP_MR", /* 3 */
"RP_AS", /* 4 */
"RP_DA", /* 5 */
"RP_DT", /* 6 */
"RP_LA", /* 7 */
"RP_SN", /* 8 */
"RP_OF", /* 9 */
"RP_DC", /* 10 */
"RP_CC", /* 11 */
"RP_ER2", /* 12 */
"RP_ER3", /* 13 */
"RP_EC1", /* 14 */
"RP_EC2", /* 15 */
"16", /* 16 */
"17", /* 17 */
"18", /* 18 */
"19", /* 19 */
"20", /* 20 */
"21", /* 21 */
"22", /* 22 */
"23", /* 23 */
"24", /* 24 */
"25", /* 25 */
"26", /* 26 */
"27", /* 27 */
"28", /* 28 */
"29", /* 29 */
"30", /* 30 */
"31", /* 31 */
"RM_CS1", /* 32 */
"RM_DS", /* 33 */
"RM_ER1", /* 34 */
"RM_MR", /* 35 */
"RM_AS", /* 36 */
"RM_DA", /* 37 */
"RM_DT", /* 38 */
"RM_LA", /* 39 */
"RM_SN", /* 40 */
"RM_OF", /* 41 */
"RM_DC", /* 42 */
"RM_CC", /* 43 */
"RM_MR2", /* 44 */
"RM_ER2", /* 45 */
"RM_EC1", /* 46 */
"RM_EC2", /* 47 */
"48", /* 48 */
"49", /* 49 */
"50", /* 50 */
"51", /* 51 */
"52", /* 52 */
"53", /* 53 */
"54", /* 54 */
"55", /* 55 */
"56", /* 56 */
"57", /* 57 */
"58", /* 58 */
"59", /* 59 */
"60", /* 60 */
"61", /* 61 */
"62", /* 62 */
"63", /* 63 */
};
/* Massbus register read */
t_stat rp_mbrd (int32 *data, int32 ofs, int32 drv)
{
uint32 val, dtype, i;
UNIT *uptr;
rp_update_ds (0, drv); /* update ds */
uptr = rp_dev.units + drv; /* get unit */
if (uptr->flags & UNIT_DIS) { /* nx disk */
*data = 0;
return MBE_NXD;
}
dtype = GET_DTYPE (uptr->flags); /* get drive type */
ofs = ofs & MBA_RMASK; /* mask offset */
if (drv_tab[dtype].ctrl == RM_CTRL) /* RM? convert */
ofs = ofs + RM_OF;
switch (ofs) { /* decode offset */
case RP_CS1_OF: case RM_CS1_OF: /* RPCS1 */
val = (rpcs1[drv] & CS1_RW) | CS1_DVA; /* DVA always set */
break;
case RP_DA_OF: case RM_DA_OF: /* RPDA */
val = rpda[drv] = rpda[drv] & ~DA_MBZ;
break;
case RP_DS_OF: case RM_DS_OF: /* RPDS */
val = rpds[drv];
break;
case RP_ER1_OF: case RM_ER1_OF: /* RPER1 */
val = rper1[drv];
break;
case RP_AS_OF: case RM_AS_OF: /* RPAS */
val = 0;
for (i = 0; i < RP_NUMDR; i++) {
if (rpds[i] & DS_ATA)
val |= (AS_U0 << i);
}
break;
case RP_LA_OF: case RM_LA_OF: /* RPLA */
val = GET_SECTOR (rp_rwait, dtype) << LA_V_SC;
break;
case RP_MR_OF: case RM_MR_OF: /* RPMR */
val = rpmr[drv];
break;
case RP_DT_OF: case RM_DT_OF: /* RPDT */
val = drv_tab[dtype].devtype;
break;
case RP_SN_OF: case RM_SN_OF: /* RPSN */
val = 020 | (drv + 1);
break;
case RP_OF_OF: case RM_OF_OF: /* RPOF */
val = rpof[drv] = rpof[drv] & ~OF_MBZ;
break;
case RP_DC_OF: case RM_DC_OF: /* RPDC */
val = rpdc[drv] = rpdc[drv] & ~DC_MBZ;
break;
case RP_CC_OF: /* RPCC */
val = rp_unit[drv].CYL;
break;
case RP_ER2_OF: case RM_ER2_OF: /* RPER2 */
val = rper2[drv];
break;
case RP_ER3_OF: /* RPER3 */
val = rper3[drv];
break;
case RP_EC1_OF: case RM_EC1_OF: /* RPEC1 */
val = rpec1[drv];
break;
case RP_EC2_OF: case RM_EC2_OF: /* RPEC2 */
val = rpec2[drv];
break;
case RM_HR_OF: /* RMHR */
val = rmhr[drv] ^ DMASK;
break;
case RM_MR2_OF: /* RHMR2 */
val = rmmr2[drv];
break;
default: /* all others */
*data = 0;
return MBE_NXR;
}
sim_debug(DBG_REG, &rp_dev, "rp_mbrd(drv=%d(%s), %s=0x%X)\n", drv, drv_tab[dtype].name, rp_regnam[ofs], val);
sim_debug_bits(DBG_REG, &rp_dev, rp_reg_bits[ofs], val, val, 1);
*data = val;
return SCPE_OK;
}
/* Massbus register write */
t_stat rp_mbwr (int32 data, int32 ofs, int32 drv)
{
uint32 old_reg;
UNIT *uptr = rp_dev.units + drv; /* get unit */
int32 dtype = GET_DTYPE (uptr->flags); /* get drive type */
sim_debug(DBG_REG, &rp_dev, "rp_mbwr(drv=%d(%s), %s=0x%X)\n", drv, drv_tab[dtype].name, rp_regnam[ofs], data);
if (uptr->flags & UNIT_DIS) /* nx disk */
return MBE_NXD;
if ((ofs != RP_AS_OF) && sim_is_active (uptr)) { /* unit busy? */
rp_set_er (ER1_RMR, drv); /* won't write */
rp_update_ds (0, drv);
return SCPE_OK;
}
rmhr[drv] = (uint16)data; /* save write */
ofs = ofs & MBA_RMASK; /* mask offset */
if (drv_tab[dtype].ctrl == RM_CTRL) /* RM? convert */
ofs = ofs + RM_OF;
switch (ofs) { /* decode PA<5:1> */
case RP_CS1_OF: case RM_CS1_OF: /* RPCS1 */
old_reg = rpcs1[drv];
rpcs1[drv] = data & CS1_RW;
sim_debug_bits(DBG_REG, &rp_dev, rp_reg_bits[ofs], old_reg, rpcs1[drv], 1);
if (data & CS1_GO) /* start op */
return rp_go (drv);
break;
case RP_DA_OF: case RM_DA_OF: /* RPDA */
old_reg = rpds[drv];
rpda[drv] = (uint16)(data & ~DA_MBZ);
sim_debug_bits(DBG_REG, &rp_dev, rp_reg_bits[ofs], old_reg, rpds[drv], 1);
break;
case RP_AS_OF: case RM_AS_OF: /* RPAS */
sim_debug_bits(DBG_REG, &rp_dev, rp_reg_bits[ofs], data, data, 1);
rp_clr_as (data);
break;
case RP_MR_OF: case RM_MR_OF: /* RPMR */
old_reg = rpmr[drv];
rpmr[drv] = (uint16)data;
sim_debug_bits(DBG_REG, &rp_dev, rp_reg_bits[ofs], old_reg, rpmr[drv], 1);
break;
case RP_OF_OF: case RM_OF_OF: /* RPOF */
old_reg = rpof[drv];
rpof[drv] = (uint16)(data & ~OF_MBZ);
sim_debug_bits(DBG_REG, &rp_dev, rp_reg_bits[ofs], old_reg, rpof[drv], 1);
break;
case RP_DC_OF: case RM_DC_OF: /* RPDC */
old_reg = rpdc[drv];
rpdc[drv] = (uint16)(data & ~DC_MBZ);
sim_debug_bits(DBG_REG, &rp_dev, rp_reg_bits[ofs], old_reg, rpdc[drv], 1);
break;
case RM_MR2_OF: /* RMMR2 */
old_reg = rmmr2[drv];
rmmr2[drv] = (uint16)data;
sim_debug_bits(DBG_REG, &rp_dev, rp_reg_bits[ofs], old_reg, rmmr2[drv], 1);
break;
case RP_ER1_OF: case RM_ER1_OF: /* RPER1 */
case RP_DS_OF: case RM_DS_OF: /* RPDS */
case RP_LA_OF: case RM_LA_OF: /* RPLA */
case RP_DT_OF: case RM_DT_OF: /* RPDT */
case RP_SN_OF: case RM_SN_OF: /* RPSN */
case RP_CC_OF: /* RPCC */
case RP_ER2_OF: case RM_ER2_OF: /* RPER2 */
case RP_ER3_OF: /* RPER3 */
case RP_EC1_OF: case RM_EC1_OF: /* RPEC1 */
case RP_EC2_OF: case RM_EC2_OF: /* RPEC2 */
case RM_HR_OF: /* RMHR */
break; /* read only */
default: /* all others */
return MBE_NXR;
} /* end switch */
rp_update_ds (0, drv); /* update status */
return SCPE_OK;
}
/* Initiate operation - unit not busy, function set */
t_stat rp_go (int32 drv)
{
int32 dc, fnc, t;
DEVICE *dptr = &rp_dev;
UNIT *uptr = dptr->units + drv; /* get unit */
int32 dtype = GET_DTYPE (uptr->flags); /* get drive type */
sim_debug(DBG_REQ, dptr, "rp_go(drv=%d(%s))\n", drv, drv_tab[dtype].name);
fnc = GET_FNC (rpcs1[drv]); /* get function */
sim_debug(DBG_REQ, dptr, ">>RP%d STRT: fnc=%s, ds=%o, cyl=%o, da=%o, er=%o\n",
drv, rp_fname[fnc], rpds[drv], rpdc[drv], rpda[drv], rper1[drv]);
rp_clr_as (AS_U0 << drv); /* clear attention */
dc = rpdc[drv]; /* assume seek, sch */
if ((fnc != FNC_DCLR) && (rpds[drv] & DS_ERR)) { /* err & ~clear? */
rp_set_er (ER1_ILF, drv); /* not allowed */
rp_update_ds (DS_ATA, drv); /* set attention */
return MBE_GOE;