Notes: M9301 Unibus Bootstrap and Terminator

Note: Since I originially investigated the M9301, I fould it would be quite useful to build an adapter to allow the use of M9312 boot ROMs with the M9301. You can find information on the Boot ROM Adapter here.

This M9301-YA has 4 PROMs with the numbers 034A9, 035A9, 036A9, and 037A9.

The 10 position dipswitch is set to 1101101110 with 1 meaning closed and 0 meaning open with open meaning the side nearest the edge fingers pressed down. Reading the M9301-YA documentation, this means boot the RK11 without diagnostics.

The instructions taped to the front of the machine say to load address 173100 and then press start. This results with a $ on the console terminal and from there you can boot a device or use a very simple emulated console. There is a great description in the M9301 Users Manual.

There are some situations that hang the front panel and do not respond to anything but a power cycle. I think this is because the DK11 boot does not work without a drive and the DK11 controller hangs the Unibus.

Command Controller Description Typical Device
DK RK11 Disk Cartridge RK05
DP RP11 Disk Pack RP02, RP03
DT TC11 DECtape TU55, TU56
MT TM11 800 bpi Magtape
CT TA11 Magnetic Cassette
DX RX11 Diskette RX01
TT DL11 ASR-33 Teletype
PR PC11 Paper Tape PC05

I set all the switches so that the machine drops into the emulated console on power up. I have not wired in a boot switch, although I am thinking that would be useful. I am not sure where to put the switch. The 11/40 does not have a boot switch on the front panel.

TT Bootstrap

The TT bootstrap is equivalent to the toggle-in bootstrap loader (DEC-11-L1PA-LA) as described in the PDP-11/40 System Manual.

Bootstrap Procedure

  1. Set TTY to LINE.
  2. Turn power switch to POWER
  3. Boot ROM should print out 4 16-bit octal values and then a $ prompt.
  4. Set reader switch to stop.
  5. Type TT and return.
  6. Position Absolute Loader paper tape in reader so that 351 leader punches are in reader. This is important because any other leader will not work with bootstap loader.
  7. Set reader switch to start.
  8. Reader should begin and read in tape.
  9. CPU should halt at end of tape with 157500 (for a 28KW machine) in the address display.
At this point, the absolute loader is resident in memory and a program or diagnostic tape can be loaded.
  1. Set reader switch to stop.
  2. Load 157500 (for a 28KW machine).
  3. Position program paper tape in reader so that leader punches are in reader.
  4. Set reader switch to start.
  5. Depress START switch.
  6. Reader should begine and read in tape.
  7. CPU should halt with the lower half of the data register all zeros to indicate a good checksum. Anything else in the lower half indicates a checksum error.
At this poinrt, the program is resident in memory. Load the start address and press start to begin program execution.

Using a KL11 as a PC11

The bootstrap for the KL11 (TT) and for the PC11 (PR) are identical except for the device CSR. The ABSOLUTE LOADER is also the same and gets its CSR address from the contents of the highest address in memory (157776 for a 28KW machine). So, it is possible to put a KL11 attached to an ASR33 at the PC11 CSR address and get the paper tape reader functionality for loading paper tapes. I have not verified that this works for any OS, but it works fine for bootstrapping.

ROM Dump and Partial Disassembly

This was created by using the console emulator to examine the ROM contents and then capturing that with a terminal emulator program. The results were hand disassembled. Athough incomplete the results were useful in determining how the RX01 and the TTY paper tape reader bootstraps functioned.
			; Dump of M9301-YA boot roms
			; 23-034A9, 23-035A9, 23-036A9, and 23-037A9


