**************************************************************************
*
*  Smoke Signal Broadcasting BFD-68 Disk Controller ROM 2-61777
*
*  This file contains the disassembly of the 512 byte ROM on the BFD-68.
*  This disassembly is the processor's view of the ROM. The actual ROM has
*  all bytes inverted since the SS-50 data bus is inverted and the ROM's
*  data lines connect directly to the SS-50 bus.
*
*  This ROM is in the SWTPC memory-mapped I/O space from $8000-$83FF. The
*  ROM appears every other 32 bytes ($20) bytes. This is reflected in this
*  source file by the "rmb $20" statements. The empty 32 byte blocks are
*  not present in the ROM because ROM address pins 5-8 are driven with bus
*  address lines 6-9.
*
*  The 1771 disk controller is accessed through a 6821 PIA. Values are
*  written to port A of the PIA to select the 1771 register to read/write
*  and then port B is used to transfer data bytes to/from the 1771. CA1
*  is used to detect the rising edge of the INTRQ line from the 1771. CA2
*  is used to detect the DRQ handshake line from the 1771 when reading
*  sector data. CB2 is used as a negative going output strobe for data
*  written to the 1771.
*
*  The 6821 is connected directly the negative logic SS-50 data bus, so 
*  the values read/written with the 6821 are inverted. Note, however, that
*  the 1771 also uses an inverted data bus, so the values to/from the 1771
*  do not have to be inverted
*
*  Disassembly by Mike Douglas, 4/11/2023
*
**************************************************************************
PIABASE	equ	$9FFC		;board controlled through a 6821 PIA

ADATA	equ	PIABASE+0	;data register A
ADIR	equ	PIABASE+0	;data direction register A
ACONTRL	equ	PIABASE+1	;control register A
oADATA	equ	0		;offset to data register A
oADIR	equ	0		;offset to data direction reg A
oACTL	equ	1		;offset to control register A

BDATA	equ	PIABASE+2	;data register B
BDIR	equ	PIABASE+2	;data direction register B
BCONTRL	equ	PIABASE+3	;control register B
oBDATA	equ	2		;offset to data register B
oBDIR	equ	2		;offset to data direction reg B
oBCTL	equ	3		;offset to control register B

INPUT	equ	$FF		;sets a port as input (inverted)
BOOTLOC	equ	$7000		;boot sector loaded here

* This ROM is used with DOS-68 which supplies parameters as follows:
*    Drive numbers 0-3 come in as $08, $10, $20, $40 at $A07B
*    Track numbers 0-34 come in as $80-$A2 at $A07C
*    Sector numbers 0-17 come in as $40-$51 at $A07D
*    Sector buffer pointer is at $A07E

PARAMS	equ	$A07A
BOOTFLG	equ	$A07A		;0=cold boot, 3=warm boot
DRIVE	equ	$A07B		;drive number as above
TRACK	equ	$A07C		;track number as above
SECTOR	equ	$A07D		;sector number as above
BUFPTR	equ	$A07E		;pointer to sector buffer

oDRIVE	equ	1		;offset to drive in PARAMs
oTRACK	equ	2		;offset to track
oSECTOR	equ	3		;offset to sector
oBUFPTR	equ	4		;offset to buffer pointer

*----------------------------------------------------------------------
* Start of code. Code is broken into to 32 byte blocks every 
*   other 32 bytes
*----------------------------------------------------------------------
	org	$8020

* Entry vectors

vCold	jmp	cold		;cold start (boot)
vWarm	jmp	warm		;warm start (boot)
vIniPia	jmp	initPia		;initialize PIA
vRdSec	jmp	readSec		;read a sector
vWrtSec	jmp	wrtSec		;write a sector
vRdTrk	jmp	readTrk		;read track
vWrtTrk	jmp	wrtTrk		;write track (format)
vSeek	jmp	seek		;seek
vRestor	jmp	restore		;restore to track 0

	fcb	$6B,0,0,0,0	;match ROM
	rmb	$20

vWrtCmd	jmp	wrtCmd		;send command to 1771
vWtCmd	jmp	waitCmd		;wait for command to complete
vRdStat	jmp	rdStat		;read 1771 status register
vSetSec	jmp	setSec		;write to 1771 sector register
vSetTrk	jmp	setTrk		;write TRACK to track register
vSetSk	jmp	setSeek		;set seek in data register
vGetTrk	jmp	getTrk		;read track register into B
vStepIn	jmp	stepIn		;step in one track
vStpOut	jmp	stepOut		;step out one track
vStep	jmp	step		;execute step command at $3B

	fcb	$AE,0		;match ROM
	rmb	$20

*----------------------------------------------------------------------
* initPia - Initialize the PIA
*----------------------------------------------------------------------
initPia	ldx	#PIABASE
	ldaa	#$FF		;$00 (values are complemented)
	staa	oACTL,x		;access data direction register
	staa	oBCTL,x
	staa	oBDIR,x		;port B is input ($00)
	clr	oADIR,x		;port A is output ($FF)

	ldaa	#$FF-$1E	;$1E INTRQ in on rising edge of CA1
