	.title Dual-Density bootstrap for RX02

	; This bootstrap is derived from the RX211/RXV21
	; bootstrap that appears in the RX01/RX02 Pocket Service
	; Gude (DEC order number EK-RX012-PS-002).
	;
	; It has been modified so that:
	; * It can be used for unit 0 or unit 1
	; * It will first attempt to boot a double-density disk.
	;   If that fails, it will then attempt to boot a
	;   single-density disk.
	;
	; The code shown below is for unit 0. to boot from unit 1:
	; * change the word at 0010036 from 000407 to 000427
	; * change the word at 0010132 from 000000 to 000001
	;
	; Malcolm MacLeod - 11 June 2017
	;
	; Documentation and boot logic
	; Joerg Hoppe - Nov 2022


rx2cs	= 177170		; RXV21 control/status register
rx2db	= 177172		; RXV21 data buffer register
wrdcnt	= ^D128 		; 128 for DBL-DEN, 64 for SGL-DEN
mask	= 100240		; Bit 15=ERR, 7=XFER-RQST, 5=DONE

	.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

	; On boot from #0 implemented
start:
;	; 2 unit numbers => 2 entry addresses
start0:
;	mov	#0,r0
;	br	boot
;	nop
;start1:
;	mov	#1,r0

boot:	mov	#rx2cs,r1	; put addr of rx2cs into r1
	mov	#mask,r0	; put bit mask into r0
	clr	R2		; clear bus addr (dma dest'n addr)
	mov	#wrdcnt,r5	; put word count (128) into r5
	mov	#401,r4 	; track 1, sector 1
$1:	mov	#rx2db,r3	; put addr of rx2db in r3

	; Check that the rxv21 is ready

$2:	bit	r0,(r1) 	; apply mask to rx2cs
	beq	$2		; loop until err, xfer-rqst or done
	bmi	quit		; halt if err is set

	; Initiate a read-sector command

	mov	#407,(r1)	; den=dden, unit=0, fn=rd-sector, go
$3:	bit	r0,(r1) 	; apply mask to rx2cs
	beq	$3		; loop until err, xfer-rqst or done
	bmi	quit		; halt if err is set
	; Code assumes that xfer-rqst is now set (ignores done)
	movb	r4,(r3) 	; write sector number to rx2db
	swab	r4		; swap track number to bits 0-7
$4:	bit	r0,(r1) 	; apply mask to rx2cs
	beq	$4		; loop until err, xfer-rqst or done
	; Code assumes that xfer-rqst (not err or done) is now set
	movb	r4,(r3) 	; write track number to rx2db

	; rxv21 is now reading sector data into its own buffer

	swab	r4		; swap track number to bits 15-8
$5:	bit	r0,(r1) 	; apply mask to rx2cs
	beq	$5		; loop until err, xfer-rqst or done
	bmi	quit		; halt if err is set

	; Code assumes that xfer-rqst is now set (ignores done)

	; The sector data is now in rxv21's data buffer.
	; Prepare to transfer sector data from rxv21 to ram by dma

	mov	#403,(r1)	; den=dden, unit=any, fn=empty-buf, go
$6:	bit	r0,(r1) 	; apply mask to rx2cs
	beq	$6		; loop until err, xfer-rqst or done
	bmi	quit		; halt if err is set
	; Code assumes that xfer-rqst is now set (ignores done)
	mov	r5,(r3) 	; ld word count into rx2wc via rx2db
$7:	bit	r0,(r1) 	; apply mask to rx2cs
	beq	$7		; loop until err, xfer-rqst or done
	bmi	quit		; halt if err is set
	; Code assumes that xfer-rqst is now set (ignores done)
	mov	r2,(r3) 	; ld bus addrs into rx2ba via rx2db

	; Data (256 bytes) is now being copied to ram via dma

	add	r5,r2		; add 128 dec to bus address
	add	r5,r2		; add 128 dec to bus address
	cmpb	(r4)+,(r4)+	; increment sector number by 2
	cmpb	r4,#7		; sectors 1, 3, 5 & 7 will be read
	ble	$2		; loop back and do next sector
	mov	#0,r0		; boot device is unit 0
	clr	pc		; go to addr zero

	; Errors always branch to here. on first error (during
	; dden attempt) we change to sden mode and try again.
	; Self modifying code here!
	; On second error, we halt.

quit:	reset			; reset all i/o devices
	mov	#boot,r0	; load r0 with start address
	mov	#400,r1 	; setup mask byte
	asr	14(r0)		; change "mov #wrdcnt,r5" to 64 decimal
	bic	r1,36(r0)	; change "mov #407,(r1)" read-sector cmd to sden
	bic	r1,72(r0)	; change "mov #403,(r1)" empty-buffer cmd to sden
	mov	#17,124(r0)	; change "cmpb r4,#7" last sector to d'15
	clr	136(r0) 	; change "reset" to halt at quit location
	br	boot		; go back and try sden mode

	.end