$L 165000
$E
$E 165000 005001
$E 165002 005201
$E 165004 005101
$E 165006 006201
$E 165010 006301
$E 165012 006001
$E 165014 005701
$E 165016 005401
$E 165020 005301
$E 165022 005601
$E 165024 006101
$E 165026 005501
$E 165030 000301
$E 165032 001377
$E 165034 012702
$E 165036 165112
$E 165040 011201
$E 165042 022201
$E 165044 001377
$E 165046 063201
$E 165050 165201
$E 165052 044201
$E 165054 056201
$E 165056 000004
$E 165060 037201
$E 165062 000006
$E 165064 001777
$E 165066 012701
$E 165070 165074
$E 165072 000111
$E 165074 000121
$E 165076 012701
$E 165100 165106
$E 165102 000131
$E 165104 000111
$E 165106 165104
$E 165110 000412
$E 165112 165112
$E 165114 165122
$E 165116 177777
$E 165120 165116
$E 165122 000001
$E 165124 100000
$E 165126 177777
$E 165130 177777
$E 165132 177777
$E 165134 177777
$E 165136 105767
$E 165140 177762
$E 165142 001377
$E 165144 012702
$E 165146 165124
$E 165150 105722
$E 165152 001377
$E 165154 105712
$E 165156 100377
$E 165160 012703
$E 165162 165130
$E 165164 012702
$E 165166 165132
$E 165170 021322
$E 165172 001377
$E 165174 034342
$E 165176 001777
$E 165200 016701
$E 165202 005620
$E 165204 042701
$E 165206 177001
$E 165210 001002
$E 165212 000167
$E 165214 005612
$E 165216 005000
$E 165220 032701
$E 165222 000774
$E 165224 001003
$E 165226 012706
$E 165230 000024
$E 165232 000002
   ; entry point
$E 165234 012705
$E 165236 165320
$E 165240 012702
$E 165242 000500
$E 165244 011503
$E 165246 005012
$E 165250 112512
$E 165252 005202
$E 165254 112512
$E 165256 005302
$E 165260 023512
$E 165262 001015
$E 165264 005202
$E 165266 143522
$E 165270 024542
$E 165272 143522
$E 165274 001010
$E 165276 011502
$E 165300 016505
$E 165302 177772
$E 165304 110532
$E 165306 150572
$E 165310 000000
$E 165312 020352
$E 165314 001407
$E 165316 000000
$E 165320 177777
$E 165322 165320
$E 165324 165130
$E 165326 165330
$E 165330 000500
$E 165332 000501
$E 165334 012701
$E 165336 165356
$E 165340 011206
$E 165342 005726
$E 165344 004311
$E 165346 000000
$E 165350 004361
$E 165352 000004
$E 165354 000406
$E 165356 005723
$E 165360 001372
$E 165362 021605
$E 165364 001370
$E 165366 000203
$E 165370 000000
$E 165372 005006
$E 165374 012705
$E 165376 017776
$E 165400 005003
$E 165402 010701
$E 165404 000430
$E 165406 012705
$E 165410 160000
$E 165412 012702
$E 165414 000006
$E 165416 012712
$E 165420 000340
$E 165422 010742
$E 165424 012706
$E 165426 000502
$E 165430 005745
$E 165432 012712
$E 165434 173030
$E 165436 010701
$E 165440 000412
$E 165442 016702
$E 165444 005356
$E 165446 032702
$E 165450 000770
$E 165452 001402
$E 165454 022222
$E 165456 000401
$E 165460 010402
$E 165462 000167
$E 165464 005734
$E 165466 010602
$E 165470 010322
$E 165472 020205
$E 165474 101775
$E 165476 005103
$E 165500 020342
$E 165502 001411
$E 165504 010312
$E 165506 020312
$E 165510 001006
$E 165512 020206
$E 165514 101371
$E 165516 005703
$E 165520 001362
$E 165522 000167
$E 165524 005556
$E 165526 010300
$E 165530 011204
$E 165532 010206
$E 165534 000000
			; TA11 boot (?)
$E 165536 000304
$E 165540 010411
$E 165542 012705
$E 165544 165624
$E 165546 012704
$E 165550 000375
$E 165552 112503
$E 165554 112511
$E 165556 100407
$E 165560 130311
$E 165562 001776
$E 165564 105204
$E 165566 100772
$E 165570 116114
$E 165572 000002
$E 165574 000771
$E 165576 005711
$E 165600 100407
$E 165602 010103
			; entry point
