
	.Z80
;
;	***********************************************
;	SUBROUTINES TO SUPPORT ALL THE MODULES IN CBIOS
;	***********************************************
;
;
;	This routine transfers control to the
;	I/O driver indicated by the appropriate
;	bits in IOBYTE at address (0003H)
;	and save I/O port address pointer in
;	register IX. Do  LD  C,(IX) to get a data
;	port, LD C,(IX+1) to get a status port,
;	and LD C,(IX+2) to get a number of mask
;	bits from the I/O driver.
;
;	ENTRY (SP) -->  (DEVICE TYPE)
;			(DEVICE 1 INDEX)
;			(DEVICE 2 INDEX)
;			(DEVICE 3 INDEX)
;			(DEVICE 4 INDEX)
;
IODISP:	POP	HL
	PUSH	BC
	LD	A,(HL)		; GET DEVICE TYPE
	LD	D,A		; SAVE IT FOR LATER
	LD	E,A
	OR	A
	LD	A,(IOBYTE)	; GET CURRENT IOBYTE
	JR	Z,IODI20	; IF NO SHIFTING NEEDED
;
IODI10:	RRCA			; ROTATE BYTE UNTIL DEVICE BITS
	DEC	D		; ARE LINED UP WITH BIT #0
	JR	NZ,IODI10
;
IODI20:	AND	03H		; MASK OFF DON'T CARE BITS
	LD	C,A
	RLCA			
	ADD	A,C		;IOBYTE * 3 
;
	PUSH	AF
	LD	A,E
	ADD	A,A
	LD	B,A
	ADD	A,A
	ADD	A,B
	LD	E,A		;E = DEVICE TYPE*6 
	POP	AF
;
	LD	IX,IOPTAB	;IO PORT ADDRESS TABLE
	ADD	IX,DE		;OFFSET TO APPROPRIATE DEVICE TYPE
	LD	E,A
	ADD	IX,DE		;OFFSET ACCORDING TO IOBYTE
	INC	HL		;ADDRESS OF DEVICE 1 DRIVER
	LD	E,C
	ADD	HL,DE
	LD	E,(HL)		; GET DISPATCH ADDRESS INTO DE
	LD	HL,DRIVER
	ADD	HL,DE
	POP	BC		; RESTORE BC
	LD	E,(HL)
	INC	HL
	LD	D,(HL)
	EX	DE,HL
	JP	(HL)		; AND GO TO I/O ROUTINE
;
;	KEYBOARD INTERRUPT SERVICE ROUTINE
;
INTKEY:	DI			; DISABLE SYSTEM INTERRUPT
	LD	(KEYSTK),SP
	LD	SP,KB_LOCSTK	; SET LOCAL STACK POINTER
;
				; SAVE AF, BC REGISTERS IN LOCAL STACK
	PUSH	BC
	PUSH	AF
;
	IN	A,(KBDDP)	; GET A BYTE OF CHAR
	LD	B,A		; STORE IT FOR LATER
	BIT	7,A		; IS KEY RELEASED?
	JR	Z,CHK80		; YES, NO BELL SOUND NEEDED
	CPL			; COMPLEMENT KEY DATA
	CP	29		; IS KEY CONTROL KEY
	JR	Z,CHK80		; IF SO, NO BELL SOUND NEEDED
	CP	42		; IS KEY LEFT OR RIGHT SHIFT
	JR	Z,CHK80		; IF SO, NO BELL SOUND NEEDED
	CP	54
	JR	Z,CHK80		; IS KEY ALT?
	CP	56		; IF SO, NO BELL SOUND NEEDED
	JR	Z,CHK80
	LD	A,(KEYCLK)	; IS KEYCLICK ON?
	OR	A
	JR	NZ,CHK80	; NO,SKIP BELL SOUND ROUTINE
	LD	A,0F0H		; SET FREQUENCY TO 0F0H
BELAGAN:
	OUT	(PRNTDP),A	; NOW, RING THE BELL
;	
;	CHECK KEYBOARD INPUT DATA IS LESS THEN 80H.		****8/9/83***
;	IF SO, DISREGARD KEY BOARD DISABLE.
;	IF NOT, CHECK KEY BOARD DISABLE.
;
CHK80:	LD	A,B
	IF	TS803 OR TS803H OR TS800
	CP	80H
	JR	C,KB_ENABLE
	ELSE
	CP	1		; IS KEY ESC?
	JR	Z,CHK_KYB	; YES, CHECK KYB DISABLE
	CP	59		; IS KEY BELOW MATRIX 59?
	JR	C,KB_ENABLE	; YES, KYB DISABLE IS UNAFFECTED.
	ENDIF
;********							****6/7/83***
;	CHECK KEYBOARD INPUT DISABLE FLAG
;	BECAUSE ALPHA DRIVER ACTIVE.
;********
CHK_KYB:
	LD	A,(KB_DISABLE)
	OR	A
	JR	NZ,EXITKX	; IF KBD DISABLE THEN IGNORE INPUT KEYS.
				; 				****6/7/83***
				; SAVE ALL REGISTERS IN LOCAL STACK
KB_ENABLE:
	PUSH	IX	
	PUSH	IY
	PUSH	HL
	PUSH	DE
;	
;	NOTE:  TO IMPROVE KEYBOARD TYPE AHEAD "KEYBOARD FILTER"
;	       MUST RESIDE IN COMMON MEMORY INSTEAD OF PAGE #0
;
;	CALL KEYBOARD FILTER RESIDED IN PAGE 0
;	   ENTRY: A  = CURRENT KEY
;		  D  = CONSOLE BUFFER SIZE	
;	          HL = POINTER TO THE BEGINNING OF CONSOLE BUFFER
;	
	LD	A,B		; SET A = KEY
	LD	HL,CONBUF	; SET HL = CONSOLE BUFFER POINTER
	LD	D,BUFSIZ	; SET D = CONSOLE BUFFER SIZE
	LD	B,0
	LD	C,BANKSW
	OUT	(C),B		; SWITCH MEMORY BANK TO 0 
	CALL	KBDFTR		; CALL KEYBOARD FILTER
	LD	A,(C_BANK)
	OUT	(BANKSW),A	; SWITCH BACK TO MEMORY BANK 1

	POP	DE		; RESTORE ALL REGISTERS
	POP	HL
	POP	IY
	POP	IX
