;****************************************************************************
;* Copyright 1994 MBARI							    *
;****************************************************************************
;* $Header: diskio.s,v 4.4 2001/06/19 12:13:20 oasisa Exp $			    *
;* Summary  : Assembly language routines for Kittyhawk IDE drive for OASIS  *
;* Filename : diskio.s							    *
;* Author   : Robert Herlien						    *
;* Project  : OASIS Mooring Controller                                      *
;* $Revision: 4.4 $							    *
;* Created  : 12/21/94							    *
;*									    *
;* MBARI provides this documentation and code "as is", with no warranty,    *
;* express or implied, of its quality or consistency. It is provided without*
;* support and without obligation on the part of the Monterey Bay Aquarium  *
;* Research Institute to assist in its use, correction, modification, or    *
;* enhancement. This information should not be published or distributed to  *
;* third parties without specific written permission from MBARI.            *
;*									    *
;****************************************************************************

$TITLE("IDE Disk I/O Routines")

DISKIO		MODULE

$INCLUDE(..\C196\INCLUDE\8096.INC)
$INCLUDE(OASIS.INC)
$INCLUDE(IO.INC)
$INCLUDE(DISK.INC)

;*****************************************************************************

PUBLIC	disk_status, disk_alt_status, disk_command, disk_error
PUBLIC	disk_read_port, disk_write_port, disk_read_buffer, disk_write_buffer

		RSEG

EXTRN	zeroBank:BYTE			;How to select bank zero


		CSEG

;******************************************************************************
; disk_status - Return disk status register
;
; Word disk_status( Void )
;
disk_status:
	ldb	tmp2b, #DSK_STATUS
	stb	tmp2b, piab_pdc			;Send status port address
	ldb	tmp3b, #(DSK_STATUS AND DSK_RD_STROBE)
	stb	tmp3b, piab_pdc			;Turn on read strobe
	ldbze	plmreg, piab_pda		;Read status byte
	stb	tmp2b, piab_pdc			;Turn off read strobe
	ldb	tmp2b, #DSK_QUIET
	stb	tmp2b, piab_pdc			;Turn off strobes
	ret

	
;******************************************************************************
; disk_alt_status - Return alternate disk status register
;
; Word disk_alt_status( Void )
;
disk_alt_status:
	ldb	tmp2b, #DSK_ALT_STATUS
	stb	tmp2b, piab_pdc			;Send alt status port address
	ldb	tmp3b, #(DSK_ALT_STATUS AND DSK_RD_STROBE)
	stb	tmp3b, piab_pdc			;Turn on read strobe
	ldbze	plmreg, piab_pda		;Read alt status byte
	stb	tmp2b, piab_pdc			;Turn off read strobe
	ldb	tmp2b, #DSK_QUIET
	stb	tmp2b, piab_pdc			;Turn off strobes
	ret

	
;******************************************************************************
; disk_error - Return disk error vector
;
; Errno disk_error( Void )
;
;	Returns status register in high byte and error register in low byte.
;
disk_error:
	scall	disk_status			;Get status register
	stb	tmp0b, tmp1b			;Put it in high byte
	ldb	tmp2b, #DSK_ERROR
	stb	tmp2b, piab_pdc			;Send error port address
	ldb	tmp3b, #(DSK_ERROR AND DSK_RD_STROBE)
	stb	tmp3b, piab_pdc			;Turn on read strobe
	ldb	tmp0b, piab_pda			;Get error byte in low byte
	stb	tmp2b, piab_pdc			;Turn off read strobe
	ldb	tmp2b, #DSK_QUIET
	stb	tmp2b, piab_pdc			;Turn off strobes
	ret


;******************************************************************************
; disk_command - Send command to disk command port
;
; Void disk_command( Nat16 cmd )
;
disk_command:
	ldb	tmp2b, #0ffh
	stb	tmp2b, piab_ddra		;Set port A as outputs
	ldb	tmp2b, #DSK_COMMAND
	stb	tmp2b, piab_pdc			;Send command port address
	ldbze	tmp0, 2[SP]			;Get command byte
	stb	tmp0b, piab_pda			;Put it out on port A
	ldb	tmp3b, #(DSK_COMMAND AND DSK_WRT_STROBE)
	stb	tmp3b, piab_pdc			;Turn on write strobe
	stb	tmp2b, piab_pdc			;Turn off write strobe
	ldb	tmp2b, #DSK_QUIET
	stb	tmp2b, piab_pdc			;Turn off chip select
	stb	R0, piab_ddra			;Restore port A as inputs
	ret
	

;******************************************************************************
; disk_read_port - Read a value from a disk port
;
; Nat16 disk_read_port( Nat16 port )
;
disk_read_port:
	ldbze	tmp2, 2[SP]			;Get disk port number
	orb	tmp2b, #DSK_PORT_MASK		;Make sure rd/wrt strobes off
	stb	tmp2b, piab_pdc			;Put out port address
	andb	tmp3b, tmp2b, #DSK_RD_STROBE
	stb	tmp3b, piab_pdc			;Turn on read strobe
	ldbze	plmreg, piab_pda		;Read port byte
	stb	tmp3b, piab_pdc			;Turn off read strobe
	ldb	tmp2b, #DSK_QUIET
	stb	tmp2b, piab_pdc			;Turn off chip select
	ret

	