$E 165604 122737 	CMPB 	#000240,(000000) ; check for 240 magic number
$E 165606 000240
$E 165610 000000
$E 165612 001002 	BNE 	165620
$E 165614 010300 	MOV 	R3,R0		; drive number
$E 165616 005007 	CLR 	R7   		; jump to 0
			; entry point
			; return to console emulator
$E 165620 000167 	JMP 	005552(R7)  	; 173374 (or 173372?)
$E 165622 005552
$E 165624 017640
$E 165626 002415
$E 165630 112024
			; entry point -- RX11 boot
			; R1 == CSR
			; R0 == drive number
$E 165632 012704	MOV 	#123667,R4	; status masks 247 (10100111), 167 (01101111)
						;                   10100111        10110111
$E 165634 123667
$E 165636 010003 	MOV 	R0,R3  		; save drive number
$E 165640 131700 	BITB 	(R7),R0		; AND 001
$E 165642 001001 	BNE 	165646		; go if not drive 0
$E 165644 000304 	SWAB 	R4		; swap mask bytes
						; RESET inits RX01 and clears the status
$E 165646 105711 	TSTB 	(R1)		; read RXCS 
$E 165650 001776 	BEQ 	165646		; loop until TR or DONE is set
$E 165652 012705 	MOV 	#000003,R5	; load R5 as pass counter
						; first pass issue read sector command
						; second pass load RXDB with sector number
						; third pass load RXDB with track number
						; forth pass, R5 == C == 0, issue empty buffer command
$E 165654 000003	
$E 165656 000261 	SEC			; set C for first pass flag
   			; entry point
$E 165660 010411 	MOV 	R4,(R1)		; issue a command to the drive
						; pass 1
						; CSR writable bits 0100000001011111
						;        drive 0 -> 1011011110100111
						;		    0000000000000111
						;			FUNC=READ SECTOR, GO, DRIVE 0
						;	 drive 1 -> 1010011110110111
						;                   0000000000010111
						;			FUNC=READ SECTOR, GO, DRIVE 1
$E 165662 141704 	BICB 	(R7),R4		; clear bits in R4 command/mask
						;	            0011001001000100
						;  setup for fourth pass
						;        drive 0 -> 1000010110100011
						;			FUNC=EMPTY BUFFER, GO, DRIVE 0
						;	 drive 1 -> 1000010110110011
						;			FUNC=EMPTY BUFFER, GO, DRIVE 1
   			; entry point
$E 165664 031104 	BIT 	(R1),R4		; read status of the drive and mask it
						; CSR readable bits 1000000011100000
						;        drive 0 -> 1000010110100011
						;	 drive 1 -> 1000010110110011
						;		    1000000010100000
						;		ERROR, TR, DONE
$E 165666 001776 	BEQ 	165664		; no error, not done and no transfer request, loop
$E 165670 100753 	BMI 	165620  	; ERROR bit is set, go
$E 165672 103405 	BLO 	165706		; C = 1, still working on sector read command, go
$E 165674 131104 	BITB 	(R1),R4		; AND CSR with TR, DONE mask
$E 165676 100342 	BPL 	165604  	; TR = 0, DONE = 1, done with buffer empty, go 
$E 165700 116125 	MOVB 	2(R1),(R5)+	; transfer sector data to low memory
$E 165702 000002
$E 165704 000767 	BR 	165664
   			; entry point
$E 165706 006205 	ASR 	R5		; lsb into C
$E 165710 103363 	BHIS 	165660		; C = 0, go and R5 is now zero
$E 165712 112761 	MOVB 	#000001,2(R1)	; write 1 to RXDB for sector and track
$E 165714 000001
$E 165716 000002
$E 165720 000761 	BR 	165664
$E 165722 020040
$E 165724 020040
$E 165726 032063
$E 165730 030411
$E 165732 031467
$E 165734 033462
$E 165736 004466
$E 165740 030060
$E 165742 030065
$E 165744 030460
$E 165746 004411
$E 165750 004411
$E 165752 046103
$E 165754 004522
$E 165756 030522
$E 165760 004411
$E 165762 044473
$E 165764 042116
$E 165766 054105
$E 165770 052040
$E 165772 020117
$E 165774 040524
$E 165776 046102
$E 166000

