TITLE R5232 ---- 06/10/85  COMMUNICATIONS BIOS (RS232)
.LIST
CODE	SEGMENT BYTE PUBLIC

	PUBLIC	RS232_IO_1
	EXTRN	A1:NEAR
	EXTRN	DDS:NEAR

;--- INT 14 H -----------------------------------------------------------------
;RS232_IO								:
;       THIS ROUTINE PROVIDES BYTE STREAM I/O TO THE COMMUNICATIONS		:
;       PORT ACCORDING TO THE PARAMETERS:							:
;									:
;       (AH)= 00H  INITIALIZE THE COMMUNICATIONS PORT					:
;                  (AL) HAS PARAMETERS FOR INITIALIZATION				:
;									:
;               7       6       5       4       3       2      1       0	:
;               ----- BAUD RATE --      -PARITY--     STOPBIT  --WORD LENGTH--:
;               000 - 110               XO - NONE	0 - 1	    10 - 7 BITS	:
;               001 - 150               01 - ODD	1 - 2	    11 - 8 BITS	:
;               010 - 300               11 - EVEN					:
;               O11 - 600							:
;               100 - 1200							:
;               101 - 2400							:
;               110 - 4800							:
;               111 - 9600							:
;               ON RETURN, CONDITIONS SET AS IN CALL TO COMMO STATUS (AH=03H)	:
;									:
;      (AH)= 01H   SEND THE CHARACTER IN (AL) OVER THE COMMO LINE			:
;                  (AL) REGISTER IS PRESERVED						:
;                  ON EXIT, BIT 7 OF AH IS SET IF THE ROUTINE WAS UNABLE TO	:
;                       TO TRANSMIT THE BYTE OF DATA OVER THE LINE.		:
;                       IF BIT 7 OF AH IS NOT SET, THE				:
;                       REMAINDER OF (AH) IS SET AS IN A STATUS REQUEST,	:
;                       REFLECTING THE CURRENT STATUS OF THE LINE.		:
;      (AH)= 02H   RECEIVE A CHARACTER IN (AL), FROM COMMO LINE BEFORE 		:
;                       RETURNING TO CALLER						:
;                  ON EXIT, (AH) HAS THE CURRENT LINE STATUS, AS SET BY THE	:
;                       THE STATUS ROUTINE, EXCEPT THAT THE ONLY BITS		:
;                       LEFT ON ARE THE ERROR BITS (7,4,3,2,1)			:
;                       IF (AH) HAS BIT 7 ON (TIME OUT) THE REMAINING		:
;                       BITS ARE NOT PREDICTABLE.					:
;                       THUS, (AH) IS NON ZERO ONLY WHEN AN ERROR OCCURRED.	:
;      (AH)= 03H   RETURN THE COMMO PORT STATUS IN (AX)				:
;                   (AH) CONTAINS THE LINE CONTROL STATUS IN (AX)			:
;                        BIT 7 = TIME OUT							:
;                        BIT 6 = TRANSMIT SHIFT REGISTER EMPTY			:
;                        BIT 5 = TRANSMIT HOLDING REGISTER EMPTY			:
;                        BIT 4 = BREAK DETECT						:
;                        BIT 3 = FRAMING ERROR						:
;                        BIT 2 = PARITY ERROR						:
;                        BIT 1 = OVERRUN ERROR						:
;                        BIT 0 = DATA READY						:
;                   (AL) CONTAINS THE MODEM STATUS IN					:
;                        BIT 7 = RECEIVE LINE SIGNAL DETECT				:
;                        BIT 6 = RING INDICATOR						:
;                        BIT 5 = DATA SET READY						:
;                        BIT 4 = CLEAR TO SEND						:
;                        BIT 3 = DELTA RECEIVE LINE SIGNAL DETECT			:
;                        BIT 2 = TRAILING EDGE RING DETECTOR			:
;                        BIT 1 = DELTA DATA SET READY					:
;                        BIT 0 = DELTA CLEAR TO SEND					:
;									:
;      (DX) = PARAMETER INDICATING WHICH RS232 CARD (0,1 ALLOWED)			:
;									:
; DATA AREA @RS232_BASE CONTAINS THE BASE ADDRESS OF THE 8250 ON THE CARD	:
;       LOCATION 400H CONTAINS UP TO 4 RS232 ADDRESSES POSSIBLE			:
;       DATA AREA LABEL @RS232_TIM_OUT (BYTE) CONTAINS OUTER LOOP COUNT		:
;       VALUE FOR TIMEOUT (DEFAULT=1)							:
;OUTPUT									:
;               AX MODIFIED ACCORDING TO PARAMETERS OF CALL				:
;               ALL OTHERS UNCHANGED							:
;------------------------------------------------------------------------------
	ASSUME	CS:CODE,DS:DATA