EXITKX:	
;	XOR	A		; SET FLAG THAT NEXT BYTE IS 1ST BYTE
;
;EXITKY:	LD	(BYTFLG),A	; SET BYTE-ORDER FLAG
;
	POP	AF		; RESTORE AF, BC REGISTERS FROM LOCAL STACK
	POP	BC
;
	LD	SP,(KEYSTK)     ; RESTORE STACK POINTER
;
	EI			; ENABLE SYSTEM INTERRUPT
	RETI	
;
;KEYSTK:	DEFS	2		; USER STACK POINTER 
;	DEFS	32		; 16 LEVELS OF STACK AREA
;KB_LOCSTK EQU	$		; KEYBOARD STACK START ADDRESS
;
;	TIMER INTERRUPT SERVICE ROUTINE
;       Keeps time and date.
;	Provides capability to set and read time and date.
;	Shuts off floppy disk motor after 5 sec of no access.
;
TCOUNT:	DI
	LD	(TUSTACK),SP	; SAVE USER STACK
	LD	SP,LSTACK	; SET STACK POINTER TO LOCAL
	PUSH	AF
	PUSH	HL
;
	LD	HL,(MSECNT)
	INC	HL
	LD	(MSECNT),HL	; INCREMENT 16-BIT MS COUNTER	
;
	LD	HL,CLOCK
	CALL	TCOUN4		; COUNT 1/100 SEC.
	JP	NZ,TEXIT	; SKIP IF NOT OVERFLOW 99 (BCD)
;
	IF	XONDRV
	LD	A,(XOFFTM)	; GET XOFF TIMER COUNTER
	OR	A
	JR	Z,TCOUN0	; CHANGE TO XON-MODE
	INC	A		; INCREMENT COUNTER
	LD	(XOFFTM),A	; IF TIMER EXPIRED
	JR	NZ,TCOUN0	; THEN
	LD	A,0FFH		; CHANEGE TO XON-MODE
	LD	(XONOFF),A
	ENDIF
;	
TCOUN0:	CALL	FLOPOFF		; TURN OFF FLOPPY DISK?
;
; 	ELSE RESET PRECOUNTER AND ADD 1 TO SEC.
;
	CALL	TCOUN1
	CP	060H		; CHECK FOR SEC. OVERFLOW
	JP	NZ,TEXIT	; SKIP IF NOT
;
	CALL	TCOUN1		; ADD 1 TO MINUTE COUNT
	CP	060H
	JR	NZ,TEXIT	; SKIP IF NOT OVERFLOW
;
; 	ELSE RESET MINUTE COUNT AND ADD 1 TO HOUR
;
	CALL	TCOUN1
	CP	024H		; CHECK OVERFLOW
	JR	NZ,TEXIT
;
	CALL	TCOUN1		; RESET HOUR TO 0 AND ADD 1 TO DATE COUNT
	CP	029H		; CHECK DATE = 29
	JR	C,TEXIT		; SKIP IF DATE < 29
;
	CALL	NC,CHKM28	; IF DATE >= 29 THEN CHECK MONTH = FEB
	JR	Z,TCOUN3	; SKIP IF FEB 29TH
;
	LD	A,(HL)		; CHECK DATE = 31
	CP	031H
	CALL	NC,CHKM30	; IF DATE >= 30 THEN CHECK MONTH=4,6,9,11?
	JR	Z,TCOUN3	; SKIP IF MONTH = 4,6,9,11
;
	LD	A,(HL)
	CP	032H		; CHECK DATE = 32
	JR	C,TEXIT
;
; 	ADJUST MONTH AND RESET SET DATE = 1
;
TCOUN3: LD	(HL),1		; RESET DATE = 1
	CALL	TCOUN2		; MONTH = MONTH + 1
	CP	013H
	JR	C,TEXIT		; SKIP IF MONTH < 13
	LD	(HL),1		; RESET MONTH = 1
	CALL 	TCOUN2		; AND ADD 1 TO YEAR
	JR	NZ,TEXIT	; SKIP IF LSB OF YEAR > 0
	CALL	TCOUN2		; ELSE ADD 1 TO MSB OF YEAR COUNT
TEXIT:
	POP	HL
	POP	AF
	LD	SP,(TUSTACK)	; RESTORE USER STACK
	EI
	RETI
;
TCOUN1:	LD	(HL),0		; RESET BCD TO 0
;
TCOUN2:	INC	HL
;
TCOUN4:	LD	A,(HL)		; ADD 1 TO NEXT COUNT
	ADD	A,1
	DAA
	LD	(HL),A
	RET
;
; 	CHECK MONTH = 2
; 	RETURN Z = 1 IF YES, ELSE Z = 0
;
CHKM28:	INC	HL
	LD	A,(HL)
	DEC	HL
	CP	2
	RET
;
; 	CHECK MONTH = 4,6,9 OR 11
; 	RETURN Z = 1, ELSE Z = 0
;
CHKM30:	INC	HL
	LD	A,(HL)
	DEC	HL
	CP	4
	RET	Z
	CP	6
	RET	Z
	CP	9
	RET	Z
	CP	011H
	RET
;
; 	DATE AND TIME INTERFACE ROUTINE
; 	ENTRY: READ CURRENT DATE AND TIME
;              C-REG = 0 AND DE = DATE AND TIME BUFFER POINTER
;	       SET CURRENT DATE AND TIME
;              C-REG = 1 AND DE = BUFFER POINTER
; 	RETURN: CURRENT DATE AND TIME IN USER BUFFER
;         	FORMAT: MM?DD?YYYY?HH?MM?SS?NN
;
TOD:	DEC	C
	JR	Z,SETOD		; SET CURRENT DATE AND TIME
;
RDTOD:	LD	HL,MONTH
	CALL	BCDASC		; CONVERT BCD TO ASCII AND SAVE INTO (DE)
	INC	DE
	DEC	HL		; ADDRESS DATE
	CALL	BCDASC
	INC	DE
	INC	HL		; ADDRESS YEAR
	INC	HL
	INC	HL
	CALL	BCDASC		; SAVE MSB OF YEAR
	DEC	HL		; ADDRESS LSB OF YEAR
	CALL	BCDASC		; SAVE LSB OF YEAR
;
	INC	DE		; SKIP FILLER
	LD	HL,HOUR
	CALL	BCDASC		; SAVE HOUR
	INC	DE
	DEC	HL
	CALL	BCDASC		; SAVE MINUTE
	INC	DE
	DEC	HL
	CALL	BCDASC		; SAVE SECOND
	INC	DE
	DEC	HL
	CALL	BCDASC		; SAVE 1/100 SEC
	LD	A,(TINITF)	; SET A = INITIALIZE FLAG
	RET
