;============================================================
;CP/M Program to a Eject PerSci Disk on the CCS 2422
;Floppy Disk Controller
;============================================================
;Revision History
; 1.00 13 Feb 2018  M. Eberhard
;============================================================
;=======
;Equates
;=======

MAXDRV	equ	3		;highest allowed drive number

;------------------------------------------
; BDOS Function Codes, passed in register C
;------------------------------------------
BPRINT	equ	9	;Print $-terminated line at de
;-------------------------
;Page 0 reserved locations
;-------------------------
WBOOTV	equ	0		;CP/M warm boot entry
IOBYTE	equ	3		;Intel IOBYTE location
CDISK	equ	4		;current disk
BDOSV	equ	5		;vector to BDOS

;CP/M Buffers 

COMBUF	equ	80h		;temp buffer used by CP/M
TPA	equ	100h		;transient program area
;---------------------------------------
;CCS 2422 floppy disk controller equates
;---------------------------------------
BCTRL	equ	4		;Control port 2
BSTAT	equ	4		;status port 2
DSTAT	equ	30h		;disk status port
DCMMD	equ	DSTAT		;disk command port
DTRCK	equ	DSTAT+1		;track port
DSCTR	equ	DSTAT+2		;sector port
DDATA	equ	DSTAT+3		;data port
DFLAG	equ	DSTAT+4		;disk flag port
DCTRL	equ	DSTAT+4		;disk control port

;WD1793 commands

RSTRCM	equ	00000000b	;(I) restore
SEEKCM	equ	00010000b	;(I) seek
STEPCM	equ	00100000b	;(I) step
STPICM	equ	01000000b	;(I) step-in
STPOCM	equ	01100000b	;(I) step-out
RSECCM	equ	10000000b	;(II) read sector
WSECCM	equ	10100000b	;(II) write sector
RADRCM	equ	11000000b	;(III) read address
RTRKCM	equ	11100000b	;(III) read track
WTRKCM	equ	11110000b	;(III) write track
FINTCM	equ	11010000b	;(IV) force interrupt

;WD1793 command options (1st letter matches WD1793 data sheet)

RS03MS	equ	00000000b	;(I) 3 mS step rate
RS06MS	equ	00000001b	;(I) 6 mS step rate
RS10MS	equ	00000010b	;(I) 10 mS step rate
RS15MS	equ	00000011b	;(I) 15 mS step rate
VERTRK	equ	00000100b	;(I) verify on destination track
HDLOAD	equ	00001000b	;(I) head load
UPDTTR	equ	00010000b	;(I) update track reg
F1SCMP	equ	00000010b	;(II)enable side compare
F2SCS1	equ	00001000b	;(II)side compare, side 1
MULTCM	equ	00010000b	;(II) read/write multiple
ED15MS	equ	00000100b	;(II & III) settling delay

;Control register 1 (DCTRL) output bits

DCDS1	equ	00000001b	;drive select 1
DCDS2	equ	00000010b	;drive select 2
DCDS3	equ	00000100b	;drive select 3
DCDS4	equ	00001000b	;drive select 4
DCMAXI	equ	00010000b	;0=Minidisk, 1=8" disk
DCMDMO	equ	00100000b	;Motor on
DCDDEN	equ	01000000b	;double density enable
DCAUTOW	equ	10000000b	;autowait

;Control register 2 (BCTRL) output bits

BCEJECT	equ	00000100b	;remote eject (PerSci)
BCFSEKN	equ	00010000b	;fast seek:
				;0 for voicecoil drives
BCSIDE0	equ	01000000b	;0=side 1, 1=side 0
BCROMEN	equ	10000000b	;enable onboard ROM

;WD1793 status (DSTAT) after a command

SBUSY	equ	00000001b	;(All) busy
SCRCERR	equ	00001000b	;(All) CRC error
SWRPROT	equ	01000000b	;(All) write protect
SNOTRDY	equ	10000000b	;(All) drive not ready
SINDEX	equ	00000010b	;(I) index
STRACK0	equ	00000100b	;(I) track 0
SSEEKER	equ	00010000b	;(I) seek error
SHEADLD	equ	00100000b	;(I) head loaded
SDATRQ	equ	00000010b	;(II & III) data request
SLOSTD	equ	00000100b	;(II & III) lost data error
SRNFER	equ	00010000b	;(II & III) record not found
SRCTYF	equ	00100000b	;(II & III) record type fault
SWFALT	equ	00100000b	;(II & III) Write fault

