;------------------------------------------------------------------
;
;  88-HDSK I/O support routines from the BASIC program VOLINIT
;
;------------------------------------------------------------------

; 88-HDSK ports (The interface board is actually an 88-4PIO.)

CREADY	equ	0A0h		;IN: Ctlr ready for command (bit7)
CSTAT	equ	0A1h		;IN: error flags, reset CREADY
ACSTA	equ	0A2h		;IN: Command Ack (bit 7)
ACMD	equ	0A3h		;IN: reset Command Ack
				;OUT: Command high byte/initiate
CDSTA	equ	0A4h		;IN: data/stat available at CDATA
CDATA	equ	0A5h		;IN: Disk data or status from Ctlr
ADSTA	equ	0A6h		;IN: ADATA Port Available (bit 7)
ADATA	equ	0A7h		;OUT: Command low byte

; 88-HDSK Commands

CSEEK	equ	00h		;Bits 15:12 = 0000b
				;Bits 11:10 = Unit #
				;Bits  9:0  = Cylinder #
CWRSEC	equ	20h		;same bit fields as CRDSECT
CRDSEC	equ	30h		;Bits 15:12 = 0011b
				;Bits 11:10 = Unit #
				;Bits  9:8  = Buffer #
				;Bit   7:6  = Platter #
				;Bits    5  = Side #
				;Bits  4:0  = Sector #
CSIDE	equ	020h		;Side select for CRDSEC
CFPLTR	equ	0C0h		;platter mask for CRDSEC
CUNIT	equ	00Ch		;Unit mask for CSEEK & CRDSEC
CWRBUF	equ	40h		;same bit fields as CRDBUF
CRDBUF	equ	50h		;Bits 15:12 = 0101b
				;Bits 11:10 = not used
				;Bits  9:8  = buffer #
				;Bits  7:0  = # bytes to transfer
				;(00 means 256)
; Misc Equates

PTSTR	equ	3		;BASIC parameter type is string
MAKINT	equ	046h		;BASIC MAKINT return entry point

	org	0E700H
;------------------------------------------------------------------
; seek - seek to the unit:cylinder number passed from BASIC as an 
;    integer.
;------------------------------------------------------------------
seek	push	psw
	push	h
	call	getParm		;get the integer passed by BASIC
	mov	a,l
	out	ADATA		;send low byte of command
	mov	a,h
	ori	CSEEK		;form seek command
	call	sendCmd		;send the command
	pop	h
	pop	psw
	ret

;------------------------------------------------------------------
; rdSect - read the specified sector from the specified unit
;    and head from the current cylinder into the specified buffer.
;    The integer passed must have the unit, buffer, head and
;    sector values in place to match the Read Sector command word.
;------------------------------------------------------------------
rdSect	push	b
	push	h
	push	psw
	call	getParm		;get the integer passed by BASIC
	mov	a,l
	out	ADATA		;send low byte of command
	mov	a,h		;A = high byte of command
	ori	CRDSEC		;form read sector command
	call	sendCmd		;send the command
	pop	psw
	pop	h
	pop	b
	ret

;------------------------------------------------------------------
; rdBuf - read the specified buffer into the BASIC array pointed
;    to by the passed parameter. Buffer and length are in the
;    first word of the passed buffer pointer. The read data is
;    stored beginning in the second word of the passed buffer.
;-----------------------------------------------------------------
rdBuf	push	b
	push	h
	push	psw
	call	getParm		;get buffer pointer
	mov	a,m		;first word contains command h:l
	mov	c,a		;A and C = buffer length
	out	ADATA		;send low byte of command
	inx	h
	mov	a,m		;A = buffer number
	ori	CRDBUF		;form read buffer command
	call	sendCmd		;send the command

; Transfer the buffer back to BASIC.

rdBufLp	in	CDATA		;get the next byte
	inx	h
	mov	m,a		;store in BASIC buffer
	dcr	c
	jnz	rdBufLp
	pop	psw
	pop	h
	pop	b
	push	h		;save the value to return
	lhld	MAKINT		;address of BASIC MAKINT
	xthl			;restore HL
	ret			;exit through MAKINT function

;------------------------------------------------------------------
; wrSect - write the specified sector to the specified unit
;    and head from the current cylinder from the specified buffer.
;    The integer passed must have the unit, buffer, head and
;    sector values in place to match the Write Sector command word.
;------------------------------------------------------------------
wrSect	push	h
	push	psw
	call	getParm		;get the integer passed by BASIC
	mov	a,l
	out	ADATA		;send low byte of command
	mov	a,h		;A = high byte of command
	ori	CWRSEC		;form writesector command
	call	sendCmd		;send the command
	pop	psw
	pop	h
	ret

;------------------------------------------------------------------
; wrBuf - write the specified buffer from the BASIC array pointed
;    to by the passed parameter. Buffer and length are in the
;    first word of the passed buffer pointer. The data to write is
;    stored beginning in the second word of the passed buffer.
;-----------------------------------------------------------------
wrBuf	push	b
	push	h
	push	psw
	call	getParm		;get buffer pointer
	mov	a,m		;first word contains command h:l
	mov	c,a		;A and C = buffer length
	out	ADATA		;send low byte of command
	inx	h
	mov	a,m		;A = buffer number
	ori	CWRBUF		;form write buffer command
	call	sendCmd		;send the command

; Transfer the BASIC buffer to the controller buffer

wrBufLp	inx	h
	mov	a,m		;next byte from BASIC buffer
	out	ADATA		;send to the controller buffer
	dcr	c
	jnz	wrBufLp
	pop	psw
	pop	h
	pop	b
	push	h
	lhld	MAKINT		;address of BASIC MAKINT
	xthl			;restore HL
	ret			;exit through MAKINT function

;------------------------------------------------------------------
; sendCmd - send command in A to the controller
;------------------------------------------------------------------
sendCmd	push	psw
sndLoop	in	CREADY		;wait for CRDY true
	ora	a
	jp	sndLoop
	in	CSTAT		;reset CRDY
	in	ACMD		;reset command ACK
	in	CDATA		;reset command data available
	in	ADATA		;reset write data ready
	pop	psw
	out	ACMD		;send the upper byte of the command
	ret

;------------------------------------------------------------------
; getParm - get parameter passed by BASIC program. If an integer
;    was passed, the integer is returned in HL. If a string was
;    passed, the address of the first character is returned in HL
;------------------------------------------------------------------
getParm	push	d
	cpi	PTSTR		;is parameter a string?
	jz	strParm		;yes
	mov	e,m		;form DE = passed integer
	inx	h
	mov	d,m
	xchg			;HL = passed integer
	pop	d
	ret

strParm	inx	d		;skip length byte
	mov	l,m		;form HL = address of string
	inx	d
	mov	h,m
	pop	d
	ret
	end