;
; 	SET CURRENT DATE AND TIME
;
SETOD:	LD	HL,MONTH
	CALL	ASCBCD
	LD	(HL),A		; SET MONTH
	INC	DE
	DEC	HL
	CALL	ASCBCD
	LD	(HL),A		; SET DATE
	INC	DE
	LD	HL,YEAR+1
	CALL	ASCBCD
	LD	(HL),A		; SET YEAR MSB
	DEC	HL
	CALL	ASCBCD		; SET YEAR LSB
	LD	(HL),A
;
	INC	DE
	LD	HL,HOUR
	CALL	ASCBCD
	LD	(HL),A		; SET HOUR
	DEC	HL
	INC	DE
	CALL	ASCBCD
	LD	(HL),A		; SET MINUTE
	DEC	HL
	INC	DE
	CALL	ASCBCD
	LD	(HL),A		; SET SECOND
	DEC	HL
	XOR	A
	LD	(HL),A		; RESET 1/100 SEC COUNT TO 0
	LD	(TINITF),A	; SET DATE AND TIME INITIALIZE FLAG
	RET
;
;	CONVERT 1 BYTE BCD TO 2 BYTE ASCII
; 	AND SAVE IT INTO (DE)
;
BCDASC:
	LD	A,(HL)
	RRA
	RRA
	RRA
	RRA
	CALL	BCDAS1
	LD	A,(HL)
BCDAS1:
	AND	0FH
	OR	'0'
	LD	(DE),A
	INC	DE
	RET
;
;	CONVERT 2 BYTE ASII DIGIT TO 1 BYTE BCD
;
ASCBCD:
	LD	A,(DE)
	RLA
	RLA
	RLA
	RLA
	AND	0F0H
	LD	C,A		; SAVE MSN TO C-REG
	INC	DE
	LD	A,(DE)
	AND	0FH		; GET LSN
	OR	C		; PACK IT
	INC	DE
	RET
;
;	TURN FLOPPY DRIVES MOTOR OFF?
;
FLOPOFF:
	LD	A,(FDTIME)	; MOTOR OFF DISABLE
	OR	A
	RET	Z
	DEC	A		; TIME = TIME - 1
	LD	(FDTIME),A
	RET	NZ		; EXIT IF NOT TIMEOUT
	LD 	A,11110110B	; SET MOTOR OFF 
	OUT	(DSELOP),A	; ELSE RESET DRIVE SELECT AND TURN MOTOR OFF
	XOR	A
	LD	(FDMOT),A	; SET MOTOR OFF INDICATION
	RET
;
;	THIS ROUTINE SET UP TO CALL ROUTINES RESIDES IN EPROM
;	EXCEPTS:	IX:  ADDRESS OF JUMP ROUNTINE RESIDES
;
ROMSW:
	DI
	LD	(USER_STACK),SP	; SAVE STACK POINTER IN IY REG
	LD	SP,LOCSTK	; SWITCH TO LOCAL STACK
	PUSH	AF		;
	XOR	A
	OUT	(BANKSW),A	; SWITCH BANK TO ZERO
	LD	(C_BANK),A
	POP	AF
	LD	IY,RETADR	; GET RETURN ADDRESS
	PUSH	IY
	PUSH	BC		; SAVE JUMP TABLE ADDRESS
	EI			; ***** ENABLE INTERRUPT *****
	RET			; GO TO JUMP TABLE ADDRESS
RETADR:
	DI				
	PUSH	AF
	LD	A,1
	OUT	(BANKSW),A	; RESTORE BANK TO 1
	LD	(C_BANK),A	; AND RESTORE STACK.
	POP	AF
	LD	SP,(USER_STACK)
	EI
	RET
;
;	RETURN DE=ADDRESS OF INTERRUPT VECTOR TABLE
;	FOR USER PROGRAM WANT TO USE 16-BIT COUNTER
;	THAT INCREMENT AT EVERY 10 MS THEN
;	DE-2=LSB COUNT, DE-1=MSB COUNT
;
INTADD:	LD	DE,INTVEC	; SET DE=INTERRUPT TABLE ADDRESS
	RET 
;
;	FILL LOGICAL DRIVE, SECTOR, TRACK NUMBER 
; 	IN ERROR TABLE AND REPORT TO OPERATOR
;
ERRHST:	LD	A,(HSTDSK)	; CURRENT HOST DISK
	ADD	A,41H		; MAKE IT ASCII CHARACTER
	LD	HL,VDRV		; GET DRIVE TABLE ADDRESS
	LD	(HL),A		; STORE IT IN TABLE

	LD	DE,(HSTTRK)	; GET TRACK NUMBER
	LD	HL,VTRK		; GET TRACK TABLE ADDRESS
	CALL	CVD3		; CONVERT IT AS DECIMAL

	LD	A,(HSTSEC)	; CURRENT SECTOR
	LD	E,A
	LD	D,0		; DE = SECTOR NUMBER
	LD	HL,VSEC		; GET SECTOR TABLE ADDRESS
	CALL	CVD2
	LD	HL,VTAB		; VARIABLE TABLE RECORDED
	CALL	PRNT			
	RET
;
;	DECIMAL CONVERSION SUBROUTINE
;
CVD3:	
	LD	BC,CVD3ROM
	JR	ROMSW
CVD2:	
	LD	BC,CVD2ROM
	JR	ROMSW
;
;	PRINT ROUTINE
;
PRNT:	LD	A,(HL)		; PRINT CHAR
	INC	HL		; FOR NEXT CHAR
	OR	A
	RET	Z		; RIF DONE
	LD	C,A
	PUSH	HL
	CALL	CONOUT		; PRINT A CHAR
	POP	HL
	JR	PRNT		; DO NEXT CHAR
;
; 	THIS ROUTINE CONVERTS HEX CODE INTO ASCII AND FILL OUT THE TABLE
;
FTAB:	
	LD	BC,FTABROM
	JP	ROMSW
;
	IF	USRCPM
CVHEX:	RRCA
	RRCA
	RRCA
	RRCA
;
;	HEX INTO ASCII ROUTINE
;
GHEX:	AND	0FH		; STRIP HIGH 4 BITS
	CP	10		; NUMERIC?
	JR	C,G10		; YES, SKIP FOR NUMERIC
	ADD	A,7		; ADD 40
G10:	ADD	A,'0'		; ADD 30
	RET
	ENDIF