$L 173000
   ; entry point -- CPU Diagnostics w/ console emulator
   ;  DIP switches xx11111111  (173000)
$E 173000 000574 BR 173372
   ; entry point -- CPU Diagnostics w/ console emulator
      ;  DIP switches xx11111110  (173002)
$E 173002 000573 BR 173372
   ; entry point
$E 173004 010701 MOV R7,R1  ; PC -> R1
$E 173006 000467 BR 173166
$E 173010 010015
$E 173012 000421
$E 173014 010701
$E 173016 000463
$E 173020 010005
$E 173022 000414
$E 173024 173000
$E 173026 000340
   ; entry point -- Console Emulator
   ;  DIP switches xx11110011  (173030)
$E 173030 010701 MOV R7,R1
$E 173032 000516 BR 173372 
$E 173034 000240
$E 173036 000525
$E 173040 010400
$E 173042 000523
$E 173044 010600
$E 173046 000521
$E 173050 010500
$E 173052 000517
   ; entry point
$E 173054 005004 CLR R4
$E 173056 012700 MOV #173726,R0
$E 173060 173726
$E 173062 112002 MOVB (R0)+,R2
$E 173064 010703 MOV R7,R3  ; print R2
$E 173066 000466 BR 173244
$E 173070 001374 BNE 173062
$E 173072 010703 MOV R7,R3  ; get a character into R2
$E 173074 000455 BR 173230
$E 173076 000302 SWAB R2
$E 173100 001774 BEQ 173072  ; current low byte of R2 == 0 ?
$E 173102 005001 CLR R1
$E 173104 020220 CMP R2,(R0)+
$E 173106 001404 BEQ 173120
$E 173110 005201 INC R1
$E 173112 005710 TST (R0)
$E 173114 001373 BNE 173104
$E 173116 000757 BR 173056
$E 173120 012702 MOV #175400,R2
$E 173122 175400
$E 173124 156102 BISB 173764(R1),R2
$E 173126 173764
$E 173130 006302 ASL R2
$E 173132 020204 CMP R2,R4
$E 173134 001001 BNE 173140
$E 173136 005725 TST (R5)+
$E 173140 010204 MOV R2,R4
$E 173142 020127 CMP R1,#000010
$E 173144 000010
$E 173146 103133 BGT 173436
$E 173150 010701 MOV R7,R1
$E 173152 000405 BR 173166
$E 173154 105737 TSTB (173024)
$E 173156 173024
$E 173160 001115 BNE 173414
$E 173162 000137 JMP 165234
$E 173164 165234
   ; entry point
$E 173166 005000 CLR R0
$E 173170 005002 CLR R2
$E 173172 010703 MOV R7,R3  ; return link
$E 173174 000415 BR 173230  ; get a character with echo

$E 173176 120227 CMPB R2,#000015 ; check for CR
$E 173200 000015
$E 173202 001440 BEQ 173304
$E 173204 162702 SUBB #000070,R2
$E 173206 000070
$E 173210 062702 ADD #000010,R2 ; ascii '0' is zero
$E 173212 000010
$E 173214 103317 BHIS 173054  ; looking for octal digits, but find something else (?)
   ; this looks like it is accumulating octal digits from the keyboard
   ; into R0 until either a CR or a non-octal character
$E 173216 006300 ASL R0  ; R0 << 3
$E 173220 006300 ASL R0
$E 173222 006300 ASL R0
$E 173224 050200 BIS R2,R0  ; OR of R2 and R0
$E 173226 000760 BR 173170
   ; entry point
   ;  get a character and echo, return via R3