*				;    DRQ in on rising edge of CA2 
	staa	oACTL,x
	ldaa	#$FF-$2C	;$2C negative write strobe on CB2
	staa	oBCTL,x
	jmp	rdStat		;exit with 1771 status in B

*----------------------------------------------------------------------
* step - Execute 1771 step command saved at $3B
* stepIn - Execute 1771 step in command 
* stepOut - Execute 1771 step out command
*----------------------------------------------------------------------
step	ldab	$3B		;use command store at $3B
	bra	doStep

	fcb	$BE,0,0,0	;match ROM
	rmb	$20

stepIn	ldab	#$5B		;1771 step in command

doStep	jsr	wrtCmd
	jmp	waitCmd

stepOut	ldab	#$7B		;1771 step out command
	bra	doStep

*----------------------------------------------------------------------
* restore - Execute 1771 restore to track 0 commannd
*----------------------------------------------------------------------
restore	ldx	#PARAMS		;X->drive, track, sector parameters
	ldab	#$0B		;B=restore command
	jsr	wrtCmd		;write it
	jmp	waitCmd		;wait for finish then exit

*----------------------------------------------------------------------
* setSeek - Set the seek-to track in the 1771 data register from TRACK
*----------------------------------------------------------------------
setSeek	ldaa	#$BC		;setup port A to write to data reg
	ldab	oTRACK,x
	andb	#$3F		;get track number alone
	bra	wrtReg		;write track to 1771 data register

	fcb	$E5		;match ROM
	rmb	$20

*----------------------------------------------------------------------
* setSec - Set the sector number register in the 1771 from SECTOR
*----------------------------------------------------------------------
setSec	ldaa	#$BD		;setup port A to write to sector reg
	ldab	oSECTOR,x	;B=sector number
	andb	#$1F
	bra	wrtReg		;write sector to 1771 sector reg

*----------------------------------------------------------------------
* setTrk - Set the track number register in the 1771 from TRACK
*----------------------------------------------------------------------
setTrk	ldaa	#$BE		;setup port A to write to track reg
	ldab	oTRACK,x	;B=track
	andb	#$3F		;limit to 0-63
	bra	wrtReg		;write track to 1772 track reg

*----------------------------------------------------------------------
* wrtCmd - Write 1771 command register from B
* wrtReg - Write 1771 register in A with data from B
*----------------------------------------------------------------------
wrtCmd	ldaa	#$BF		;setup port A to write command reg

wrtReg	eora	oDRIVE,x	;include drive select
	staa	ADATA
	clra			;set port B as output
	bsr	setDirB
	stab	BDATA		;write value to 1771
	rts

	fcb	$1E,0		;match ROM
	rmb	$20

*----------------------------------------------------------------------
* getTrk - Return the 1771 track register in B
*----------------------------------------------------------------------
getTrk	ldaa	#INPUT		;set port B as input
	bsr	setDirB
	ldaa	#$FE		;setup port A to access track reg
	eora	oDRIVE,x	;include drive select
	staa	ADATA
	fcb	$02		;should be $01 (NOP)
	ldab	BDATA		;return 1771 value in B
	rts

*----------------------------------------------------------------------
* setDirB - Set PIA port B direction register from A
*----------------------------------------------------------------------
setDirB	psha
	ldaa	#$FF-$28	;$28 access data direction register
	staa	BCONTRL
	pula
	staa	BDIR		;set new direction
	ldaa	#$FF-$2C	;$2C access data register
	staa	BCONTRL
	rts

	rmb	$20

*----------------------------------------------------------------------
* waitCmd - Wait for INTRQ from the 1771 to indicate the command
*   has completed. Returns with the 1771 status register in B.
*----------------------------------------------------------------------
waitCmd	ldaa	ACONTRL		;wait for INTRQ from 1771
	bmi	waitCmd

	ldaa	ADATA		;clear handshake
*				;fall into rdStat

*----------------------------------------------------------------------
* rdStat - Return 1771 status register in B. Status set with
*   TSTB on exit.
*----------------------------------------------------------------------
rdStat	ldx	#PARAMS		;X->drive, track, sector parameters
	ldaa	#INPUT		;setup to input from 1771
	bsr	setDirB

	ldaa	#$FF		;setup port A to read 1771 status
	eora	oDRIVE,x	;include drive select
	staa	ADATA
	ldab	BDATA		;read 1771 status
	ldaa	ADATA		;clear handshake bits
	tstb
ret1	rts

	fcb	$49,0		;match ROM
	rmb	$20

*----------------------------------------------------------------------
* readTrk - Issue 1771 Read Track command
*----------------------------------------------------------------------
readTrk	jsr	seek		;seek to TRACK
	bne	ret1		;error
	ldab	#$E5		;1771 read track command
	bra	doCmd

*----------------------------------------------------------------------
* readSec - Read sector using TRACK, SECTOR and BUFPTR
*----------------------------------------------------------------------
readSec	jsr	seek		;seek to TRACK
	bne	ret1		;error
	jsr	setSec		;give 1771 the sector to look for

	ldab	#$8C		;B=1771 read command