;
;	ENTRY FOR APPLICATION PROGRAM TO GRAPHIC DRIVER
;  	          CALL GRAPHIC DRIVER RESIDED 
;		 IN MEMORY BANK 0 USING RST 5.
;
GRPDRV:	DI			; DISABLE SYSTEM INTERRUPT
	LD	IX,0
	ADD	IX,SP		; SAVE CURRENT STACK POINTER
	LD	SP,LOCSTK	; SET LOCAL STACK POINTER
	LD	A,0
	OUT	(BANKSW),A	; SWITCH TO MEM BANK 0
	PUSH	IX
	CALL	GROUT		; CALL GRAPHIC DRIVER
	POP	IX
	LD	A,1
	OUT	(BANKSW),A	; SWITCH BACK TO MEM BANK 1
	LD	SP,IX		; RESTORE STACK POINTER
	EI			; ENABLE SYSTEM INTERRUPT
	RET
;
;
;	ROUTINE TO STORE CHARACTER ON KEY BOARD BUFFER
;
STORKB:
	LD	HL,CONBUF+1
	LD	A,(HL)
	INC	A
	CP	BUFSIZ
	JR	NZ,SKIPP
	XOR	A
SKIPP:	DEC	HL
	CP	(HL)
	RET	Z
	INC	HL
	LD	E,(HL)
	LD	(HL),A
	LD	D,0
	INC	HL
	ADD	HL,DE
	LD	(HL),B
	RET
;
;
	IF	USRCPM
;
; 	          ipc transfer logic
;		hl has address of data 
;		b  has length of transfer 
;
pnxo:	push	hl
	push	bc
;
	ld	hl,txtab	;get sdlc txmt table
	call	prtini		;initialize sdlc txmt for sio
	xor	a
	out	(sioatc),a	;sio auto-wait on
;
	pop	bc
	pop	hl	
	ld	c,b		;modify hl to end of buffer	
	ld	b,0
	add	hl,bc
	dec	hl
	ld	(dmaddr),hl
	ld	a,c		
	ld	(dmalng),a
	ld	a,retries	;store number of retries at retrycnt
	ld	(retrycnt),a
	ld	a,5		;assert rts
	out	(status),a
	ld	a,xmtlng or 2
	out	(status),a
ctslp:
	ld	a,10h
	out	(status),a
	in	a,(status)
	and	20h
	jr	z,ctslp		;WAIT IF MMMOST BUSY
;
	ld	a,10h		;check cts again
	out	(status),a
	in	a,(status)
	and	20h
	jr	z,ctslp		;id false then wait
;
tryagain:
	di			;disable system interrupt
	ld	a,5		;clear rts
	out	(status),a
	ld	a,xmtlng
	out	(status),a
	ld	b,62		;200 us delay
trylup:	djnz	trylup
	ld	a,1		;enable sio wait/ready line
	out	(status),a
	ld	a,xmtrdy
	out	(status),a
;
	ld	a,80h		;reset crc checker
	out	(status),a
	ld	hl,(dmaddr)	;set up for initial outd
	ld	c,data
	ld	a,(dmalng)
	ld	b,a
	outd
	ld	a,0c0h		;set up to clear underun latch
	out	(status),a
	otdr
	jp	morelp
CTSLP4:
	ld	a,(retrycnt) 
	dec	a
	jp	z,erroret
	ld	(retrycnt),a
;
	ld	a,5
	out	(status),a
	ld	a,xmtlng or 2 
	out	(status),a
	ld	b,33		;set synch. window (.5 ms)
ctslp5:	dec	b
	jp	z,tryagain	;skip if time out
	ld	a,10h
	out	(status),a
	in	a,(status)	;make sure receiver still in retry loop
	and	20h
	jp	nz,ctslp5
	ld	a,10h
	out	(status),a
	in	a,(status)
	and	20h
	jr	nz,ctslp5
	jp	erroret		;else exit txmt with error 
;
;	WAIT UNTIL TXMIT END OF BLOCK
;
morelp:	
	in	a,(status)	;--2.75
	and	40h		;--1.75
	jr	z,morelp	;WAIT IF NOT EOB --1.75
;
;	WAIT FOR RCV. "ACK" BY DROPPING CTS SIGNAL
;	WITHIN 4MS AFTER TXMIT EOB
;
	ld	b,0
CTSLP3:
	dec	b
	jr	z,CTSLP4	;if timeout then do error retry
	ld	a,10h		;check cts
	out	(status),a
	in	a,(status)
	and	20h		;cts = true?
	jr	nz,ctslp3	;if cts = true then loop more
;
	LD	A,10H
	OUT	(STATUS),A
	IN	a,(STATUS)	;double checl CTS = FALSE?
	AND	20H
	JR	NZ,CTSLP3	;WAIT MORE IF CTS = TRUE
;
ERROR0:
	LD	B,0		;if here then okay
ERROR1:
	LD	A,1
	OUT	(STATUS),A	;RESET SIO WAIT/READY LINE
	LD	A,40H
	OUT	(STATUS),A
	LD	A,35H		;RESET ERROR FLAGS,SELECT REG #5
	OUT	(STATUS),A
	LD	A,XMTLNG	;SHUT OFF DTR AND RTS
	OUT	(STATUS),A
	LD	A,B
	ei			;enable system interrupt
	ret
;
erroret:
	LD	B,4		;RETURN WITH ERROR CODE IN A-REG
	JR	ERROR1
;
;	  sdlc receiver routine 
;	accept:  hl = buffer pointer 
;		 b  = size 
;	return:  a  = 0  if no error 
;		 a  = 4  if receive error 
;
pnxi:	LD	C,B
	LD	B,0
	LD	A,C
	LD	(DMARXL),A	;SET RCV. INTO DMA TABLE
	ADD	HL,BC		;FIND END OF BUFFER ADDRESS
	DEC	HL
	LD	(DMARXA),HL	;SAVE BUFFER ADDRESS TO DMA TABLE
;
	ld	a,retries-1	;initialize retry count
	ld	(irtrycnt),a
ictslp:	ld	a,10h		;WAIT FOR CTS (HOST POLLING)
	out	(status),a	
	in	a,(status)
	and	20h
	jr	z,ictslp
	LD	A,10H
	OUT	(STATUS),A
	IN	A,(STATUS)
	AND	20H		;CTS = TRUE
	JR	Z,ICTSLP	;WAIT IF NOT
;
; initialize sio for receive: current hl = rxtab pointer
; 
again:	di			;disable system interrupt
	ld	hl,rxtab
	call	prtini
	ld	hl,(dmarxa)
	ld	c,data
	LD	A,(DMARXL)
	LD	E,A
