;DSKDEV.68K	APR-27-88	(ALSO SEE "INFOSTR")
;HANDLER FOR BYTE I/O USING THE DISK
;WRITTEN BY LOREN BLANEY FOR DFM ENGINEERING
;THIS IS BASED ON 6502 CODE WRITTEN BY P.J.R. BOYLE.
;
;REVISION HISTORY:
;FEB-15-86, ORIGINAL.
;SEP-14-86, CONVERTED TO ASM68K CONVENTIONS, AND MODIFIED.
;APR-27-88, CHANGE STRING TERMINATOR CONVENTION.
;
;NOTES:
;This handler requires that the buffers are an even multiple of 256
; bytes long (SET guarantees this).
;
	NOLIST
	INCLUDE	SYSPAG		;GET SYSTEM PAGE DEFINITIONS
	LIST

DEVNUM	EQU	3		;BY CONVENTION THIS SHOULD BE DEVICE #3

	ORG	MEMTOP -$1100
START	EQU	@		;START ADDRESS OF THIS HANDLER

DSKDEV	DC.L	OPENI		;0 = OPEN FOR INPUT
	DC.L	OPENO		;1 = OPEN FOR OUTPUT
	DC.L	CHIN		;2 = INPUT A BYTE
	DC.L	CHOUT		;3 = OUTPUT A BYTE
	DC.L	CLOSE		;4 = CLOSE OUTPUT FILE
	DC.L	GETINFO		;5 = GET INFO
	DC.L	DUMMY		;6 = SPARE
	DC.L	DUMMY		;7 = SPARE

;VARIABLES:
INBSIZ	DC.L	0		;INPUT BUFFER SIZE IN BLOCKS
INBPTR	DC.L	0		;INPUT BUFFER BLOCK POINTER
INPTR	DC.L	0		;INPUT BUFFER BYTE POINTER
INBEND	DC.L	0		;END OF INPUT BUFFER+1, AS ACTUALLY READ

OTBSIZ	DC.L	0		;OUTPUT BUFFER SIZE IN BLOCKS
OTBPTR	DC.L	0		;OUTPUT BUFFER BLOCK POINTER
OTPTR	DC.L	0		;OUTPUT BUFFER BYTE POINTER

;-----------------------------------------------------------------------
;OPEN (INITIALIZE) AN INPUT FILE
;
OPENI	MOVE.L	D0,-(SP)	;SAVE D0

	TST.B	INFLG		;DO WE HAVE AN INPUT FILE?
	BNE.S	OPNI10		;BRANCH IF YES
	JSR	VERROR
	ASCII	'7 - INPUT FILE NOT SET UP'
	DC.B	0
	BRA.S	OPNI90		;EXIT

OPNI10	MOVE.L	INLBLK,INBPTR.L ;SET BLOCK POINTER TO FIRST BLOCK

	MOVE.L	INBUFE,D0	;INBSIZ := (INBUFE - INBUF) /256
	SUB.L	INBUF,D0	;CALCULATE THE NUMBER OF BLOCKS
	LSR.L	#8,D0		; IN THE INPUT BUFFER
	MOVE.L	D0,INBSIZ.L	; (ASSUMES EVEN 256-BYTE MULTIPLES)

	MOVE.L	INBUFE,INBEND.L	;SET THE POINTER TO MAKE THE INPUT
	MOVE.L	INBUFE,INPTR.L	; BUFFER APPEAR EMPTY
	MOVE.B	#$55,INFLG	;INDICATE THAT THE INPUT FILE IS OPEN

OPNI90	MOVE.L	(SP)+,D0	;RESTORE D0
DUMMY	RTS

;-----------------------------------------------------------------------
;OPEN (INITIALIZE) AN OUTPUT FILE
;
OPENO	MOVE.L	D0,-(SP)	;SAVE D0

	CMPI.B	#$01,OTFLG	;DO WE HAVE AN OUTPUT FILE?
	BEQ.S	OPNO10		;BRANCH IF YES
	CMPI.B	#$55,OTFLG	;IS IT ALREADY SET UP?
	BEQ.S	OPNO10		;BRANCH IF YES
	JSR	VERROR
	ASCII	'8 - OUTPUT FILE NOT SET UP'
	DC.B	0
	BRA.S	OPNO90		;EXIT

OPNO10	MOVE.L	OTLBLK,OTBPTR.L	;SET BLOCK POINTER TO FIRST BLOCK

	MOVE.L	OTBUFE,D0	;OTBSIZ := (OTBUFE - OTBUF) /256
	SUB.L	OTBUF,D0	;CALCULATE THE NUMBER OF BLOCKS
	LSR.L	#8,D0		; IN THE OUTPUT BUFFER
	MOVE.L	D0,OTBSIZ.L

	MOVE.L	OTBUF,OTPTR.L	;RESET POINTER TO EMPTY
	MOVE.B	#$55,OTFLG	;FLAG OUTPUT FILE OPEN

