; dos3d/asm
*TITLE	'<DOS+II rs232 drivers>'
;
;	local equates
;
SIODA	EQU	3		;SIO channel A DCB number
SIODB	EQU	4		;SIO channel B DCB number
;
;	vector for SIO (in/out)(SVC's 96-99)
;	on entry, IX=DCB
;		 C = input a byte
;		 Z = output a byte
;	on exit, B = char, A = status
;		 Z = OK, char in B
;		NZ = no character
;		 Carry = carrier lost
;
SIOCODE EX	AF,AF'          ;save I/O
	BIT	1,(IX+5)	;initialized?
	LD	A,66		;'no function exists'
	RET	NZ		;exit!
	EX	AF,AF'          ;get I/O
	JR	Z,ABTX		;transmit
;
;	SIO receive services
;
	CALL	BUFTAKE 	;any chars in buffer?
	JR	C,RXIN		;char in buffer
	LD	A,2		;char not avail
	OR	A		;NZ status
	RET
;
RXIN	PUSH	BC		;SAVE char
	AND	(IX+20) 	;word length mask
	LD	C,(IX+11)
	LD	B,(IX+12)	;buff length
	ADD	HL,BC		;HL => status
	LD	L,(HL)		;L = status byte
	LD	(IX+15),E	;update
	LD	(IX+16),D	;ring
	BIT	0,(IX+5)	;translate?
	JR	Z,SIO4		;continue if not
	PUSH	HL		;save status
	LD	L,(IX+6)	;table address
	LD	H,(IX+7)
	LD	B,(IX+8)	;# of entries
	CALL	XLATE		;translate the char
	POP	HL		;get status
;
SIO4	POP	BC		;get char
	LD	B,A		;new char
	LD	A,L		;get status
	CP	A		;all ok
	RET
;
;	SIO transmit services
;
ABTX	PUSH	BC		;save character
	LD	A,B		;get character
	AND	(IX+20) 	;word length mask
	LD	E,A		;save it here
TXWT	CALL	RSTATUS 	;get status byte
	BIT	2,B		;tx buffer empty?
	JR	NZ,TXWT 	;wait if not
	LD	C,(IX+17)	;SIO base port
	DEC	C		;point to data port
	DEC	C
	OUT	(C),E		;send the byte
	LD	A,B		;get status byte
	POP	BC		;restore chars
	CP	A		;z status
	RET			;done
;
;	fetch the status of the SIO port
;	set the mask byte so 0 bits = OK
;
RSTATUS LD	C,(IX+17)	;get SIO base port
	IN	B,(C)		;RR 0 status
	LD	A,1		;RR 1
	OUT	(C),A		;sel register
	IN	C,(C)		;RR 1 status
	LD	A,30H		;error MASK
	OUT	(C),A		;clear error
	LD	A,B		;RR 0 status
	AND	84H		;BREAK,TX
	XOR	4		;invert TX
	LD	B,A		;B = RR 0 status
	LD	A,C		;RR 1 status
	AND	70H		;FRAME,OVERRUN,PARITY
	OR	B		;OR status
	LD	B,A		;B = status
	RET
;
*EJECT
;	SIO interrupt services
;
RSINTA	PUSH	AF		;save
	LD	A,SIODA 	;channel A DCB
	JR	RSINTC		;go common
;
RSINTB	PUSH	AF		;save everything
	LD	A,SIODB 	;channel B DCB
;
RSINTC	PUSH	BC		;save everything
	PUSH	DE
	PUSH	HL
	PUSH	IX
;
	CALL	LOCDCB		;locate DCB
	LD	C,(IX+17)	;get base port
	DEC	C
	DEC	C		;C = data port
	IN	B,(C)		;get character
	CALL	VIDOFF		;no VIDEO!
	CALL	BUFFADD 	;room to add?
	LD	A,0		;no overrun
	JR	C,RSINT1	;all ok
	LD	E,(IX+13)
	LD	D,(IX+14)	;get ring
	LD	L,(IX+09)
	LD	H,(IX+10)	;HL => start buffer
	ADD	HL,DE		;HL => last char
	LD	A,20H		;overrun mask
;
RSINT1	LD	(HL),B		;put char in buffer
	LD	C,(IX+11)
	LD	B,(IX+12)	;buff size
	ADD	HL,BC		;HL => status
	LD	(HL),A		;overrun status
	CALL	RSTATUS 	;get status byte
	OR	(HL)		;with overrun
	LD	(HL),A		;status to buffer
	CALL	NMION		;restore VIDEO
	LD	(IX+13),E	;update
	LD	(IX+14),D	;ring
;
	POP	IX		;restore everything
	POP	HL
	POP	DE
	POP	BC
	POP	AF
	EI
	RETI			;return from interrupt
;
 