;Status register 1 (DFLAG) input bits

DFINTRQ	equ	00000001b	;WD1793 INTRQ signal, active high
DFDS1	equ	00000010b	;DS1 in control reg 1
DFDS2	equ	00000100b	;DS2 in control reg 1
DFDS3	equ	00001000b	;DS3 in control reg 1
DFDS4	equ	00010000b	;DS4 in control reg 1
DFSHLD	equ	00100000b	;WD1793 HLD, active high
DFAUTOB	equ	01000000b	;autoboot jumper, 0=autoboot
DFSDRQ	equ	10000000b	;WD1793 DRQ signal, 1=ready

;Status reg 2 (BSTAT) input bits

BTRK0	equ	00000001b	;when on track 0: 1=8" disk
BMINI	equ	00000010b	;-DCTRL reg bit: 1=Minidisk
BWPRT	equ	00000100b	;0=disk is write-protected
BSIDE0	equ	00001000b	;SIDE0 bit in ctrl reg 2
BINDEX	equ	00010000b	;index signal, active low
BDDEN	equ	00100000b	;DDEN signal in ctrl reg 1
BSIDED	equ	01000000b	;0=selected disk is 2-sided
;================
;Start of program
;================
	ORG	TPA

	lda	CDISK		;default to eject
	mov	c,a

;Get drive letter to eject

	lxi	h,COMBUF

	mov	b,m		;1st byte is byte count
	inr	b		;for initial dcr b

PLOOP:	inx	h
	dcr	b		;any more characters?
	jz	EJECT		;n: default

	mov	a,m
	cpi	' '		;skip spaces
	jz	PLOOP

	ori	'a'-'A'		;either case is ok
	sui	'a'		;valid disk to eject?
	cpi	MAXDRV+1
	jnc	ERROR
	mov	c,a		;drive to eject
EJECT:
;compute c = select bit for the drive we will eject

	mvi	a,80h		;build select bit pattern
SBLOOP:	rlc
	dcr	c
	jp	SBLOOP

	mov	c,a		;select bit pattern


;remember the controller's mini/maxi and density states in d

	in	BSTAT		;get setup too
	rlc			;move density bit into place
	mov	e,a		;temp save
	ani	DCDDEN		;density bit in place
	mov	d,a

	mov	a,e
	rlc			;move mini bit into place
	rlc
	mov	e,a
	cma			;BSTAT bit is inverted
	ani	DCMAXI
	ora	d		;combine bits
	mov	d,a		;d has density and mini/maxi bits

	mov	a,e		;sided bit is shfted 3 left
	ani	BCSIDE0		;get original side
	mov	b,a		;remember in b


;remember the controller's selected disk in e

	in	DFLAG		;get selected drive
	rar
	ani	0Fh		;just the DS bits
	mov	e,a		;..so we can put it back

;select the specified disk

	mov	a,c		;select bits
	ora	d		;leave other bits as they were
	out	DCTRL

;Eject the disk

	mvi	a,BCEJECT+BCSIDE0
	out	BCTRL

;1/2-second delay

	lxi	h,456		;assume 4 MHz

STALUP:	xra	a		;(4)[4]

STALP1:	sui	1		;(7)[7] 17*256=4352 cycles
	jnz	STALP1		;(10)[10]

	dcx	h		;(6)[5]
	mov	a,h		;(4)[5]
	ora	l		;(4)[4]
	jnz	STALUP		;(10)[10] (4+4352+24=4380 cycles/pass)

;end eject pulse

	mov	a,b		;originally selected side
	out	BCTRL

;Put disk controller back

	mov	a,e		;original select bits
	ora	d		;original controller bits
	out	DCTRL

;Return to CP/M

	ret			;to CP/M

;Bogus Entry

ERROR:	mvi	c,BPRINT	;BDOS code
	lxi	d,ERRMSG
	jmp	BDOSV		;return from there


ERRMSG:	db	'Huh?$'

	