$E 173230 105737 TSTB (177560) ; console CSR
$E 173232 177560
$E 173234 100375 BPL 173230  ; loop until character available
$E 173236 105002 CLRB R2
$E 173240 153702 BISB (177562),R2 ; load data character into R2
$E 173242 177562
   ; entry point 
   ;  type a character and return via R3
$E 173244 105737 TSTB (177564) 
$E 173246 177564
$E 173250 100375 BPL 173244  ; loop until transmit buffer empty
$E 173252 110237 MOVB R2,(177566) ; echo the received character
$E 173254 177566
$E 173256 022323 CMP (R3)+,(R3)+ ; increment R3 by 4 (?)
$E 173260 142702 BICB #000200,R2 ; clear bit 7 of input character
$E 173262 000200
$E 173264 000163 JMP -2(R3)
$E 173266 177776

$E 173270 012702 MOV #005015,R2
$E 173272 005015
   ; RX01 boot
$E 173274 010703 MOV R7,R3  ; save PC
$E 173276 000762 BR 173106
$E 173300 000302
$E 173302 000760
   ; entry point
$E 173304 022121 CMP (R1)+,(R1)+ ; increment R1 by 4
$E 173306 000161 JMP -2(R1)
$E 173310 177776

$E 173312 012702
$E 173314 000030
$E 173316 000261
$E 173320 006100
$E 173322 106102
$E 173324 010703
$E 173326 000746
$E 173330 012702
$E 173332 020206
$E 173334 006300
$E 173336 001403
$E 173340 106102
$E 173342 103774
$E 173344 000765
$E 173346 105002
$E 173350 000751
$E 173352 000005
$E 173354 000115
$E 173356 010500
$E 173360 010701
$E 173362 000753
$E 173364 011500
$E 173366 000751
$E 173370 000632
   ; entry point - console emulator (?)
$E 173372 000137 JMP 165000
$E 173374 165000
$E 173376 005316
$E 173400 001014
$E 173402 000000
   ; entry point
$E 173404 005000 CLR R0
$E 173406 013704 MOV (173024),R4 ; boot address from switches
$E 173410 173024
$E 173412 005724 TST (R4)+  ; increment R4 by 2
   ;entry point
$E 173414 010402 MOV R4,R2
$E 173416 012705 MOV #017776,R5 ; top of 4KW memory
$E 173420 017776
$E 173422 012201 MOV (R2)+,R1 ; device address
$E 173424 010506 MOV R5,R6  ; set stack pointer to top of 4KW memory
$E 173426 012716 MOV #004012,(R6)
$E 173430 004012
$E 173432 000005	RESET			; BUS Reset
$E 173434 010004	MOV R0,R4		; drive number (?)
			; entry point
$E 173436 000112	JMP (R2)
			; entry point -- RK11 Diagnostic Boot
			;  DIP switches xx01101111  (173440)
$E 173440 000754	BR 173372
			; entry point -- RK11 Boot
			;  DIP switches xx01101110  (173442)
$E 173442 000760	BR 173404
$E 173444 177404
$E 173446 052704
$E 173450 000010
$E 173452 006304
$E 173454 103376
$E 173456 010461
$E 173460 000006
$E 173462 005004
$E 173464 000405
$E 173466 000741
$E 173470 000745
$E 173472 176714
$E 173474 000304
$E 173476 010411
$E 173500 062704
$E 173502 000005
$E 173504 000435
$E 173506 000731
$E 173510 000735
$E 173512 177342
$E 173514 000412
$E 173516 004011
$E 173520 174002
$E 173522 100000
   ; TM11