R5232_10_1	PROC    FAR

;-----	VECTOR TO APPROPRIATE ROUTINE
	STI				; INTERRUPTS BACK ON
	PUSH	DS			; SAVE SEGMENT
	PUSH	DX
	PUSH	SI
	PUSH	DI
	PUSH	CX
	PUSH	BX
	MOV	SI,DX			; R5232 VALUE TO (SI)
	MOV	DI,DX			; AND TO (DI) (FOR TIMEOUTS)
	SHL	SI,1			; WORD OFFSET
	CALL	DDS
	MOV	DX,@RS232_BASE[SI]	; GET BASE ADDRESS
	OR	DX,DX			; TEST FOR 0 BASE ADDRESS
	JZ	A3			; RETURN
	OR	AH,AH			; TEST FOR (AH)= 00H
	JZ	A4			; COMMO INITIALIZATION
	DEC	AH			; TEST FOR (AH)= 01H
	JZ	A5			; SEND (AL)
	DEC	AH			; TEST FOR (AH)= 02H
	JZ	A12			; RECEIVE INTO (AL)
A2:
	DEC	AH			; TEST FOR (AH)= 03H
	JNZ	A3
	JMP	A18			; COMMUNICATION STATUS
A3:					; RETURN FROM RS232
	POP	BX
	POP	CX
	POP	DI
	POP	SI
	POP	DX
	POP	DS
	IRET				; RETURN TO CALLER, NO ACTION

;-----	INITIALIZE THE COMMUNICATIONS PORT
A4:
	MOV	AH.AL			; SAVE INITIALIZATION PARAMETERS IN (AN)
	ADD	DX,3			; POINT TO 825O CONTROL REGISTER
	MOV	AL,80H
	OUT	DX,AL			; SET DLAB=1

;-----	DETERMINE BAUD RATE DIVISOR
	MOV	DL,AH			; GET	PARAMETERS TO (DL)
	MOV	CL,4
	ROL	DL,CL
	AND	DX,0EH			; ISOLATE THEM
	MOV	DI,OFFSET A1		; BASE OF TABLE
	ADD	DI,DX			; PUT INTO INDEX REGISTER
	MOV	DX,@RS232_BASE[SL]	; POINT TO HIGH ORDER OF DIVISOR
	INC	DX
	MOV	AL,CS:[DI]+1		; GET HIGH ORDER OF DIVISOR
	OUT	DX,AL			; SET ms OF DIVISOR TO 0
	DEC	DX
	JMP	$+2			; I/O DELAY
	MOV	AL.CS:[DI]		; GET LOW ORDER OF DIVISOR
	OUT	DX,AL			; SET LOW OF DIVISOR
	ADD	DX,3
	MOV	AL,AH			; GET PARAMETERS BACK
	AND	AL,01FH			; STRIP OFF THE BAUD BITS
	OUT	DX,AL			; LINE CONTROL TO 8 BITS
	DEC	DX
	DEC	DX
	JMP	$+2			; I/O DELAY
	MOV	AL,0
	OUT	DX,AL			; INTERRUPT ENABLES ALL OFF
	JMP	SHORT A18		; COM_STATUS

;-----	SEND CHARACTER IN (AL) OVER COMMO LINE

A5:
	PUSH	AX			; SAVE CHAR TO SEND
	ADD	DX,4			; MODEM CONTROL REGISTER
	MOV	AL,3			; DTR AND RTS
	OUT	DX,AL			; DATA TERMINAL READY, REQUEST TO SEND
	INC	DX			; MODEM STATUS REGISTER
	INC	DX
	MOV	BH,30H			; DATA SET READY A CLEAR TO SEND
	CALL	WAIT_FOR_STATUS		; ARE BOTH TRUE
	JE	A9			; YES, READY TO TRANSMIT CHAR