;******************************************************************************
; disk_write_port - Write a value to a disk port
;
; Void disk_write_port( Nat16 port, Nat16 value )
;
disk_write_port:
	ldb	tmp2b, #0ffh
	stb	tmp2b, piab_ddra		;Set port A as outputs
	ldbze	tmp2, 2[SP]			;Get disk port number
	orb	tmp2b, #DSK_PORT_MASK		;Make sure rd/wrt strobes off
	stb	tmp2b, piab_pdc
	ldbze	tmp0, 4[SP]			;Get value to write
	stb	tmp0b, piab_pda			;Write it
	andb	tmp3b, tmp2b, #DSK_WRT_STROBE
	stb	tmp3b, piab_pdc			;Turn on write strobe
	stb	tmp2b, piab_pdc			;Turn off write strobe
	ldb	tmp2b, #DSK_QUIET
	stb	tmp2b, piab_pdc			;Turn off strobes
	stb	R0, piab_ddra			;Restore port A as inputs
	ret
	
	
;******************************************************************************
; disk_read_buffer - Read one sector (512 bytes) of data from disk buffer
;		     into banked memory.  Takes approx 4.1 ms at 9.83 MHz.
;		     Has interrupt-off window of 256 usec at 9.83 MHz.
;
; Void disk_read_buffer( Nat16 bank, char *dst )
;
;	Register usage: tmp0b = inner loop counter
;			tmp1b = outer loop counter
;			tmp2b = disk data port address, RD/ strobe inactive
;			tmp3b = disk data port address, RD/ strobe active
;			tmp4 = destination buffer pointer
;			tmp6 = data word

disk_read_buffer:
	ld	tmp4, 4[SP]			;Get destination address
	ldb	tmp2b, #DSK_DATA		;Remember data port address
	ldb	tmp3b, #(DSK_DATA AND DSK_RD_STROBE)
	stb	tmp2b, piab_pdc			;Output data port address
	ldb	tmp1b, #16			;Transfer 16 * 16 = 256 words

disk_read_loop1:
	ldb	tmp0b, 2[SP]			;Get memory bank number
	orb	tmp0b, zeroBank
	di					;Keep interrupts off
	stb	tmp0b, bank_port		;Switch in banked memory
	ldb	tmp0b, #16			;Transfer 16 * 16 = 256 words

disk_read_loop2:
	stb	tmp3b, piab_pdc			;Turn on read strobe
	ld	tmp6,  piab_pda		;Fortuitously, port A data and port B
					;data are adjacent, so we can get word
	stb	tmp2b, piab_pdc			;Turn off read strobe
	st	tmp6, [tmp4]+			;Store disk word
	djnz	tmp0b, disk_read_loop2		;Do inner loop

	stb	zeroBank, bank_port		;Restore memory bank 0
	ei					;Allow an interrupt window
	djnz	tmp1b, disk_read_loop1		;Do outer loop

	ldb	tmp2b, #DSK_QUIET
	stb	tmp2b, piab_pdc			;Turn off chip select
	ei
	ret
	
	
;******************************************************************************
; disk_write_buffer - Write one sector (512 bytes) of data from banked
;		      memory into disk buffer.  Takes approx 4.1 ms at 9.83 MHz.
;		      Has interrupt-off window of 256 usec at 9.83 MHz.
;
; Void disk_write_buffer( Nat16 bank, char *src )
;
;	Register usage: tmp0b = inner loop counter
;			tmp1b = outer loop counter
;			tmp2b = disk data port address, WRT/ strobe inactive
;			tmp3b = disk data port address, WRT/ strobe active
;			tmp4 = source buffer pointer
;			tmp6 = data word

disk_write_buffer:
	ldb	tmp0b, #0ffh
	stb	tmp0b, piab_ddra		;Set ports A and B as outputs
	stb	tmp0b, piab_ddrb
	ld	tmp4, 4[SP]			;Get source address
	ldb	tmp2b, #DSK_DATA		;Remember data port address
	ldb	tmp3b, #(DSK_DATA AND DSK_WRT_STROBE)
	stb	tmp2b, piab_pdc			;Output data port address
	ldb	tmp1b, #16			;Transfer 16 * 16 = 256 words

disk_write_loop1:
	ldb	tmp0b, 2[SP]			;Get memory bank number
	orb	tmp0b, zeroBank
	di					;Interrupts off
	stb	tmp0b, bank_port		;Switch in banked memory
	ldb	tmp0b, #16			;Transfer 16 * 16 = 256 words

disk_write_loop2:
	ld	tmp6, [tmp4]+			;Get data word
	st	tmp6,  piab_pda		;Fortuitously, port A data and port B
					;data are adjacent, so we can wrt word
	stb	tmp3b, piab_pdc			;Turn on write strobe
	stb	tmp2b, piab_pdc			;Turn off write strobe
	djnz	tmp0b, disk_write_loop2		;Do inner loop

	stb	zeroBank, bank_port		;Restore memory bank 0
	ei					;Allow an interrupt window
	djnz	tmp1b, disk_write_loop1		;Do outer loop

	ldb	tmp2b, #DSK_QUIET
	stb	tmp2b, piab_pdc			;Turn off chip select
	stb	R0, piab_ddra			;Restore ports A and B
	stb	R0, piab_ddrb
	ei
	ret

	END