doCmd	pshb
	ldaa	#$BF		;setup port A to write 1771 command
	eora	oDRIVE,x	;include drive select
	staa	ADATA
	ldaa	#$FF-$E8	$E8 access data direction reg
	bra	rdSec2

	fcb	$B5		;match ROM
	rmb	$20

rdSec2	staa	BCONTRL		;access port B DDR
	clrb			;$FF set as output
	stab	BDIR
	ldab	#$FF-$EC	;$EC back to data register
	stab	BCONTRL

	pulb			;B=read command
	stab	BDATA		;give to 1771

	ldab	#INPUT		;set port B to read data
	staa	BCONTRL		;access DDR
	stab	BDATA
	ldaa	#$FF-$EC	;$EC back to data register
	bra	rdSec3		;continue

	fcb	$B3,0,0,0	;match ROM
	rmb	$20

rdSec3	staa	BCONTRL
	ldaa	#$3C		;setup port A to read sector data
	eora	oDRIVE,x	;include drive select
	ldx	oBUFPTR,x	X->sector buffer
	staa	ADATA

rdLoop	ldaa	ACONTRL		;sector done (INTRQ)?
	bpl	rdDone		;yes
	asla			;new byte ready?
	bmi	rdLoop		;no

	ldab	BDATA		;get byte
	stab	0,x		;save in buffer
	inx
	ldaa	ADATA		;clear handshake
	bra	rdLoop

	fcb	$81		;match ROM
	rmb	$20

rdDone	asla			;need to read last byte?
	bmi	rdExit		;no
	ldab	BDATA		;else, get last byte
	stab	0,x
rdExit	jmp	rdStat		;exit with 1771 status in B

*---------------------------------------------------------------------
* seek - Seek to track specified in TRACK
*----------------------------------------------------------------------
seek	ldx	#PARAMS		;X->drive, track, sector parameters
	jsr	setSeek		;set destination track in 1771

	ldab	#$1F		;seek with verify command
	jsr	wrtCmd
	jsr	waitCmd
	orab	#$01		;flag that this is seek status
	bitb	#$98		;test for seek error bits
ret2	rts

	fcb	$33,0		;match ROM
	rmb	$20

*----------------------------------------------------------------------
* wrtTrk - Write track for formatting. Assumes the drive is already
*   on the correct track.
*----------------------------------------------------------------------
wrtTrk	ldab	#$F4		;B=1771 write track command
	ldx	#PARAMS		;X->drive, track, sector parameters
	bra	doWrt

*----------------------------------------------------------------------
* wrtSec - Write sector using TRACK, SECTOR and BUFPTR
*----------------------------------------------------------------------
wrtSec	bsr	seek		;seek to track in TRACK
	bne	ret2		;error
	jsr	setSec		;give 1771 the sector to wwrite
	ldab	#$AC		;B=1771 write sector command

doWrt	ldaa	#$BF		;setup port A to write 1771 command
	eora	oDRIVE,x	;include drive select
	staa	ADATA
	clra			;set port B as output
	jsr	setDirB
	ldaa	#$BC		;access 1771 data register next
	bra	wrtSec2		;continue

	fcb	$BB		;match ROM
	rmb	$20

wrtSec2	eora	oDRIVE,x	;include drive select
	ldx	oBUFPTR,x	;X->data buffer
	stab	BDATA		;issue write command
	staa	ADATA		;1771 data reg from here on

wrtLoop	ldaa	ACONTRL		;end of sector (INTRQ)?
	bpl	wrtDone		;yes
	asla			;new byte requested?
	bmi	wrtLoop		;no

	ldab	0,x		;get next byte
	stab	BDATA		;give to 1771
	inx
	ldaa	ADATA		;clear handshake
	bra	wrtLoop

wrtDone	jmp	rdStat		;exit with 1771 status
	
	rmb	$20

*----------------------------------------------------------------------
* cold - Cold start entry point and boot
* warm - Warm start entry point and boot
*----------------------------------------------------------------------
cold	ldab	#0		;cold boot flag is 0
	bra	setBoot

warm	ldab	#3		;warm boot flag is 3

setBoot	stab	BOOTFLG
	fcb	$02		;should be $01 (NOP)
	sei			;disable interrupts
	lds	#$A079		;init stack pointer
	bra	boot		;boot the disk

	fcb	$3F,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	rmb	$20

*----------------------------------------------------------------------
* boot - Read track 0 sector 0 into RAM at BOOTLOC and then jump to it
*----------------------------------------------------------------------
boot	jsr	initPia		;initalize the PIA

	ldx	#0		;track 0, sector 0
	stx	TRACK
	ldx	#BOOTLOC	;X->where to load sector ($7000)
	stx	BUFPTR
	ldaa	#$08		;specify drive 0
	staa	DRIVE

	jsr	restore		;restore to track 0
	jsr	readSec		;read sector 0
	bne	boot		;loop if failed

	jmp	BOOTLOC		;execute loaded code

	fcb	$98		;match ROM
	rmb	$20
	fcb	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	fcb	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

	end