;
loopcb:	in	a,(status)
	and	01
	jr	z,pnxiw0
	in	a,(data)
	jp	loopcb
;
pnxiw0:	ld	b,100		;set b = time out(1ms)
PNXIW:	DJNZ	PNXIW1
	JP	PNXIW2
PNXIW1:
	IN	A,(STATUS)
	RRCA
	JR	NC,PNXIW	;WAIT IF RCV. NOT READY
;
	LD	B,E
;
	INDR

	LD	B,12		;DELAY FOR 40US FOR SIO TO RCV. CRCC AND FLAG
PNXIW4:
	DJNZ	PNXIW4
	IN	A,(DATA)	;READ IN FIRST CRCC BYTE
	NOP
	IN	A,(DATA)	;READ IN SECOND CRCC BYTE
	NOP
;
	IN	A,(STATUS)	;CHECK SIO RCV. STATUS
	AND	080H		;RCV. ABORT?
	JR	NZ,PNXIW2	;YES, THEN BAD XFER TRY AGAIN
;
	LD	A,1		;CHECK CRC, OVERUN ERROR
	OUT	(STATUS),A
	IN	A,(STATUS)
	BIT	7,A
	JR	Z,PNXIW2
	AND	60H
	JP	Z,ERROR0	;NO ERROR THEN EXIT WITH B = 0
;
PNXIW2:
	LD	B,200		;B = (3MS) TIMEOUT FOR SYNCH. RETRY
PNXIW6:
	DEC	B
	JP	Z,PNXIW8
	LD	A,10H
	OUT	(STATUS),A
	IN	A,(STATUS)
	AND	20H		;WAIT FOR CTS ACTIVE
	JP	Z,PNXIW6
	LD	A,10H
	OUT	(STATUS),A
	IN	A,(STATUS)	;CHECK CTS ACTIVE AGAIN
	AND	20H
	JR	Z,PNXIW6	;WAIT IF NOT ACTIVE
;
;	CHECK RETRY MORE ?
;
PNXIW8:
	ld	a,(irtrycnt)	;decrement retry count	
	dec	a
	JP	Z,ERRORET	;SKIP IF NO MORE RETRY
	ld	(irtrycnt),a
	jp	again
;
;	sdlc transmitter initialization for sio
;
txtab:	defb	status
	defb	txtabs
txtab1:	db	chnrst
	db	4,sdlcmd	
	db	6,global
	db	7,flag
	db	3,rcvlng
	db	5,xmtlng
	db	1,xmtrdy
txtabs	equ	$-txtab1
;
;	sdlc receiver initialization for sio 
;
rxtab:	defb	status
	defb	rxtabs
rxtab1:	defb	7
	defb	7eh		;sdlc flag
	defb	11h		;RESET EXT/STATUS INTERRUPT
	defb	0a0h		;ENABLE WAIT/RECEIVE
	defb	75h		;CRC, ERROR RESET, ADDRESS REG #5
	defb	xmtlng or 2	;SET RTS, TX8B, TX ENABLE, TX CRCC ENABLE
	defb	3		;POINTER #3
	defb	0d9h		;RX8B, ENTER HUNT, CRCC ENABLE, RX ENABLE
rxtabs	equ	$-rxtab1
;
RETRYCNT: defs	1		;RETRY COUNT
IRTRYCNT: defs  1 
DMALNG:	defs	1 		;FILLED IN TRANSFER LENGTH	
DMARXL:	defs	1 		;RECEIVE BLOCK LENGTH(LSB)
DMARXA: defs	2 		;END ADDRESS OF RECEIVE BLOCK
DMADDR: defs	2 		;DMA BUFFER ADDRESS
;*
;*	M M M O S T   2 . 0 
;*
;       SET UP BDOS INTERCEPT ADDRESS IN BDOS AND CLEAR OPEN FILE TABLE
;
.8080
BDOSSET:LXI	H,BIOSDOS	;PUT IN BDOS INTERCEPT ADDRESS
	SHLD	BDOS+1		;INTO INITIAL BDOS JUMP
	LXI	H,BDOSTRT	;PUT REAL BDOS JUMP ADDRESS IN REALDOS
	SHLD	REALDOS
	MVI	A,TABLEN	;RESET DRIVE BYTE TO 80H (EMPTY)
	LXI	H,FILETAB	;START OF FILE TABLE
	LXI	D,14		;LENGTH OF TABLE ENTRIES
ZEROLP:	MVI	M,80H
	DAD	D
	DCR	A
	JNZ	ZEROLP
	MVI	M,0FFH	;END OF TABLE FLAG
	RET
;
;	*END MMMOST 2.0
;
; 	WARM BOOT REQUEST BLOCK
;
WRQBLK:	DB	SOR
WRQCOD:	DB	IPL
	DB	USRPROM
	DB	0
	DB	2BH	;REQUEST XFER LENGTH.-2 CP/M SECTORS
WRECNO:	DS	1
	DS	4
WCKSM:	DS	1
;
;	PRNTERR ROUTINE WILL PRINT ALL ERROR MESSAGES FROM MMMOST 2.0
;	IT EXPECTS REGISTER B TO HAVE A ERROR PRINTING CODE AND C TO =0
;	FOR BDOS ERR, 1 FOR BIOS READ ERR, 2 FOR BIOS WRITE ERR AND 3 FOR
;	BIOS SELECT ERROR
;	THE ROUTINE WILL PRINT MAX OF THREE LINES OF CODE BASED ON BITS OF
;	REG. B AS DESCRIBED IN CODE
;
PRNTERR:MOV	A,B		;RETURN IF B=0 (PRINT NOTHING)
	ORA	A
	RZ
	PUSH	B		;SAVE ERROR CODES ON STACK
	CALL	PCRLF		;PRINT A CARRIAGE RETURN, LINE FEED
	POP	B
	PUSH	B
	MOV	A,B
	ANI	70H		;BITS D6-D4 => BDOS ERROR PRINTING
	JZ	NOP1	 	;IF 0 NO PSEUDO BDOS ERROR MESSAGES
	LXI	H,M11		;IF <>0 THEN PRINT "BDOS ERROR ON "
	CALL	PRNT
	CALL	PRTDK		;PRINT "(DRIVE)"
	LXI	H,M11TAB	;GET ADDRESS OF SECOND MESSAGE TABLE 
	POP	B
	PUSH	B
	MOV	A,B		;PUT OFFSET INTO A 
	ANI	30H		;MASK OFF IRRELEVANT BITS
	RRC			;ROTATE INTO LOW ORDER
	RRC	
	RRC
	RRC
	CALL	PIMSG1		;CALL ROUTINE TO PRINT ON INDEX
				;PRINT "BAD SECTOR","R/O",ETC.
	CALL	PCRLF		;PRINT CR,LF