$E 173524 000722
$E 173526 000726
$E 173530 172522	;  TM11 CSR (?)
$E 173532 000403
$E 173534 060017
$E 173536 177772
$E 173540 000200
$E 173542 010203
$E 173544 005723
$E 173546 000304
$E 173550 062304
$E 173552 010421
$E 173554 005311
$E 173556 062704
$E 173560 177772
$E 173562 010441
$E 173564 062304
$E 173566 031311
$E 173570 001776
$E 173572 122341
$E 173574 122321
$E 173576 001277
$E 173600 012761
$E 173602 177000
$E 173604 000002
$E 173606 010411
$E 173610 105711
$E 173612 100376
$E 173614 005711
$E 173616 100667
$E 173620 105011
$E 173622 005007
   ; TA11
$E 173624 000662
$E 173626 000666
$E 173630 177500	;  TA11 CSR (?)
$E 173632 000137	JMP 165536
$E 173634 165536
			; entry point -- RX11 Diagnostic Boot
			;  DIP switches xx00110000  (173636)
$E 173636 000655	BR	173372
			; entry point -- RX11 Boot
			;  DIP switches xx00110000  (173640)
$E 173640 000661	BR	173404
$E 173642 177170	; RX11 CSR address
$E 173644 000137	JMP	165632
$E 173646 165632
			; DL11
$E 173650 000650
$E 173652 000654
$E 173654 177560	;  DL11 CSR address
$E 173656 000403	BR	173666
			; PC11
$E 173660 000644
$E 173662 000650
$E 173664 177550	;  PC11 CSR address
			; entry point PC11, DL11
$E 173666 010115	MOV	R1,(R5)			; top of memory xxx776
$E 173670 042705	BIC	#000024,R5		; xxx752
$E 173672 000024
$E 173674 010515	MOV	R5,(R5)
			; loop entry
$E 173676 011503	MOV	(R5),R3
$E 173700 005211	INC	(R1)			; set ready run flag
$E 173702 105711	TSTB	(R1)			; check char ready bit
$E 173704 100376	BPL	173702			; no char yet, go
$E 173706 116113	MOVB	2(R1),(R3)		; get char and store
$E 173710 000002
$E 173712 005215	INC	(R5)
$E 173714 120327	CMPB	R3,#000375
$E 173716 000375
$E 173720 001366	BNE	173676
$E 173722 105223	INCB	(R3)+
$E 173724 000143	JMP	-(R3)
			; table
$E 173726 005015	; line feed, charage return
$E 173730 000044	; NULL, $
$E 173732 052124	; T, T  TT teletype reader
$E 173734 045504	; K, D  DK RK11
$E 173736 052104	; T, D  DT DECtape
$E 173740 052115	; T, M  MT magtape
$E 173742 050104	; P, D  DP RP02/03
$E 173744 052103	; T, C  CT cassette tape
$E 173746 051120	; R, P  PR paper tape
$E 173750 054104	; X, D  DX diskette
$E 173752 006523	; CR, S  start
$E 173754 020105	; SP, E  examine
$E 173756 020104	; SP, D  deposit
$E 173760 020114	; SP, L  load address
$E 173762 000000	;  end of table (?)
			; table of boot strap addresses
			; 173000 + x*2 == device CSR, next address is boot start
$E 173764 111326	; DK, TT
$E 173766 126245	; MT, DT
$E 173770 146235	; CT, DP
$E 173772 150732	; DX, PR
$E 173774 073565	; examine, start
$E 173776 003002	; load, deposit
$E 174000


; toggle-in bootstrap from PDP-11/40 System Manual
;  DEC-11-L1PA-LA

   xx7744 016701	MOV	000026(R7),R1		; xx7776
   xx7746 000026	
   xx7750 012702	MOV	#000352,R2
   xx7752 000352					; load address index
   xx7754 005211	INC	(R1)			; set reader run flag
   xx7756 105711	TSTB	(R1)			; test char available bit
   xx7760 100376	BPL	xx7756			; loop if no char
   xx7762 116162	MOVB	2(R1),xx7400(R2)	; get buffer char and store
   xx7764 000002
   xx7766 xx7400					
   xx7770 005267	INC	177756(R7)		; xx7752
   xx7772 177756
   xx7774 000765	BR	xx7750
   xx7776 yyyyyy					; device address 1777560