A7:
	POP	CX
	MOV	AL,CL			; RELOAD DATA BYTE
A8:
	OR	AH,80H			; INDICATE TIME OUT
	JMP	A3			; RETURN

A9:					; CLEAR TO SEND
	DEC	DX			; LINE STATUS REGISTER
A10:					; WAIT SEND
	MOV	BH,20H			; IS TRANSMITTER READY
	CALL	WAIT_FOR_STATUS		; TEST FOR TRANSMITTER READY
	JNZ	A7			; RETURN WITH TIME OUT SET
A11:					; OUT CHAR
	SUB	DX,5			; DATA PORT
	POP	CX			; RECOVER IN CX TEMPORARILY
	MOV	AL,CL			; MOVE CHAR TO AL FOR OUT, STATUS IN AH
	OUT	DX,AL			; OUTPUT CHARACTER
	JMP	A3			; RETURN

;-----	RECEIVE CHARACTER FROM COMMO LINE
A12:
	ADD	DX,4			; MODEM CONTROL REGISTER
	MOV	AL,1			; DATA TERMINAL READY
	OUT	DX,AL
	INC	DX			; MODEM STATUS REGISTER
	INC	DX
A13:					; WAIT_DSR
	MOV	BH,20H			; DATA SET READY
	CALL	WAIT_FOR_STATUS		; TEST FOR DSR
	JNZ	A8			; RETURN WITH ERROR
A15:					; WAIT_DSR_END
	DEC	DX			; LINE STATUS REGISTER
A16:					; WAIT_RECV
	MOV	BH,1			; RECEIVE BUFFER FULL
	CALL	WAIT_FOR_STATUS		; TEST FOR RECEIVE BUFFER FULL
	JNZ	A8			; SET TIME OUT ERROR
A17:					; GET_CHAR
	AND	AH,00011110B		; TEST FOR ERROR CONDITIONS ON RECEIVE

	MOV	DX,@RS232_BASE[SI]	; DATA PORT
	IN	AL,DX			; GET CHARACTER FROM LINE
	JMP	A3			; RETURN

;-----	COMMO PORT STATUS ROUTINE

A18:
	MOV	DX,@RS232_BASE[SI]
	ADD	DX,5			; CONTROL PORT
	IN	AL,DX			; GET LINE CONTROL STATUS
	MOV	AH,AL			; PUT IN (AH) FOR RETURN
	INC	DX			; POINT TO MODEM STATUS REGISTER
	IN	AL,DX			; GET MODEM CONTROL STATUS
	JMP	A3			; RETURN

;------------------------------------------
;	WAIT FOR STATUS ROUTINE	:
;ENTRY:	(BH) = STATUS BIT(S) TO LOOK FOR	:
;	(DX) = ADDRESS OF STATUS REG	:
;EXIT:	ZERO FLAG ON = STATUS FOUND	:
;	ZERO FLAG OFF = TIMEOUT.	:
;	(AH) = LAST STATUS READ	:
;------------------------------------------

WAIT_FOR_STATUS	PROC  NEAR
	MOV	BL,@RS232_TIM_OUT[DI]	; LOAD OUTER LOOP COUNT

;-----	ADJUST OUTER LOOP COUNT

	PUSH	BP			; SAVE (BP)
	PUSH	BX			; SAVE (BX)
	POP	BP			; USE BP FOR OUTER LOOP COUNT
	AND	BP,00FFH		; STRIP HIGH BITS
	ROL	BP,1			; MULTIPLY OUTER COUNT BY 4
	ROL	BP,1
WFS0:
	SUB	CX,CX
WFS1:
	IN	AL,DX			; GET STATUS
	MOV	AH,AL			; MOVE TO (AH)
	AND	AL,BH			; ISOLATE BITS TO TEST
	CMP	AL,9H			; EXACTLY = TO MASK
	JE	WFS_END			; RETURN WITH ZERO FLAG ON

	LOOP	WFS1			; TRY AGAIN

	DEC	BP
	JNZ	WFS0
	OR	BH,BH			; SET ZERO FLAG OFF
WFS_END:
	POP	BP			; RESTORE (BP)
	RET

WAIT_FOR_STATUS	ENDP

RS232_IO_1	ENDP

	CODE	ENDS
	END

