	.title	M9312 'DU' BOOT prom for MSCP compatible controller

	; This source code is an exact 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.
	;
	; Standard devices are 82S131, Am27S13, 74S571 or other compatible bipolar
	; PROMs with a 512x4 TriState 16pin DIP architecture. This code resides in
	; the low half of the device; the top half is blank and unused.
	;
	; Alternatively, 82S129 compatible 256x4 TriState 16pin DIP devices can be
	; used, as the uppermost address line (hardwired low) is an active low chip
	; select (and will be correctly asserted low).

ducsr	=172150				; std MSCP csrbase

duip	=+0				; IP register
dusa	=+2				; SA register

diags	=165564				; console diags phase2 entry

	.asect
	.=173000

	; --------------------------------------------------

start:	.ascii	"UD"			; device code (reversed)

	.word	last-.			; offset to next boot header

du0n:	sec				; boot std csr, unit zero, no diags
du0d:	mov	#0,r0			; boot std csr, unit zero, with diags
duNr:	mov	#ducsr,r1		; boot std csr, unit <R0>
duNb:	mov	pc,r4			; boot csr <R1>, unit <R0>
	bcc	diag			; br if diags requested
	br	go			; return to (R4)+2 from diags
					; then skip over pseudo reboot vector

	; --------------------------------------------------

	.word	173000			; prom start addess @ 24
	.word	340			; and priority level @ 26

	; --------------------------------------------------

diag:	jmp	@#diags			; jump to console diags

rpkt	=1004	; rpkt structure
cpkt	=1070	; cpkt structure
comm	=2404	; comm structure

go:	mov	r0,(r1)+		; init controller (write IP), bump ptr
	mov	#4000,r5		; S1 state bitmask

	mov	pc,r3			; point to data at next word
	;
	; *** start of hack ***
	;
	;   this is a real hack to save some instruction words
	;      100000 == bpl .+2
	;      002404 == blt .+12 == comm
	;   bpl will always fail to branch (since PC is 'negative')
	;   blt will always succeed to branch (since PC is 'negative')
	;
	; MSCP init data
	;
	bpl	2$			; S1: 100000 = no int, ring size 1, no vector
2$:	blt	3$			; 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 of hack ***

	;  init loop

3$:	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

	; command loop

4$:	clr	r2			; set bufptr to 0
5$:	clr	(r2)+			; clear buffer [0..comm-1]
	cmp	r2,#comm		; check for end of buffer
	bne	5$			; loop if not done

	; r0 = unit#
	; r1 = a(sa)
	; r2 = a(comm)
	; r3 = a(table)
	; r4 = <unused>
	; r5 = 100000
	; sp = <unused>

	mov	r2,@#cpkt-4.		; set cmd packet length
	movb	(r3)+,@#cpkt+8.		; set cmd opcode
	movb	(r3),@#cpkt+13.		; set cmd bytecnt hi
	mov	r0,@#cpkt+4.		; set cmd 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)

	;  wait loop

6$:	tst	@#comm+2.		; rq own controller ?
	bmi	6$			; loop if not done

	tstb	@#rpkt+10.		; 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

	; --------------------------------------------------

	.word	0			; unused

	; --------------------------------------------------

	.=start+176
crc16:	.word	<032074>		; CRC-16 will go here

last:	; next boot prom starts here

	.end