NOP1:	POP	B		;CHECK IF PRINT SECOND ERROR LINE
	PUSH	B
	MOV	A,B
	ORA	A
	JP	NOP2		;IF MSB=0 THEN DON'T PRINT
	MOV	A,C
	ORA	A		;CHECK IF BIOS OR BDOS
	JZ	PBDOSE		;IF ZERO THEN BDOS ERROR
	LXI	H,M21A		;PRINT "BIOS "
	CALL	PRNT
	POP	B
	PUSH	B		;PRINT "READ","WRITE" OR "SELECT"
	LXI	H,M22ATAB
	MOV	A,C
	CALL	PIMSG		;USING INDEXED PRINT ROUTINE
	LXI	H,M23A		;PRINT "ERROR ON DRV="
	CALL	PRNT
	CALL	PRTDK		;PRINT "(DISK)"
	LXI	H,M24A		;PRINT "; TRK="
	CALL	PRNT
	LDA	TRK16+1		;PRINT MSB OF TRACK NO.
	CALL	PBYTE
	LDA	TRK16		;PRINT LSB OF TRACK NO.
	CALL	PBYTE
	LXI	H,M25A		;PRINT "; SCTR="
	CALL	PRNT
	LDA	SECT+1		;PRINT MSB OF SECTOR
	CALL	PBYTE
	LDA	SECT		;PRINT LSB OF SECTOR
	CALL	PBYTE
	POP	B		;CHECK IF WRITE ERROR
	PUSH	B
	MOV	A,C
	CPI	2
	JNZ	NOPWRT	 
	LXI	H,M26A		;IF SO PRINT "; WRT TYPE="
	CALL	PRNT
	LDA	WRTYPE		;PRINT WRITE TYPE
	CALL	PBYTE
NOPWRT:	LXI	H,M27AB		;PRINT "; RTN CODE="
	CALL	PRNT
	LDA	STABUF		
	JMP	ENDP2		;PRINT RETURN CODE THEN CR,LF
PBDOSE:	LXI	H,M21B		;PRINT "BDOS ERROR ON FUNC="
	CALL	PRNT
	LDA	BDOSFUN		;PRINT CURRENT BDOS FUNCTION
	CALL	PBYTE
	LXI	H,M22B		;PRINT "; DRV="
	CALL	PRNT
	LDA	LOGDRV
	CALL	PRTDK2		;PRINT DISK OF ERROR
	LXI	H,M23B		;PRINT "; FILE="
	CALL	PRNT
	LHLD	FCBA		;PRINT FILE NAME FROM FCB
	INX	H
	MVI	B,11
PFCBLP:	MOV	C,M
	PUSH	B
	PUSH	H
	CALL	CONOUT
	POP	H
	POP	B
	INX	H
	DCR	B
	JNZ	PFCBLP
	LXI	H,M27AB		;PRINT "; RTN CODE="
	CALL	PRNT
	LDA	RTNCODE	
ENDP2:	CALL	PBYTE		;PRINT RETURN CODE
	CALL	PCRLF
NOP2:	POP	B		;CHECK IF MMMOST ERROR CODE
	MOV	A,B
	ANI	0FH		;LOW ORDER 4 BITS = MMMOST ERROR
	JZ	PEXIT
	LXI	H,M3TAB		;USE INDEX PRINT ROUTINE TO PRINT
	CALL	PIMSG
PEXIT:	CALL	PCRLF
	RET
;
;	PCRLF ROUTINE SIMPLE OUTPUTS A CARRIAGE RETURN, LINE FEED
;
PCRLF:	MVI	C,0DH		;OUTPUT CR
	CALL	CONOUT
	MVI	C,0AH		;OUTPUT LF
	JMP	CONOUT
;
;	PRTDRV ROUTINE WILL PRINT OUT LETTER OF CURRENTLY SELECTED DRIVE
;
PRTDK:	LDA	SELDRV		;GET DISK NUMBER
PRTDK2:	ADI	'A'		;CONVERT TO LETTER
	MOV	C,A
	JMP	CONOUT		;PRINT IT
; 
;	PIMSG ROUTINE USES THE ACCUMLATOR AS INDEX INTO A TABLE WHOSE
;	BASE IS GIVEN IN HL, THE ADDRESS STORED IN THE TABLE LOCATION
;	THEN POINTS TO A MESSAGE TO BE PRINTED BY PRNT
;
PIMSG:	SUI	1		;OFFSET RELATIVE ZERO
PIMSG1:	ADD	A		;TURN INDEX INTO OFFSET
	ADD	L		;ADD TO HL
	MOV	L,A
	MVI	A,0
	ADC	H
	MOV	H,A
	MOV	E,M		;GET ADDRESS STORED IN TABLE
	INX	H
	MOV	D,M	  		
	XCHG			;HL NOW POINTS TO MESSAGE TO PRINT
	JMP	PRNT
;
;	PBYTE ROUTINE SIMPLY PRINTS THE HEX VALUE 
;	WHICH IS IN THE ACCUMULATOR
;
.Z80
PBYTE:	PUSH	AF
	CALL	CVHEX		;CONVERT HEX FOR MSD
	LD	C,A
	CALL  	CONOUT		;PRINT MSD
	POP	AF
	CALL	GHEX		;CONVERT HEX FOR LSD
	LD	C,A
	JP	CONOUT		;PRINT LSD
.8080
;*
;* 	END MMMOST 2.0
;*
;	SETUP ERROR RETRY COUNT FOR READ/WRITE ROUTINES
;
SETERRC:
	MVI	A,RWRETRIES
	STA	ECOUNT
	RET
;
;	DECREMENT ERROR RETRY COUNT
;	RETURN Z-FLAG = TRUE IF COUNT = 0
;		Z-FLAG = FALSE IF COUNT > 0
;
DECERRC:
	LDA	ECOUNT
	DCR	A
	STA	ECOUNT
	RET
;
;	BREAKPOINT A PRINT FILE
;
BRKPT:	CALL	FORCL		;PUT FIRST BREAKPOINT PRINT	MMMOST2.0
;
REQBRK:	MVI	A,BRKCD		;NOW REQUEST BREAKPOINT
	STA	IRQCOD
