**************************************************************************
*
*  Smoke Signal Broadcasting BFD-68A Disk Controller ROM 9-81578
*
*  This file contains the disassembly of the 512 byte ROM on the BFD-68A.
*  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. CB1 can optionally be used to detect motor start
*  if J15 is installed.
*
*  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, 3/10/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
SWI	equ	$3F		;emtpy space filled with SWI instruction

* 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 ($60-$71 for top side)
*    Sector buffer pointer is at $A07E

CURDRV	equ	$A079		;drive currently selected
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
	fcb	SWI,SWI,SWI
vWrtTrk	jmp	wrtTrk		;write track (format)
	fcb	SWI,SWI,SWI
vRestor	jmp	restore		;restore to track 0
	fcb	SWI,SWI,SWI,SWI,SWI
	rmb	$20
	fcb	SWI,SWI,SWI,SWI,SWI,SWI,SWI,SWI,SWI,SWI,SWI,SWI
vSetTrk	jmp	setTrk		;write TRACK to track register
	fcb	SWI,SWI,SWI
vGetTrk	jmp	getTrk		;read track register into B
vStepIn	jmp	stepIn		;step in one track
	fcb	SWI,SWI,SWI,SWI,SWI,SWI,SWI,SWI
	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

	fcb	SWI,SWI,SWI,SWI,SWI,SWI,SWI,SWI
	rmb	$20

*----------------------------------------------------------------------
* stepIn - Execute 1771 step in command
*----------------------------------------------------------------------
stepIn	ldab	#$5B		;B=step in command
	fcb	$8C		;makes CPX to skip next ldab

*----------------------------------------------------------------------
* restore - Execute 1771 restore to track 0 commannd
*----------------------------------------------------------------------
restore	ldab	#$0B		;B=restore command
	bsr	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	#$80		;write track to 1771 data reg
	ldab	TRACK
	andb	#$7F		;get track number alone
	bra	wrtReg		;write B to 1771 register in A

*----------------------------------------------------------------------
* addDrv2 - continuation of the addDrv function
*----------------------------------------------------------------------
addDrv2	ldaa	oSECTOR,x	;A=sector number
	anda	#$20		;side 2 bit
	lsra			;put in bit 3
	lsra
	aba			;combine with drive bits
	pulb			;caller's port A value
	aba			;combine	
	eora	#$38		;negate drive/side select bits
	pulb			;restore caller's B register
	rts

	rmb	$20

*----------------------------------------------------------------------
* setSec - Set the sector number register in the 1771 from SECTOR
*----------------------------------------------------------------------
setSec	ldaa	#$81		;write to sector register
	ldab	oSECTOR,x	;B=sector number
	andb	#$1F
	bra	wrtReg		;write B to 1771 register in A

*----------------------------------------------------------------------
* setTrk - Set the track number register in the 1771 from TRACK
*----------------------------------------------------------------------
setTrk	ldaa	#$82		;write to track reg
	ldab	TRACK
	andb	#$7F
	fcb	$8C		;makes CPX to skip next ldaa

*----------------------------------------------------------------------
* wrtCmd - Write 1771 command register from B
* wrtReg - Write 1771 register in A with data from B
*----------------------------------------------------------------------
wrtCmd	ldaa	#$83		;select cmd reg

wrtReg	jsr	addDrv		;include drive select state
	staa	ADATA
	clra			;set port B as output
	bsr	setDirB
	stab	BDATA		;write value to 1771
	rts

	fcb	SWI
	rmb	$20

*----------------------------------------------------------------------
* getTrk - Return the 1771 track register in B
*----------------------------------------------------------------------
getTrk	ldaa	#INPUT		;set port b as input
	bsr	setDirB
	ldaa	#$C2		;access track register
	jsr	addDrv		;include drive select state
	staa	ADATA
	nop
	bra	ret1771		;return 1771 value in B

*----------------------------------------------------------------------
* 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

	fcb	SWI
	rmb	$20

*----------------------------------------------------------------------
* rdStat - Return 1771 status register in B. Status set with
*   TSTB on exit.
*----------------------------------------------------------------------
rdStat	ldaa	#INPUT		;set port B as input
	bsr	setDirB
	ldaa	#$C3		;access 1771 status
	jsr	addDrv		;include drive select state
	staa	ADATA
	bsr	ret1771		;B=status from 1771
	ldaa	ADATA		;clear handshake
	tstb
ret1	rts

ret1771	ldab	BDATA		;return 1771 data
	rts

	fcb	SWI,SWI,SWI,SWI,SWI,SWI,SWI,SWI,SWI
	rmb	$20

*----------------------------------------------------------------------
* readSec - Read sector using TRACK, SECTOR and BUFPTR
*----------------------------------------------------------------------
readSec	jsr	seek		;seek to TRACK
	bne	ret1		;error
	jsr	setSec		;give 1771 sector to look for
	
	ldab	#$8C		;1771 read command
	pshb
	ldaa	#$83		;access 1771 command reg
	jsr	addDrv		;include drive select state
	staa	ADATA
	ldaa	#$FF-$E8	;($E8) access data direction register
	bra	rdSec2		;continue

	fcb	SWI,SWI,SWI,SWI,SWI,SWI,SWI,SWI,SWI
	rmb	$20

