	.title	M9312 'DU' BOOT prom for MSCP compatible controller
; This source code is a mdified copy of the DEC M9312 23-767A9 boot PROM.
;
; This boot PROM is for any MSCP compatible controller 
; (DEC UDA50, EMULEX UC17/UC18)
;
; Multiple units and/or CSR addresses are supported via different entry points.
;
; Revision history:
; August 2024: Mark Matlock - add ability to boot secondary controller
; April 2022: Mark Matlock - add retrys to boot 11/83 more consistently
; On 11/83 & 11/73 two digit LED display will show retries needed
; Remove LEDCSR writes if used on other systems
;
; May 2017: Joerg Hoppe
; 198?:  DEC
;      Original ROM 23-767A9 for M9312.
;
       
	mscsr	=172150 		; std MSCP csrbase
	mscsr2	=172154			; sec MSCP csrbase
	msip	=+0			; IP register
	mssa	=+2			; SA register
	ledcsr = 177524
       
       	.asect
       	; ---- Simple boot drive 0 from 0
       	. = 0
       	jmp	@#start0
       
       	; ---- Reboot drive 0 on power event
       	. = 24				; Power ON/OFF
       	.word	     start0		; PC
       	.word	     340		; PSW priority level 7
       
       
       	; ----- Main boot addresses
       	.=10000 			;  arbitrary position > 3000
       
       
       rpkt	=1004	; rpkt structure
       cpkt	=1070	; cpkt structure
       comm	=1200	; comm structure
       ;comm	 =2404	 ; comm structure (at 'blt .+12')
       
       	; register usage:
       	; r0: unit number 0..3
       	; r1: MSCP csrbase
       	; r2: moving buffer pointer
       	; r3: moving buffer pointer
	; r4: counter for retries
       	; r5: init mask
       
       	; 4 unit numbers => 4 entry addresses
start0:
       	mov	#0,r0
       	br	csrA
       	nop
start1:
       	mov	#1,r0
       	br	csrA
       	nop
start2:
       	mov	#2,r0
       	br	csrA
       	nop
start3:
       	mov	#3,r0
       	br	csrA
       	nop
       
start4:
       	mov	#0,r0
       	br	csrB
       	nop
start5:
       	mov	#1,r0
       	br	csrB
       	nop
start6:
       	mov	#2,r0
       	br	csrB
       	nop
start7:
       	mov	#3,r0
       	br	csrB
       	nop
       
csrA:	mov	#mscsr,r1		; boot std csr, unit <R0>
	mov	r1,@#csrpt		; save csr selection
	br	duNr
csrB:	mov	#mscsr2,r1		; boot sec csr, unit <R0>
	mov	r1,@#csrpt		; save csr selection

       	; retry entry
duNr:	dec	@#lpcnt			; MGM lpcnt = 177777 @ start
	mov	@#lpcnt,R4		; MGM dec lpcnt to advance LEDs
;	mov     R4,@#ledcsr		; MGM Comment this if no LEDCSR exists
	mov	#10000,r4		; MGM loop 10000 times then retry
	mov	@#csrpt,r1		; load selected csr to R1, unit <R0>
go:	mov	r0,(r1)+		; init controller (write IP), bump ptr
       	mov	#4000,r5		; S1 state bitmask
       	mov	#mscpdt,r3		; point to data
       
       	; write 4 init words, with r5 mask from 4000 to 40000
3$:	dec	r4			; MGM count loops in r4 
	beq	duNr			; if too many, goto retry
	tst	(r1)			; error bit set ?
       	bmi	duNr			; yes, fail back to begin to retry
       	bit	(r1),r5 		; step bit set ?
       	beq	3$			; not yet, wait loop
       	mov	(r3)+,(r1)		; yes, send next init data
       	asl	r5			; next mask
       	bpl	3$			; s4 done? br if not yet
       
4$:	clr	r2			; set bufptr to 0
5$:	clr	(r2)+			; clear buffer [0..2403]
       	cmp	r2,#comm		; check for end of buffer
       	bne	5$			; loop if not done
       
       	mov	r2,@#cpkt-4		; set lnt -- R2=2404
       	movb	(r3)+,@#cpkt+10 	; set command
       	movb	(r3),@#cpkt+15		; set bytecnt(hi)
       	mov	r0,@#cpkt+4		; set unit
       	mov	#rpkt,(r2)+		; rq desc addr
       	mov	r5,(r2)+		; rq own bit15
       	mov	#cpkt,(r2)+		; cp desc addr
       	mov	r5,(r2)+		; cq own bit15
       	mov	-2(r1),r2		; wake controller (read IP)
       
	mov	#10000,r4		; MGM loop 10000 times then retry

6$:	dec	r4			; MGM count loops in r4
	beq	duNr			; if too many, go to start
	tst	@#comm+2		; rq own controller ?
       	bmi	6$			; loop if not done
       
       	tstb	@#rpkt+12		; check for error ?
       	bne	duNr			; yup, fail back to begin to retry
       
       	tstb	(r3)+			; check end of table ?
       	beq	4$			; br if not yet
       
       	clr	-(r1)			; init controller (write IP)
       	clr	pc			; jmp to bootstrap at zero
       
lpcnt:	.word	177777			; LED display = .
csrpt:	.word	172150			; store csr choice for retries

       	; MSCP init and command data
       	; pointed to by r3
mscpdt:
       	.word	100000			; S1: 100000 = no int, ring size 1, no vector
       	.word	comm			; S2: 002404 = ringbase lo addr
       	.word	000000			; S3: 000000 = no purge/poll, ringbase hi addr
       	.word	000001			; S4: 000001 = go bit
       	;
       	; MSCP command data
       	;
       	.byte	011,000 		; cmd=011(online), bytecnt_hi=000(0)
       	.byte	041,002 		; cmd=041(read), bytecnt_hi=002(512)
       
       	.end