OPNO90	MOVE.L	(SP)+,D0	;RESTORE D0
	RTS

;-----------------------------------------------------------------------
;READ A BYTE FROM THE DISK FILE AND RETURN IT IN D0
;
CHIN	MOVE.L	A6,-(SP)	;SAVE A6

	CMPI.B	#$55,INFLG	;DO WE HAVE AN OPEN INPUT FILE?
	BEQ.S	CHI10		;BRANCH IF YES
	JSR	VERROR
	ASCII	'9 - INPUT FILE NOT OPEN'
	DC.B	0
	MOVEQ	#0,D0		;RETURN A 0
	BRA	CHI90		;EXIT

CHI10	MOVEA.L	INPTR.L,A6	;GET THE BUFFER POINTER
	CMPA.L	INBEND.L,A6	;IS THE BUFFER FULL?
	BLO	CHI50		;BRANCH IF NOT

;READ ANOTHER BUFFER FROM DISK
	MOVE.L	INHBLK,D0	;CALCULATE REMAINING NUMBER OF BLOCKS
	SUB.L	INBPTR.L,D0	;NBLKS := INHBLK - INBPTR +1	?????
	ADDQ.L	#1,D0
	BHI.S	CHI20		;BRANCH IF THERE IS AT LEAST ONE BLOCK
	JSR	VERROR		; REMAINING
	ASCII	'11 - READ BEYOND INPUT FILE'
	DC.B	0
	MOVEQ	#0,D0		;RETURN A 0
	BRA.S	CHI90		;EXIT

CHI20	CMP.L	INBSIZ.L,D0	;IF NBLKS > INBSIZ THEN NBLKS:=INBSIZ
	BLO.S	CHI30		;USE THE SMALLER NUMBER OF BLOCKS
	MOVE.L	INBSIZ.L,D0	;I.E. USE EITHER THE SIZE OF THE BUFFER
CHI30	MOVE.L	D0,NBLKS	; OR THE REMAINING BLOCKS IF LESS THAN
				; A BUFFER FULL
	ASL.L	#8,D0		;INBEND := INBUF + NBLKS *256
	ADD.L	INBUF,D0	;CALCULATE THE END OF THE BUFFER
	MOVE.L	D0,INBEND.L	;DON'T READ BEYOND END OF PARTIAL BUFFER

	MOVE.B	INUNT,UNIT	;PASS REMAINING ARGS TO READ ROUTINE
	MOVE.L	INBPTR.L,BLKNO
	MOVE.L	INBUF,FADDR
	MOVEA.W	#8,A6		;SET FUNCTION CODE TO "READ"
	JSR	VUNTHAN		;READ A BUFFER FULL FROM DISK
	TST.L	ERRLOC		;DID WE GET AN ERROR?
	BNE.S	CHI90		;BRANCH IF YES

	MOVE.L	INBPTR.L,D0	;INBPTR := INBPTR + NBLKS
	ADD.L	NBLKS,D0	;I.E. BUMP BLOCK POINTER
	MOVE.L	D0,INBPTR.L
	MOVEA.L	INBUF,A6	;RESET BYTE POINTER TO START OF BUFFER

CHI50	MOVEQ	#0,D0
	MOVE.B	(A6)+,D0	;GET THE BYTE, AND INCREMENT POINTER
	MOVE.L	A6,INPTR.L	;SAVE THE POINTER

CHI90	MOVEA.L	(SP)+,A6	;RESTORE A6
	RTS

;-----------------------------------------------------------------------
;FAST OUTPUT ENTRY POINT
;WRITE ARGUMENT TO DEVICE 3
; CHOUT(3,CH)
CHOUT3	MOVE.L	(A5),D0		;GET CHAR
				;(PFALL)
;-----------------------------------------------------------------------
;OUTPUT THE BYTE IN D0 TO THE DISK FILE
;
CHOUT	MOVE.L	A6,-(SP)	;SAVE A6

	CMPI.B	#$55,OTFLG	;IS THE OUTPUT FILE OPEN?
	BEQ.S	CHO10		;BRANCH IF YES
	JSR	VERROR
	ASCII	'10 - OUTPUT FILE NOT OPEN'
	DC.B	0
	BRA.S	CHO90		;EXIT

CHO10	MOVEA.L	OTPTR.L,A6	;IS THERE ROOM IN BUFFER FOR THIS BYTE?
	CMPA.L	OTBUFE,A6	; I.E. IS OTPTR < OTBUFE?
	BLO.S	CHO50		;BRANCH IF YES

	BSR	WRTBUF		;THE BUFFER IS FULL SO WRITE IT TO DISK
	TST.L	ERRLOC		;DID WE GET AN ERROR?
	BNE.S	CHO90		;BRANCH IF YES
	MOVEA.L	OTBUF,A6	;RESET BYTE POINTER TO START OF OUTPUT
				; BUFFER
CHO50	MOVE.B	D0,(A6)+	;STORE THE BYTE IN THE OUTPUT BUFFER
	MOVE.L	A6,OTPTR.L	; BUMP POINTER AND SAVE IT