;
	LDA	IOBYTE
	RLC			;ROTATE LOGICAL LIST 
	RLC			;DEVICE BITS TO BITS #0-#1
	STA	WRTYPE		;PASS THE CURRENT I/O BYTE
;
	LXI	H,IRQBLK
	MVI	B,10
	CALL	PNXO		;BREAK POINT DONE
	RET			;FROM BREAKPOINT
;
;*
;*	M M M O S T   2 . 0
;*
;
;	THIS CODE WILL INTERCEPT SOME BDOS CALLS MADE ON DRIVES CLASSIFIED IN
;	DRVTAB AT THE END ON BIOS.  IF THE CALL IS NOT ONE OF THOSE INDICATED
;	OR IS TO A DRIVE NOT INDICATED CONTROL IS PASSED TO THE LOCAL BDOS.
;	OTHERWISE, CONTROL IS PASSED TO THE SERVICE PROCESSOR BDOS THROUGH 
;	MMMOST
;
BIOSDOS:
	PUSH	H
.Z80
	LD	(USTACK),SP	;SAVE USER'S STACK POINTER
.8080
	LXI	SP,TOS
	PUSH	D
	PUSH	B
	PUSH	PSW
	MOV	A,C		;CHECK CALL
	STA	CURBFNC		;STORE OFF CURRENT FUNCTION #
	CPI	41		;CHECK IF IN TABLE
	JC	OKFUNC
ENTRDOS:POP	PSW		;IF FUNC. OVER TABLE THEN CALL LOCAL BDOS
	POP	B
	POP	D
	LHLD	USTACK
	SPHL
	LHLD	REALDOS		;GET JUMP ADDRESS
	XTHL
	RET
OKFUNC:	STA	BDOSFUN
	LXI	H,BDOSTAB  	;CHECK IF THIS IF FUCTION IS INTERCEPTED
	ADD	L
	MOV	L,A
	MVI	A,0
	ADC	H
	MOV	H,A
	MOV	A,M	;LOAD ACTIVITY TABLE BYTE, BIT 0=1 => INTERCEPT
	STA	CURFNCA
	ANI	1
	JZ	ENTRDOS		;IF NOT 1 THEN JUMP TO LOCAL BDOS
	XCHG			;HL=FCB ADDRESS FROM CALLING ROUTINE
	SHLD	FCBA
	MOV	A,M		;READ IN DRIVE CODE FROM FCB
	ORA	A		;CHECK IF DEFAULT
	JNZ	HAVDSK		;IF NOT DEFAULT THEN A = DRIVE + 1
	LDA	SELDRV		;IF DEFAULT THEN READ CURRENT DISK
	ANI	0FH		;AND OUT USERCODE
	JMP	OVERDSK
HAVDSK:	SUI	1
OVERDSK:STA	CURBDSK
	SUI	8	;SEE IF DRIVE BIT IN HIGH OF LOW BYTE OF DRVTAB
	JC	LOWBYTE
	MOV	C,A
	LDA	DRVTAB
	JMP	DRVSTAT
LOWBYTE:ADI	8		;RECTIFY DRIVE NUMBER
	MOV	C,A
	LDA	DRVTAB+1
DRVSTAT:INR	C		;ROTATE DRIVE BIT INTO CARRY
ROTLP:	RAL
	DCR	C
	JNZ	ROTLP
	JNC	ENTRDOS		;IF BIT NOT 1 THEN GO TO LOCAL BDOS
;
; 	section added july 1982
; 	make sure search get initially intercepted
; 	so the high water mark can be syncronized
;
	lda	bdosfun
	cpi	17	;search for first
	jnz	nsear
	lda	curbdsk
	sta	hidrv	;place drive in request block
	lxi	h,hireq
	mvi	b,10
	call	pnxo
	jnz	entrdos
	lxi	h,retbuf
	mvi	b,4
	call	pnxi
	jnz	entrdos
	lda	curbdsk
	mov	l,a
	mvi	h,0
	lxi	d,dpbase+2
	dad	h
	dad	h
	dad	h
	dad	h
	dad	d
	xchg	; now de points to high water mark in drive's dph
	lhld	retbuf
	mov	a,l
	ora	h
	jz	entrdos	
	xchg
	mov	m,e
	inx	h
	mov	m,d
	jmp	entrdos	;now go to the local bdos
;
hireq:	db	01,'C'
hidrv:	ds	1
hicod:	db	'H'
;
nsear:	
;
;	CNGSEQ#2 FOLLOWS					MMMOST2.0
;
	LXI	H,SAVUSR	;				MMMOST2.0
	PUSH	H		;				MMMOST2.0
	LXI	H,BDOSTRT	;				MMMOST2.0
	MVI	C,20H		;				MMMOST2.0
	MVI	E,0FFH		;				MMMOST2.0
	PCHL			;CALL BDOS FOR USERCODE		MMMOST2.0
SAVUSR:				;END CNGSEQ#2			MMMOST2.0
	STA	USERCOD
;	LDA	CDISK
;	MOV	C,A
	LDA	SELDRV		;GET LOGGED IN DRIVE
	ANI	0FH		;GET RID OF USER CODE
	STA	LOGDRV		;PUT INTO REQUEST BLOCK
	LXI	H,0FFFFH	;FILINDX = FFFFH IF FILE NOT IN TABLE
	SHLD	FILINDX
	INX	H
	SHLD	FILEN1		;DEFAULT IF NOT FOUND
	LXI	H,FILETAB	;CHECK IF FILE IN TABLE => FILE OPEN
	LXI	D,14		;TABLE ENTRY LENGTH
	LDA	CURBDSK
	MOV	B,A
NXTNTRY:MOV	A,M		;FIRST CHECK DRIVE MATCH
	CPI	0FFH		;CHECK IF END OF TABLE FLAG
	JZ	OKOPEN
	CMP	B
	JZ	MTCHMOR		;IF DRIVE MATCH GO ON TO CHECK NAME
GETNEXT:DAD	D		;IF NOT INCREMENT TO NEXT TABLE ENTRY
	JMP	NXTNTRY
MTCHMOR:PUSH	H		;SAVE OF SEARCH PARAMETERS
	PUSH	D
	PUSH	B
	INX	H		;HL=FILE NAME PART OF ENTRY
	XCHG
	LHLD	FCBA
	INX	H		;HL=FCB NAME, DE=TABLE NAME
	MVI	B,11		;B=LENGTH OF NAME