* rdSec2 - readSec continued

rdSec2	staa	BCONTRL		;access port B data direction register
	clrb			;($FF) set as output
	stab	BDIR
	ldab	#$FF-$EC	;($EC) back to data reg
	stab	BCONTRL

	pulb			;B=read command
	stab	BDATA		;give read to 1771

	ldab	#INPUT		;set port B to input to read data
	staa	BCONTRL
	stab	BDIR
	ldaa	#$FF-$EC	;($EC) back to data register
	staa	BCONTRL
	bra	rdSec3		;continue

	fcb	SWI
	rmb	$20

* rdSec3 - readSec continued

rdSec3	ldaa	#$00		;setup port A to read sector data
	jsr	addDrv		;include drive select state
	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
	jmp	rdLoop
	
	fcb	SWI,SWI
	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	jsr	setSeek		;give track to seek to 1771
	ldab	#$1F		;seek command with verify
	jsr	wrtCmd
	jsr	waitCmd
	orab	#$01		;flag that this is seek status
	bitb	#$98		;test error bits
ret2	rts

	fcb	SWI,SWI,SWI,SWI,SWI
	rmb	$20

*----------------------------------------------------------------------
* wrtTrk - Write track for formatting. Assumes the drive is already
*   on the correct track.
*----------------------------------------------------------------------
wrtTrk	ldab	#$F4		;B=1771 write track command
	bra	doWrt

*----------------------------------------------------------------------
* wrtSec - Write sector using TRACK, SECTOR and BUFPTR
*----------------------------------------------------------------------
wrtSec	bsr	seek		;seek to track in TRACK
	bne	ret2		;seek error
	jsr	setSec		;give 1771 the sector to write
	ldab	#$AC		;B=1771 write sector command

doWrt	ldaa	#$83		;access 1771 command register
	jsr	addDrv		;include drive select state
	staa	ADATA
	clra			;set port B as output
	jsr	setDirB
	ldaa	#$80		;access 1771 data register next
	bra	wrtSec2		;continue

wrtDone	jmp	waitCmd

	rmb	$20

* wrtSec2 - wrtSec continued

wrtSec2	jsr	addDrv		;B has access byte for data xfer
	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
	jmp	wrtLoop

	fcb	SWI
	rmb	$20

*----------------------------------------------------------------------
* cold - Cold start entry point and boot
* warm - Warm start entry point and boot
*----------------------------------------------------------------------
cold	ldab	#0		;cold boot flag is 0
	fcb	$8C		;makes CPX to skip next ldab

warm	ldab	#3		;warm boot flag is 3
	ldaa	#$08		;$08 is drive 0
	stab	BOOTFLG
	staa	DRIVE		;default drive is 0
	staa	CURDRV
	lds	#$A078		;init stack pointer
	bra	boot		;boot the disk

*----------------------------------------------------------------------
* 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
	jmp	rdStat

	rmb	$20

*----------------------------------------------------------------------
* boot - Read track 0 sector 0 into RAM at BOOTLOC and then jump to it
*----------------------------------------------------------------------
boot	nop
	sei

bootLp	jsr	initPia		;initialize the PIA
	ldx	#0		;track 0, sector 0
	stx	TRACK
	ldx	#BOOTLOC	;X->where to load sector ($7000)		
	stx	BUFPTR

	jsr	restore		;restore to track 0
	jsr	readSec		;read sector 0
	bne	bootLp		;loop if it failed

	jmp	BOOTLOC		;execute loaded code

* drvJmp2 - Continue the addDrv routine

drvJmp2	jmp	addDrv2		;continue addDrv routine

	fcb	SWI
	rmb	$20

*----------------------------------------------------------------------
* addDrv - Add the drive and side select bits to A for properly
*   setting the PIA port A output.
*----------------------------------------------------------------------
addDrv	pshb			;preserve registers
	psha			;A has starting value for PIA port A

* Convert drive number as bit position (0-3 are $08, $10, $20, $40)
*   into a two bit number in bits 5,4 ($00, $10, $20, $30)

	ldx	#PARAMS		;X->parameter table
	ldaa	oDRIVE,x	;A=requested drive
	ldab	#$30

drvLoop	asla			;drive bit reach bit 7?
	bmi	haveDrv		;yes, done
	subb	#$10		;else subtract 1 (at bit 4)
	bne	drvLoop

haveDrv	cmpb	CURDRV		;same drive as before?
	beq	drvJmp1		;yes
	stab	CURDRV		;else, set new drive number
	ldaa	#$FF		;deselect current drive
	staa	ADATA

drvJmp1	bra	drvJmp2		;jump to continue the addDrv routine

	fcb	$09		;match the ROM
	end

