; IBM PC-XT Model 286 BIOS ; RS232.ASM ---- 06/10/85 COMMUNICATIONS BIOS (RS232) ; (Modifications are based on AWARD BIOS 1999 - ATORGS.ASM) ; http://wiki.osdev.org/Serial_Ports .286C .XLIST INCLUDE DSEG.INC INCLUDE POSTEQU.INC .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 00 - NONE 0 - 1 10 - 7 BITS : ; 001 - 150 01 - ODD 1 - 2 11 - 8 BITS : ; 010 - 300 11 - EVEN : ; 011 - 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 RS232_IO_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 ; RS232 VALUE TO (SI) MOV DI,DX ; AND TO (DI) (FOR TIMEOUTS) SHR DX,2 ; TEST PARAMETER JNZ A3 ; RETURN IF NOT IN RANGE 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 PAGE ;----- INITIALIZE THE COMMUNICATIONS PORT A4: MOV AH,AL ; SAVE INITIALIZATION PARAMETERS IN (AH) ADD DX,3 ; POINT TO 8250 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[SI] ; 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 & 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 PAGE ;---------------------------------------- ; 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 RCL BP,1 ; MULTIPLY OUTER COUNT BY 4 RCL 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,BH ; 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 ; IBM PC-XT Model 286 BIOS ; ORGS.ASM ----- 06/10/85 COMPATIBILITY MODULE ;----- BAUD RATE INITIALIZATION TABLE BAUD_DIVISORS: ; Award BIOS - 1999, ATORGS.ASM A1: DW 1047 ; 110 BAUD ; TABLE OF VALUES DW 768 ; 150 ; FOR INITIALIZATION DW 384 ; 300 DW 192 ; 600 DW 96 ; 1200 DW 48 ; 2400 DW 24 ; 4800 DW 12 ; 9600 ;;;;;;;; DW 6 ; 19200 ; Award BIOS - 1999 ;;;;;;;; Retro UNIX 386 v1 DW 3 ; 38400 DW 2 ; 57600 DW 1 ; 115200