CHO90	MOVEA.L	(SP)+,A6	;RESTORE A6
	RTS

;-----------------------------------------------------------------------
;CLOSE THE OUTPUT FILE
;
CLOSE	MOVE.L	D0,-(SP)	;SAVE D0

	CMPI.B	#$55,OTFLG	;IS THE OUTPUT FILE OPEN?
	BNE.S	CLO90		;BRANCH IF NOT - JUST EXIT

	MOVEQ	#EOF,D0		;WRITE AN EOF
	BSR.S	CHOUT

	MOVE.L	OTPTR.L,D0	;RESET THE SIZE OF THE OUTPUT BUFFER TO
	SUB.L	OTBUF,D0	; INCLUDE ONLY THE BYTES THAT ARE
				; ACTUALLY STORED IN IT
	BEQ.S	CLO20		;BRANCH IF THE BUFFER IS EMPTY
	ADDI.L	#255,D0		;OTBSIZ := (OTPTR - OTBUF + 255) /256
	LSR.L	#8,D0		
	MOVE.L	D0,OTBSIZ.L

	BSR.S	WRTBUF		;WRITE OUTPUT BUFFER TO DISK
	TST.L	ERRLOC		;DID WE GET AN ERROR?
	BNE.S	CLO90		;BRANCH IF YES

CLO20	MOVE.L	OTBPTR.L,D0	;OTHBLK := OTBPTR
	SUBQ	#1,D0		;?????? CONFLICTING CONVENTIONS ????
	MOVE.L	D0,OTHBLK	;TELL APEX WHERE THE FILE ACTUALLY ENDED
	MOVE.B	#$FF,OTFLG	;INDICATE THAT THE OUTPUT FILE IS CLOSED

CLO90	MOVE.L	(SP)+,D0	;RESTORE D0
	RTS

;-----------------------------------------------------------------------
;RETURN THE ADDRESS OF THE INFORMATION ARRAY IN D0
;
GETINFO	MOVE.L	#INFO,D0
	RTS

INFO	DC.L	START		;STARTING AND ENDING ADDRESSES OF
	DC.L	END		; THIS HANDLER
	DC.L	INFOSTR
INFOSTR	ASCII	'DSKDEV    APR-27-88  Disk sequential byte handler'
	DC.B	0

;-----------------------------------------------------------------------
;WRITE THE OUTPUT BUFFER TO DISK
;
WRTBUF	MOVEM.L	D0/A6,-(SP)	;SAVE REGISTERS

	MOVE.L	OTBPTR.L,D0	;IF OTBPTR +OTBSIZ > OTHBLK+1 THEN ERROR
	ADD.L	OTBSIZ.L,D0	;I.E. ARE WE ATTEMPTING TO WRITE BEYOND
	SUBQ.L	#1,D0		;	???????
	CMP.L	OTHBLK,D0	; THE END OF THE OUTPUT FILE?
	BLS.S	WRTB20		;BRANCH IF NOT
	JSR	VERROR
	ASCII	'12 - WRITE BEYOND OUTPUT FILE'
	DC.B	0
	BRA.S	WRTB90		;EXIT

WRTB20	MOVE.B	OTUNT,UNIT	;PASS ARGUMENTS
	MOVE.L	OTBPTR.L,BLKNO
	MOVE.L	OTBUF,FADDR
	MOVE.L	OTBSIZ.L,NBLKS
	MOVEA.W	#12,A6		;SET FUNCTION CODE TO "WRITE"
	JSR	VUNTHAN		;WRITE BUFFER TO DISK
	TST.L	ERRLOC		;DID WE GET AN ERROR?
	BNE.S	WRTB90		;BRANCH IF YES

	MOVE.L	OTBPTR.L,D0	;OTBPTR := OTBPTR + OTBSIZ
	ADD.L	OTBSIZ.L,D0	;BUMP OUTPUT BLOCK POINTER
	MOVE.L	D0,OTBPTR.L

WRTB90	MOVEM.L	(SP)+,D0/A6	;RESTORE REGISTERS
	RTS

END	EQU	@-1		;END ADDRESS OF THIS HANDLER
	IF	END > START +$33F
	ERROR -- TOO BIG
	ENDIF

;-----------------------------------------------------------------------
;HOOK THIS HANDLER INTO THE DEVICE HANDLER TABLE
;
	ORG	4 *DEVNUM +DEVTBL
	DC.L	DSKDEV

;-----------------------------------------------------------------------
;ENTER FAST I/O ROUTINES INTO LIBRARY TABLE

	ORG	$C00
VCHIN3	JMP	CHIN.L		;CH:= CHIN(3)
VCHOUT3	JMP	CHOUT3.L

	END
---
;ENTER FAST I/O ROUTINES INTO LIBRARY TABLE

	ORG	$C00
VCHIN3	JMP	CHIN.L		;CH:= CHIN(3)
VCHOUT3	JMP	CHOU