-
Notifications
You must be signed in to change notification settings - Fork 3
/
xxdpp.mac
4057 lines (3509 loc) · 101 KB
/
xxdpp.mac
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
.title XXDPP - XXDP+ Operating System Monitor
.nlist ttm
; XXDPP.MAC reconstructs the XXDP+ operating system source
;
; Build procedure (RUST/RT-11):
;
; %build
; macro xds:xxdpp/object:xdb:
; macro xds:xxdpp/list:xdb:xxdpp.lst/noobject
; r detab
; xdb:xxdpp.lst xdb:xxdpps.lst
; ^C
; link xdb:xxdpp/exe:xdb:xxdpp.img/map:xdb:/cross/nobitmap
; differ/binary xdb:xxdpp.img xds:hmdld0.img
; %end
;
; Edit History:
;
; 01 01-Jan-2000 IJH Disassemble and study XXDP+
; 02 14-Mar-2021 IJH Complete initial source code recovery
;
; Source introduction:
;
; XXDP was/is the diagnostic operating system for PDP-11 computers.
; This source file was created by reverse assembling the binary image
; of the XXDP+ HMDLD0 monitor found on XXDP23 distribution.
;
; XXDP constitutes the de factor definition of the PDP-11, as anyone
; who writes an emulator soon finds out. It's the toughest the PDP-11
; systems, case-hardened by its use on only partially functioning
; systems.
;
; XXDP's architecture is based on a simple, near-boolean level state
; machine. There is rarely any analytic vagueness regarding system
; state.
;
; XXDP has a remarkably flat structure. Registers rarely need to be
; saved/restored across routines (less than 10 instances). All
; parameters and results are passed in registers, obeying a strict
; usage protocol.
;
; Because of the fixed space restrictions placed on the monitor, code
; compression was always required to find space for new functionality.
; XXDP uses many software techniques to achieve that goal. The code
; is heavily compressed.
;
; One overarching simplification is the almost complete absence of
; sanity testing. It will accept any disk volume as an XXDP volume,
; no matter how crazy the directory structure might appear. It tests
; only for conditions that make it impossible to continue.
;
; The original XXDP+ would of course have had separate source modules
; for the monitor and the various drivers. For this stage of the
; recovery process I've thought it best to have everything in a single
; source module with no external dependencies.
;
; The monitor source code translation is complete with this release.
; However, the documentation requires a programmer's guide and a system
; logic manual, at some distant point in time. For clarity I have not
; used macro definitions for system EMT calls in this, preferring to
; see all the binary code instructions. A later release should employ
; macros for system calls. The comments can also be improved.
;
; The XXDP monitor itself is restricted to read-only support for system
; media. The other half of the system, that creates and writes files,
; is buried in a DRVCOM package that are embedded in the UPD1, UPD2,
; PATCH and XTECO utilities and the stand-alone drivers.
;
; I began looking at XXDP around year 2000 when I used it to test a
; PDP-11 emulator I'd written. I got curious and wrote a simple
; disassembler and began annotating it (which I came back to in 2010
; and 2015). At first I approached the project as an act of diligence:
; I thought the source was important for the history of the PDP-11.
; However, it turned out to be a fascinating task and it was a real
; joy to see the operating system as a whole slowly emerge. There were
; so many subtleties to be discovered. There's some horrible HELLO
; WORLD coding here and there, but most of it is tight and the state
; machine design is highly disciplined.
;
; Some grateful acknowledgements:
;
; I spent so much time in Al Kossow's amazing bitsavers.org that I
; thought I should start paying rent. I crawled endlessly through
; diagnostics, looking for tiny clues. Joerg Hoppe's extensive XXDP
; microfiche contributions to bitsavers included some critical sources.
; A sometime DEC diagnostic programmer, Michael Moroney, who visited
; alt.sys.pdp11 some years ago, was kind enough to dig up and send me
; a copy of MACROM.MAC, the XXDP+ system macro module, which was truly
; invaluable: I had "names" for the system services. There have been
; quite a few valuable websites that have dedicated time and space to
; XXDP over the years from which I have gleaned information.
.sbttl XXDP API (data)
; I've renamed the system services to reflect their functional
; role within the monitor. The original service names are listed
; in the MACROM column
;
; EMT XXDPP MACROM Function
; --- ------ ------ --------
; 000 GetLin GCmdSt Get terminal/batch command line
; 001 ParFld GToken Parse next command line field
; 002 TypMon PutLin Type (relocated) monitor message
; 003 TypMsg TypMsg Type (unrelocated) message
; 004 PutChk PutChr Display character, check for Ctrl/C
; 005 GetAvl CKybd Check keyboard character available
; 006 GetChk GetChr Get character and check for Ctrl-C
; 007 Newlin CrLf Display newline
; 010 PutTab Tabs Display tab
; 011 ParOct GetNum Parse octal number
; 012 OpnFil Open Open file
; 013 CloFil Close Close file
; 014 LoaFil Load Load LDA-format program
; 015 ReaWrd GetWrd Input word from file
; 016 ReaByt GetByt Input byte from file
; 017 PutCha OneChr Display character
; 020 ReaNxt NxtBlk Read next sequential block
; 021 ReaBlk BkRead Read any block
; 022 SetAbt SetErr Set abort location
; 023 JmpAbt Error Jump to abort location
; 024 CmpSpc CmpNam Compare filespecs
; 025 SpcAsc UPkNam Convert Rad50 to ascii
; 026 SetLin KSwitch Set terminal buffer address/length
; 027 GetDat Date Get the system date
; 030 OctAsc IToA Convert octal to ascii
; 031 GetDev Default Get system device information
; 032 RptFld RToken Repeat the current field
; 033 LptMod LinePtr Write output to printer
; 034 TerMod NoPrtr Restore terminal output
; 035 LoaSup AutoLoad Load supervisor program
; 036 ParDec GetDec Parse decimal number
; 037 PadTer Fill Write nulls to the terminal
; 040 PshBat PutScp Set batch mode
; 041 PopBat CChain Set terminal mode
; 042 GetCom Comm Get monitor information common
; 043 GetDrv Rdrive Copy the system driver
; 044 TypBrk FrcTyp Type breakthrough message
.MACRO API NAM COD
.macro nam
emt cod
.endm
.ENDM
API GetLin 0 ;
API ParFld 1 ;
API TypMon 2 ;
API TypMsg 3 ;
API PutChk 4 ;
API GetAvl 5 ;
API GetChk 6 ;
API NewLin 7 ;
API PutTab 10 ;
API ParOct 11 ;
API OpnFil 12 ;
API CloFil 13 ;
API LoaFil 14 ;
API ReaWrd 15 ;
API ReaByt 16 ;
API PutCha 17 ;
API ReaNxt 20 ;
API ReaBlk 21 ;
API SetAbt 22 ;
API JmpAbt 23 ;
API CmpSpc 24 ;
API SpcAsc 25 ;
API SetLin 26 ;
API GetDat 27 ;
API OctAsc 30 ;
API GetDev 31 ;
API RptFld 32 ;
API LptMod 33 ;
API TerMod 34 ;
API LoaSup 35 ;
API ParDec 36 ;
API PadTer 37 ;
API PshBat 40 ;
API PopBat 41 ;
API GetCom 42 ;
API GetDrv 43 ;
API TypBrk 44 ;
.MACRO ASSUME EX1 CND EX2 COM
.iif cnd <ex1>-<ex2>,.mexit
.error <ex1>-<ex2> ;;;assume ex1 cnd ex2: com
.ENDM
.MACRO FALL C
.iif eq c-.,.mexit
.error c-. ;fall c
.ENDM
.MACRO STACK C D E F G H I J
maval.=0
.irp manam.,<c d e f g h i j>
sp.'manam.=maval.
maval.=maval.+2
.endr
.ENDM
.sbttl constants (data)
; CPU and device vectors
v$ebus = 4 ; bus error
v$ecpu = 10 ; cpu error
v$eemt = 30 ; emt
v$eltc = 100 ; line clock
v$ekwp = 104 ; kw11p clock
; Hardware registers
TKS = 177560 ; keyboard CSR
TKB = 177562 ; keyboard buffer
TPS = 177564 ; terminal output CSR
TPB = 177566 ; terminal output buffer
PSW = 177776 ; PSW
cbit = 1 ; PSW carry bit
;
LTC = 177546 ; line clock
KWP = 172540 ; KW11P clock
LPT = 177514 ; line printer
; S$YCFG - hardware config flags
syLTC$ = 1 ; line clock present
syKWP$ = 2 ; programmable clock present
syLPT$ = 4 ; line printer present
syNUB$ = 10 ; NoUniBus
sy50H$ = 20 ; 50 Hertz clock
; Terminal constants
ht = 11 ; tab
lf = 12 ; line feed
cr = 15 ; carriage return
space = 40 ; space
del = 177 ; delete/rubout
;
; Control keys
ctrlc = 3 ; ^C - cancel activity or pause DRS batch file
ctrlq = 21 ; ^Q - resume terminal output
ctrls = 23 ; ^S - pause terminal output
ctrlu = 25 ; ^U - cancel line
ctrlx = 30 ; ^X - resume after batch WAIT
ctrlz = 32 ; ^Z - terminate DRS batch file
.sbttl Monitor structure (data)
; Memory layout
;
; kw memory kw image disk pointer label
; --------- -------- ---- ------- -----
; 28 160000 4 20000 s$ytop: x$xtop: I/O page
; 157777 17777 x$xlim: Address limit
; 157xxx 17xxx x$xdrv: Driver
; 27 154000 3 14000 x$xsta: Static
; 152000 12000 12 s$yper: x$xper: Permanent
; 26 150000 2 10000 10 s$ytra: x$xtra: Transient
; 146000 06000 06 x$xbat: Batch
; 25 144000 1 04000 x$xhgh: Init high
; 141000 01000 01 x$xini: Init and MFD
; 24 140000 0 00000 00 s$yrel: x$xbot: Boot
; 137000 s$ysup: x$xsup: Supervisor
;
; Monitor region block numbers
; moBOO. = 0 ; boot
; moMFD. = 1 ; MFD block
moBAT. = 6 ; batch area block
moTRA. = 8. ; transient area block
moCLI. = 10. ; cli area block
moOVL. = 1414 ; monitor overlay length
; MFD block
mf.ufd = 0 ;1002 ;
mf.mon = 24 ;1026 ;
; Init information block
; in.50h = 0 ;1000 ; 50 hertz flag
; in.aut = 2 ;1002 ; automated startup flag
; Low memory syscom variables
;
; I've left these locations as absolute addresses.
;
; @#40 .byte = system device unit number
; @#41 .byte = LMD - low media code
; @#42 .word = batch diagnostic managed exit path
;
; @#52 .word job status word
;
scMAN$ = 1 ; Manual control flag (SMI/CMI)
; scXMA$ = 10000 ; XM-monitor app (XXDP V2)
;
; @#200 start: default LDA start address
; patched to default "JMP @#2100" by LoaFil
; Command line structure
; cl.ptr = 0 ; command line base pointer
; cl.len = 2 ; command line length
; cllen. = 44. ;54 ; default command line length
; clavl. = 42. ;52 ; available characters
; Device information block
dv.nam = 0 ;"DL" ; driver name
dv.uni = 2 ;"0" ; device unit
dv.med = 3 ;dlMED. ; media code
dvRK5. = 2 ;2 ; DK: disk (RT-11 RK:)
dvRL1. = 14 ;12. ; DL: disk
; Driver interface
dr.buf = -22. ; 752 ; buffer pointer
dr.ent = -20. ; 754 ; directory entry number in segment
dr.fnm = -18. ; 756 ; rad50 filename
dr.sbl = -12. ; 764 ; first file block
dr.opn = -10. ; 766 ; open file function
dr.rst = -8. ; 770 ; read monitor function
dr.tra = -6 ; 772 ; transfer function
dr.dev = -4 ; 774 ; get device info function
dr.uni = -2 ; 776 ; device unit
dr.sts = -1 ; 777 ; operation status
dr.csr = 0 ; 000 ; CSR address
io.wct = 2 ; 002 ; word count
io.buf = 4 ; 004 ; buffer address
io.blk = 6 ; 006 ; block number
io.ufd = 8. ; 012 ; (user file) directory start block
io.spc = 10. ; 014 ; ascii filespec
; dr.sts - driver status
; drSUC. = 0 ; an absence of errors
; drTRA. = -1 ; dr.tra - transfer error
; drFNF. = 1 ; dr.opn - file not found
.sbttl XXDP disk structure (data)
; HOMBLK - XXDP MFD block
hbblk. = 1 ; block 1 (for DL:)
hbbas. = 1000 ; disk byte address
hb.nxt = 0 ;0 ; next block (always zero)
hb.ufd = 2 ; ; first UFD directory block
; hb.dbc = 4 ; ; directory block count
; hb.map = 6 ; ; first map block
; hb.mbc = 10 ; ; map block count
; hb.mfd = 12 ; ; MFD block (self-reference to block 1)
; hb.ver = 14 ; ; XXDP version (never seen used)
; dbxv2. = 1002 ;0 ; XXDP V2 version code
; hb.tot = 16 ; ; total blocks
; hb.res = 20 ; ; reserved blocks
; hb.int = 22 ; ; interleave factor
; hb.boo = 24 ;0 ; boot block
hb.mon = 26 ;30 ; monitor block
; hb.ref = 30 ; ; MFD refreshed flag (not-0 = yes)
; hbbbs. = 30 ; block size
; Directory entry
; en.fil = 0 ;fil ; rad50 filename (0=>deleted)
; en.nam = 2 ;nam ;
; en.typ = 4 ;typ ;
; en.dat = 6 ; ; file date and contiguous flag
; en.ffb = 12 ; ; first-free byte
; en.sta = 14 ; ; start block
; en.len = 16 ; ; length in blocks
; en.lst = 20 ; ; last block in use
; en.flg = 22 ; ; flags
; enbbs = 24 ;18. ;
; en.dat - XXDP/DOSbatch date
; date = (year*1000.) + day-in-year;
;
; endat$ = 077777 ; date field mask
; enctg$ = 100000 ; contiguous file flag
.sbttl RL01/02 device structure (data)
; Registers
dlcsr. = 174400 ; csr
dl.csr = 0 ; csr
dl.buf = 2 ; 02 ; buffer
dl.adr = 4 ; track/sector
dl.wct = 6 ; word count (write)
dl.dat = 6 ; data value (read)
; Geometry
;
dlcyl. = 256. ; cylinders
dlrl2. = 2 ; RL02 cylinder factor
dlhds. = 2 ; heads
dlbpt. = 20. ; blocks per track
dltrk. = 64. ; track
dl1sz. = 10240. ; blocks per RL01
dl2sz. = 20480. ; blocks per RL02
dlsiz. = dl1sz. ;
; CSR definitions.
dlrdy$ = 1 ; operation complete ("drive ready")
dlfun$ = 7*2 ; function
dlgo$ = 200 ; clear to start operation
; actually "controller ready"
dluni$ = 1400 ; unit number (0..3)
dlun$m = 176377 ; unit mask
dlerr$ = 100000 ; error seen
dlNOP. = 0*2 ; 00 ; nop
dlSTA. = 2*2 ; 04 ; get status
dlSEE. = 3*2 ; 06 ; seek
dlRHD. = 4*2 ; 10 ; read header
dlREA. = 6*2 ; 14 ; read data
dlRDX. = 7*2 ; 16 ; read with no header check
; Seek
dlsee$ = 1 ;dl.adr ; seek activate
dldir$ = 4 ; seek direction
dlhea$ = 20 ; head select
dltrk$ = 177600 ;dl.dat ; track mask (RL02)
; Get device status/size
dlmrk$ = 1 ;dl.adr ; marker
dlsts$ = 2 ; get status
dlrst$ = 10 ; reset errors
dlrep$ = 13 ; get device size (rst,sts,mrk)
dlrl2$ = 200 ;dl.dat ; RL02
.sbttl boot engine (boot)
.asect
x$xlow: . = 0 ; 00000
; XXDP boot enters at location zero, like everyone else
; boot communication area
bo$pri: nop ;0000 ; boot primary entry point
br bo$con ;0002 ; continuation
.word .+2 ;0004 ; bus trap vector
.word 0 ;0006 ;
.word .+2 ;0010 ; cpu trap vector
.word 0 ;0012 ;
.word 0 ;0014 ; bpt vector skipped
.word 0 ;0016 ;
b$ocsr: .word dlcsr. ;0020 ; CSR address (patch point)(note)
bo$con: nop ;0022 ; boot continuation
br bo$eng ;0024 ; boot mainline
b$otrk: .word 0 ;0026 ; track - cylinder mask + initial sector
b$owct: .word 256. ;0030 ; word count
b$oblk: .word 0 ;0032 ; block
b$ocyl: .word 0 ;0034 ; cylinder number
b$osec: .byte 0 ;0036 ; sector: 0..39.
b$ohea: .byte 0 ;0037 ;
.word 0 ;0040 ;
.word 0 ;0042 ;
; BO$ENG - Boot engine and start
.enabl lsb
bo$eng: mov #40000,sp ; some random stack
mov b$ocsr,r1 ; r1 -> RL01 csr
mov #1000,b$obuf ; read buffer address
add #2,b$otrk ; sector needs to +2 for MFD and monitor
; MFD/monitor loop
10$: mov b$owct,-(sp) ; (sp) = remaining word count
; Block loop
20$: sub #256.,(sp) ; shave off 256. words
blos 30$ ; too much
mov #256.,b$otwc ; transfer a full block
br 40$ ;
30$: mov (sp),b$otwc ; less than a block - count is negative
add #256.,b$otwc ; add to get partial block word count
;
40$: call bo$see ; seek
call bo$adr ; setup address/wordcount/buffer
bic #dlfun$,(r1) ; clear the function
bis #dlREA.,(r1) ; set read function
call bo$opr ; go go and wait
br 60$ ; continue just below
; I/O error halt and retry
bo$hlt: halt ; stop the world
br bo$eng ; restart the world
; Continue boot
60$: tst (sp) ; read completed?
ble 70$ ; yes - MFD or monitor read done
call bo$nxt ; no - advance our cause
br 20$ ; and read the next block's worth
; MFD or monitor read done?
70$: tst (sp)+ ; pop temporary transfer word count
;
tst (pc)+ ; MFD or monitor read done?
80$: .word 0 ; 0=MFD, -1=Monitor
bne 90$ ; monitor read - finish up
com 80$ ; MFD - monitor next time
; MFD read done
;
; Setup for monitor read
b$omfd = 1002 ; 1000 - boot MFD buffer
b$omon = b$omfd+mf.mon ; 1026 - MFD monitor block
bowct. = 4096.-256. ; 7400 - monitor wordcount - boot block
mov @#b$omon,b$oblk ; monitor block from the MFD
mov #bowct.,b$owct ; monitor word count
add #1,b$oblk ; skipping the boot block
call bo$geo ; cylinder/sector/head geometry
call bo$cyl ; get the cylinder
mov #dlsee$,dl.adr(r1) ; seek flag
bis #dldir$,dl.adr(r1) ; we know its forward
bis b$otrk,dl.adr(r1) ; cylinder (and sector for MFD read)
br 10$ ; do the monitor read loop
; Monitor read done
;
; Setup monitor CSR/unit and launch init
90$: mov (r1),d$runi ; pass the unit number to the driver (boot)
bic #dlun$m,d$runi ; mask the unit
swab d$runi ; into low byte
mov r1,d$rcsr ; IOB csr
;
; Launch the init engine ;
;
jmp in$eng ; galacto city
.dsabl lsb
; BO$CYL - Cylinder calculation
bo$cyl: mov b$ocyl,-(sp)
mov #7,r3 ; shift count
10$: asl (sp) ; shift
dec r3 ;
bne 10$ ;
mov (sp)+,b$otrk ; cylinder
return
; BO$OPR - Boot operation
.enabl lsb
bo$opr: bic #dlgo$,(r1) ; clear to activate
bo$wai: bit #dlerr$!dlgo$,(r1) ; wazzup DL?
beq bo$wai ; we are waiting
bmi 30$ ; error
20$: return ; fine
30$: jmp bo$hlt ; fail - halt
; BO$CHK - Wait for seek to complete
bo$chk: bit #dlerr$!dlrdy$,(r1) ; ready/error
beq bo$chk ; neither
bpl 20$ ; fine - return
call bo$res ; bummer - reset (which calls bo$wai above)
br 30$ ; and go halt via 30$
.dsabl lsb
; BO$ADR - Combine all the addressing bits
bo$adr: mov b$otrk,-(sp) ; cylinder (and MFD sector)
bisb b$osec,(sp) ; sector
tstb b$ohea ;
beq 10$ ;
bis #100,(sp) ; head
10$: mov (sp)+,dl.adr(r1); combined track
mov b$otwc,-(sp) ; transfer word count
neg (sp) ;
mov (sp)+,dl.wct(r1); negated word count
mov b$obuf,dl.buf(r1); buffer address
return
b$obuf: .word 0 ; buffer address
b$otwc: .word 0 ; transfer word count
; BO$RES - Reset
;
; Called after an error and before a restart
bo$res: mov (r1),-(sp)
bic #dlun$m,(sp) ; clear all but unit
bis #dlSTA.,(sp) ; get status
bis #dlrep$,dl.adr(r1) ; get device status
mov (sp)+,(r1) ; take that CSR!
call bo$wai ; wait and check
return
; BO$NXT - Next block/track/sector/buffer address
bo$nxt: add #2,b$osec ; two sectors per block
cmpb b$osec,#40. ; end of track?
blt 10$ ; nope
clrb b$osec ; sector = 0
incb b$ohea ;
bicb #376,b$ohea ;
bne 10$ ;
add #200,b$otrk ;
inc b$ocyl ;
10$: add #^o1000,b$obuf ; next transfer buffer address
return
; BO$SEE - Seek
bo$see: bic #dlfun$,(r1) ; clear function
bis #dlRHD.,(r1) ; read header
call bo$opr ;
;
mov dl.wct(r1),-(sp); wct holds current track address
mov #dlsee$,dl.adr(r1) ; we will be seeking
tstb b$ohea ;
beq 10$ ;
bis #dlhea$,dl.adr(r1) ; set the head
10$: bic #177,(sp) ; determine cylinder
sub b$otrk,(sp) ; subtract what we want
bcc 20$ ; we are going forward
neg (sp) ; we are going backwardsd
bic #177,(sp) ;
bis #dldir$,dl.adr(r1) ; set negative direction
20$: bis (sp)+,dl.adr(r1); tell the RL01
bic #dlfun$,(r1) ; clear function
bis #dlSEE.,(r1) ; function = read data
bic #dlgo$,(r1) ; go
call bo$chk ; wait and check errors
return
; BO$GEO - Cylinder/sector/head geometry
bo$geo: clr b$ocyl ; clear proto cylinder
mov b$oblk,r3 ; r3 = target block
mov #40.,r2 ; r2 = sectors per cylinder
;
10$: sub r2,r3 ; get cylinder
bcs 20$ ; no more sectors here
inc b$ocyl ; up cylinder
br 10$ ;
20$: add r2,r3 ; backout the subtraction above
;
clr b$osec ;
mov #20.,r2 ; r2 = sectors per head
30$: sub r2,r3 ; see how many fit
bcs 40$ ; no more fit
incb b$ohea ; flip the head
br 30$ ;
40$: add r2,r3 ; backout subraction
asl r3 ; r2 * 2
movb r3,b$osec ; is the sector number
return
.blkw 7 ; boot round-up
.sbttl Init engine (low memory) (init)
.psect xxdp ;
x$xini: ; 01000
; Init prologue
i$n50h: .word 0 ;1000 ; 60/50 hertz clock (patch point)
i$naut: .word 0 ;1002 ; automated startup flag (patch point)
x$xgap: .blkb 2334
; IN$ENG - Initialization engine
;
; Stack, terminal and EMT vector
in$eng: mov #s$ystk,sp ; stack
mov #TPS,s$ytps ; tps
mov #TPB,s$ytpb ; tpb
;
mov #em$eng,@#v$eemt; low memory em$eng (note)
mov #340,@#v$eemt+2 ; (is never invoked)
; Size memory
mov #20$,@#4 ; trap to 20$
mov #340,@#6 ;
mov #4000,r1 ; 1kw counter
mov #4,r3 ; kw accumulator
mov #20000,r0 ; start address
;
10$: mov #0,(r0) ; this test is repeated at in$siz
call in$siz ; count 1kw
inc r3 ; kw counter up
add r1,r0 ; advance address
cmp r0,#160000 ; end of universe?
blo 10$ ; not quite
br 30$ ; yep
; Sizer trap
;
; r0 -> memory top - typically 160000
20$: add #4,sp ; dump SetAbt pc/ps stack frame
;
;memory image
30$: mov r0,s$yrel ;160000 20000
sub #20000,s$yrel ;140000 00000 relocation constant
mov r0,s$ytra ;
sub #10000,s$ytra ;150000 10000 transient area
mov r0,s$yper ;
sub #6000,s$yper ;152000 12000 permanent area
; Checksum the transient .5k area
mov #x$xtra,r2 ;10000 ; from 10000 to 12000
40$: add (r2)+,s$y5ck ; ; aka s$ytra to s$yper
cmp r2,#x$xper ;12000 ; done?
bne 40$ ; not bloodly likely
;
mov r0,s$ysup ;01000 ; supervisor load address
sub #37000,s$ysup ; ;
; Calculate MMU page count
mov r3,s$ykwd ;#28. ; memory kiloword size
mov r3,r2 ; ; calculate number of MMU pages
.rept 5 ; there are 32 per kiloword
asl r2 ; ; 2^5 is 32
.endr ; ;
dec r2 ; ; (n*32)-1 (to make it tangible)
mov r2,s$ypgs ;511. ; 32w pages in system - 1
; Copy the kword digits for later display
asl r3 ; ; kwords * 2
movb i$nkws(r3),i$nkwd ; first
movb i$nkws+1(r3),i$nkwd+1 ; second
br in$con ; skip to init continuation
; Test 1kw of memory at a time
in$siz: mov r0,r2 ; address
10$: mov #0,(r2)+ ; test location with write
bit #3777,r2 ; until we wrap
bne 10$ ;
return ; one kw more
; Process the monitor relocation list
;
; We relocate the low memory copy of the monitor just before
; copying the monitor to high memory.
in$con: mov s$yrel,r3 ; r3 = relocation constant
mov #i$nrel,r2 ; r2 -> relocation list
10$: tst (r2) ; end of table?
bmi 20$ ; yup
add r3,@(r2)+ ; relocate another brother
br 10$ ; more
; Copy up monitor and jump to high copy
20$: mov #20000,r1 ; top of low memory monitor
mov r0,s$ytop ; top of memory
30$: mov -(r1),-(r0) ; copy monitor up
cmp r1,#in$hgh ;
bhi 30$ ;
jmp (r0) ; ransfer to x$xhgh:
; Relocation list
;
; For a binary exact restoration of XXDP+ we need to follow the
; random order of entries in the table below.
;
; Each entry is created by a "movr src,dst,idx" macro, where "idx"
; is the table index (which can be elided for for a non-exact clone).
.MACRO MOVR SRC,DST,IDX
i$nr'idx' = .+2
mov src,dst
.ENDM
i$nrel: .word i$nr1 ; 1
.word i$nr2 ; 2
.word i$nr3 ; 3
.word i$nr4 ; 4
.word i$nr5 ; 5
.word i$nr6 ; 6
.word i$nr7 ; 7
.word i$nr8 ; 8
.word i$nr9 ; 9
.word i$nr10 ; 10
.word i$nr11 ; 11
.word i$nr12 ; 12
.word i$nr13 ; 13
.word i$nr14 ; 14
.word -1 ; stopper
i$nkws: .ascii " 0 1 2 3 4 5 6 7 8 9" ; memory size table
.ascii "10111213141516171819"
.ascii "202122232425262728"
i$nkwd: .ascii " K " ;"28K " ; memory size filled in
.byte 0,0 ; disassembly (note)
; .byte 0,12 ;10. ; XXDP+ live (savm?) (slip?) (note)
.even
.sbttl Init engine (high memory) (init)
; Beginning of high area
in$hgh: mov #s$ystk,sp ; use the (unrelocated) system stack
mov pc,r0 ;
add #in$hgh-.,r0 ; abort restarts us
SetAbt ;in$hgh ; (EMT vector-> low memory EM$ENG)(note)
clr r2 ; 0:1000 trap catchers
mov #2,r3 ;
10$: mov r3,(r2)+ ; 000000: .word .+2 ; trap to @#2
clr (r2)+ ; 000002: .word 0 ; aka HALT
add #4,r3 ; and so on
cmp r2,#1000 ; upto 1000
bne 10$ ;
call em$rst ; relocate EMT vector
call in$iob ; relocate the IOB
;
call @dr.dev(r5) ; get ye device name "DD"
mov r0,s$ydev ; s$ydev -> d$rdev: .ascii "DDu"<med>
movb d$runi,s$yuni ; s$yuni
mov d$rcsr,s$ycsr ; s$ycsr
;
movr #c$lbuf,c$llin,12; c$olin - relocated
mov #clavl.,c$llen ; line available length
;
mov @#i$naut,c$laut ; copy automated startup flag
;
mov pc,r0 ;
add #50$-.,r0 ;
SetAbt ;50$ ; abort skips messages
TerMod ;
NewLin ; new line even in quiet mode
;
tst @#i$naut ; quiet mode?
bne 50$ ; yes
;
movr #i$mmon,r0,1 ;
TypMsg ; CHMDLD0 XXDP+ DL MONITOR"
mov #i$mboo,r0 ;
TypMon ; BOOTED VIA UNIT
movb d$runi,r0 ;
bic #^c7,r0 ; isolate unit number
add #'0,r0 ; make it readable
PutChk ;
NewLin ;
mov #i$nkwd,r0 ; "28K" (#i$nkwd is unrelocated)
TypMsg ; (should be TypMon) (bug)(note)
50$: mov pc,-(sp) ;
add #80$-.,(sp) ; cpu traps to 80$
mov (sp)+,@#10 ;
mov #340,@#12 ;
;
mov pc,-(sp) ;
add #60$-.,(sp) ;
mov (sp)+,@#4 ; bus traps to 60$
mov #340,@#6 ;
;
mov #340,@#PSW ; check psw (trap to 60$)
mfpt ; get processor type (trap to 80$)
cmp #3,r0 ; F11: qbus 11/23, unibus 11/24
bne 90$ ; not F11
NewLin ; F11 can be unibus or qbus
mov #i$mubq,r0 ; unibus question
TypMon ; DOES THIS SYSTEM HAVE A UNIBUS (Y/N CR=Y)
GetLin ; get response
ParFld ; parse it
nop ; ignore errors
cmpb (r0),#'N ; only recognized response is "N"
beq 70$ ; not a unibus system
br 90$ ; anything else
60$: cmp (sp)+,(sp)+ ; PSW bus trap - not unibus
70$: bis #syNUB$,s$ycfg ; no unibus
;
tst @#i$naut ; quiet?
bne 100$ ; yes
mov #i$mnon,r0 ;
TypMon ; "NON"
br 90$ ; then "UNIBUS"
80$: cmp (sp)+,(sp)+ ; MFPT cpu trap
90$: tst @#i$naut ; quiet?
bne 100$ ; yes
mov #i$mubs,r0 ;
TypMon ; "UNIBUS SYSTEM"
;
100$: tst @#i$n50h ; 50 hertz time zone?
beq 110$ ; no
mov #50.,s$yltk ; setup LTC line clock tick counters
mov #50.,s$yktk ; setup KWP programmable clock counters
bis #sy50H$,s$ycfg ; flag 50hz present
110$: mov pc,r0 ;
add #105$-.,r0 ; abort address
SetAbt ;105$ ; abort repeats test
105$: tst @#i$naut ; boot auto mode?
bne in$hdw ; yes - skip date prompt and idents
; Get the date
call in$dat ; get the date
movr #in$hdw,r0,10 ; relocated
SetAbt ; abort skips messages
mov #i$mrad,r0 ;
TypMon ; "RESTART ADDR: "
movr #xx$rst,r0,3 ; XXDP system restart address
mov c$llin,r1 ; a buffer
OctAsc ; ascify it
clrb (r1) ; terminate string
mov c$llin,r0 ; get the buffer again
TypMsg ; display restart address
;
20$: fall in$hdw ; get hardware configuration
; Hardware, Config, System launch
;
; KW11P, line clock, line printer
in$hdw: mov #10$,@#4 ; trap to 10$
add s$yrel,@#4 ;
tst @#KWP ; KW11P
mov h$wkwp,s$ykwp ;
bis #syKWP$,s$ycfg ; KWP$ flag
;
10$: mov #20$,@#4 ; trap to 20$
add s$yrel,@#4 ;
tst @#LTC ; line clock
mov h$wltc,s$yltc ;
bis #syLTC$,s$ycfg ; LTC$ flag
;
20$: mov #30$,@#4 ; trap to 30$
add s$yrel,@#4 ;
tst @#LPT ; test line printer
bis #syLPT$,s$ycfg ; LPT$ flag
mov #LPT,s$ylpt ; line printer
30$: fall in$fin
in$fin: tst @#i$naut ; automated?
bne 10$ ; yes
mov pc,r0 ;
add #10$-.,r0 ;
SetAbt ;10$ ; abort skips message
NewLin ;
mov #i$mxdp,r0 ; THIS IS XXDP+ ...
TypMon ;
; Reset s$ypad because it had preset boot-time info (note)
10$: movb #1,s$ypad ; reset line padding
; Fill in missing trap catchers between 0..20
mov #20,r0 ; r0 -> top of the area
mov #16,r1 ; r1 -> a word below
20$: clr -(r0) ; 016: .word 0
mov r1,-(r0) ; 014: .word 16 ...
sub #4,r1 ; 002: .word 0
bgt 20$ ; 000: .word 2
;
; Launch XXDP monitor ;
;
jmp xx$rst ; system start and restart
.sbttl Init date, messages, relocation (init)
; IN$DAT - Date input
in$dat: mov #i$ment,r0 ; ENTER DATE..
TypMon ;
call in$ymd ; parse year, month, day
br 10$ ; failed
return ; fine
10$: mov #i$mdat,r0 ; INVALID DATE
TypMon ;
br in$dat ; try, try again
; I$M... - Init messages
i$mrad: .asciz <cr><lf>"RESTART ADDR: "
i$mboo: .asciz <cr><lf>"BOOTED VIA UNIT "
i$ment: .asciz <cr><lf>"ENTER DATE (DD-MMM-YY): "
i$mdat: .asciz "? INVALID DATE"
i$mnon: .asciz "NON-"
i$mubs: .asciz "UNIBUS SYSTEM"<cr><lf>
i$mubq: .asciz "DOES THIS SYSTEM HAVE A UNIBUS? (Y/N CR=Y) "
i$mxdp: .ascii |THIS IS XXDP+. TYPE "H" OR "H/L" FOR HELP.|<cr><lf>
.even
; HMDLD0 HMDLD0