MTCHLP:	LDAX	D
	CMP	M
	JNZ	NOMTCH
	INX	H
	INX	D
	DCR	B
	JNZ	MTCHLP
	LDAX	D		;IF HERE THEN MATCH SO MOVE FILE NO.
	STA	FILEN1		;INTO REQUEST BLOCK
	INX	D
	LDAX	D
	STA	FILEN1+1
	XCHG
	LXI	D,-13		;STORE OFF CURRENT FILE ENTRY ADDRESS
	DAD	D
	SHLD	FILINDX
	POP	B		;RESTORE STACK
	POP	D
	POP	H
	JMP	OKOPEN
;
NOMTCH:	POP	B
	POP	D
	POP	H
	JMP	GETNEXT
;
BADRET:	MVI	A,0FFH		;IF HERE FILE STATUS ~= FUNC. ACTIVITY
	STA	RTNCODE
RETROT:	POP	PSW
	POP	B		;RETURN TO CALLING ROUTINE
	POP	D
	LHLD	USTACK		;RELOAD USER'S STACK POINTER
	SPHL
	POP	H
	LDA	RTNCODE
	RET
;
;	IF HERE THEN PROPER ENTRY INTO MMMOST BDOS CALL => MAKE CALL
;
OKOPEN:	LXI	H,BDRQBLK	;REQUEST BLOCK HAS BEEN FILLED IN
	MVI	B,10		;THEREFORE, SEND IT
	CALL	PNXO
	ORA	A		;A=0 => GOOD TRANSFER
	JNZ	XOTERRT		;PRINT ERROR AND RETURN ERROR
;
OKXFR1:	LHLD	FCBA		;SEND FCB TO SERVICE
	MVI	B,36
	CALL	PNXO
	ORA	A
	JNZ	XOTERRT		;PRINT ERROR AND RETURN
;
OKXFR2:	LDA	CURFNCA		;IF WRITE THEN SEND 128 BYTE DATA
	ANI	04H
	JZ	NONWRT
	LHLD	DMAADR
	MVI	B,128
	CALL	PNXO		;SEND DATA
	ORA	A
	JNZ	XOTERRT		;PRINT ERROR AND RETURN ERROR
;
NONWRT:	MVI	B,4		;READ IN RETURN CODE
	LXI	H,RETBUF
	CALL	PNXI
	CPI	TIMERR		;				MMMOST2.04
	JZ	NONWRT		;				MMMOST2.04
	ORA	A
	JNZ	XINERRT		;				MMMOST2.04
;
OKXFR4:	LHLD	FCBA		;READ IN NEW FCB
	MVI	B,36
	CALL	PNXI
	ORA	A
	JNZ	XINERRT
;
OKXFR5:	LDA	PRNTRTN
	ORA	A
	JZ	NOMESSGE
	MOV	B,A		;B HAS PRINT ERROR CODE
	MVI	C,0		;C HAS 0 TO INDICATE BDOS ERR.
	CALL	PRNTERR
	LDA	PRNTRTN		;IF ERROR PRINT BYTE = X010XXXX
	ANI	20H		;THEN JUMP TO WARM BOOT
	CPI	20H		;BECAUSE R/O ERROR
	JZ	WBOOT		;AS PER CP/M 2.2 STANDARD
	JMP	RETROT
;
NOMESSGE:
	LDA	CURFNCA		;ERROR IF FF OR ~00
	ANI	40H		;DO6=1 IF ERR ON ~00 =0 IF ON FF
	LDA	RTNCODE
	JZ	ERRFF
	ORA	A
	JNZ	RETROT
	JMP	NOERR
ERRFF:	CMA
	ORA	A		;SET FLAGS, ZERO SET IF A WAS FFH
	JZ	RETROT
NOERR:	LDA	CURFNCA		;CHECK IF NEED TO READ SECTOR
	ANI	8
	JZ	NONREAD
	LHLD	DMAADR		;IF READ THEN READ 128 BYTES INTO DMAADR
	MVI	B,128
	CALL	PNXI
	ORA	A
	JNZ	XINERRT		;PRINT ERROR AND RETURN ERROR
;
NONREAD:LDA	CURFNCA		;CHECK IF OPEN OR MAKE
	ANI	10H
	JZ	NONOPEN
	LHLD	FILINDX		;IF FILINDX ~=FFFF THEN REOPEN
	MOV	A,H
	ANA	L
	CPI	0FFH		;A=FF IF FILINDX = FFFF
	JZ	FILLIN
	LXI	D,12		;IF HERE THEN REOPEN =>
	DAD	D
	LDA	FILENO		;FILL IN POSSIBLY NEW FILE NUMBER
	MOV	M,A
	LDA	FILENO+1
	INX 	H
	MOV	M,A
	JMP	RETROT		;IF OPEN AND FILLED IN THEN DONE
;
FILLIN:	LXI	H,FILETAB	;IF OPEN OR MAKE GET OPEN SPACE
	LXI	D,14
LOOPLP:	MOV	A,M
	CPI	80H		;80H = EMPTY RECORD
	JZ	HOLE
	CPI	0FFH
	JZ	RETROT		;TOO BAD TABLE FULL
;				;BUT IT'S OK
KEEPLK:	DAD	D
	JMP	LOOPLP
;
HOLE:	LDA	CURBDSK
	MOV	M,A
	INX	H
	XCHG			;MOVE OVER DRIVE, FILE NAME, FILE NUM.
	LHLD	FCBA
	INX	H
	MVI	B,11
FILLLP:	MOV	A,M
	STAX	D
	INX 	H
	INX	D
	DCR	B
	JNZ	FILLLP
	LDA	FILENO
	STAX	D
	INX 	D
	LDA	FILENO+1
	STAX	D
	JMP	RETROT		;FINISHED IF OPEN => RETURN
;
NONOPEN:
	LDA	CURFNCA
	ANI	20H
	JZ	RETROT		;IF NOT CLOSE THEN DONE => RETURN
	LHLD	FILINDX		;IF CLOSE THEN PUT DRIVE TO 80H
	MVI	M,80H
	JMP	RETROT
;
XOTERRT:
	MVI	B,06H		;PRINT XFER OUT ERR CODE
OTHERP:	CALL	PRNTERR
	JMP	BADRET		;RETURN WITH FF IN A
;
XINERRT:
	MVI	B,07H		;PRINT XFER IN ERR CODE
	JMP	OTHERP
	ENDIF			;END OF USERCPM
;
; END OF TPCISUBS.MAC

