; COM1200.ASM - 23-JUN-95 - for MS C5.10 ; 26-NOV-93 - GR-526 MS-C5.1 ; 4-APR-94 - for GR-820 RBUF[100H] -> 2048 ; 5-APR-94 - .FARDATA ... deleted -> .DATA ; 23-JUN-95 - from COM9600.ASM ; *** PC: COM1 SERIAL PORT 9600 Bd ; ROUTINES: _m_init( void ) ; _m_dis( void ) ; _m_DTR1(void), _m_DTR0(void) ; M_INT - IR4 ; LF->STOP _m_read ( char *buf, int *n ) ; binary _m_readb( char *buf, int *n ) ; _m_writ ( char *buf, int *n ) ; int = _m_wait( void ) I4_VEC EQU 30H ;COM1 INT VECTR RS1B EQU 3F8H ;BASE COM1 REG .MODEL LARGE .DATA PUBLIC _m_loc _m_loc DW 0 ;nb of bytes in RBUF RS_RBUF DB 2048 DUP(0) ;RS READ BUF RS_REND label byte ;END OF R.BUF RS_WBUF DB 100H DUP(0) ;RS WRITE BUF RS_WEND label byte ;END OF W.BUF RS_RIN DW 0,0 ;RS READ IN P RS_WOUT DW 0,0,0 ;RS WRITE OUTP I4_ADDR DW 0,0 ;OLD INT #4 ADDR INT_IER DB 0 ;INT EN MASK RS_WFLG DB 0 ;WRITE FLAG .CODE ; DS = _DGRPOUP, NOT _DATA !!! ; *** void m_init( void ) _m_init PROC PUBLIC _m_init PUSH AX PUSH BX PUSH CX PUSH DX PUSH SI PUSH ES PUSH DS ASSUME DS:@DATA MOV AX,@DATA MOV DS,AX ; -1- SET 1200 BD, 8 DATA, NO PARITY, 1 STOP MOV DX,RS1B+3 ;LCR MOV AL,80H ;DLAB=1 OUT DX,AL MOV DX,RS1B ;BAL REG MOV AL,96 ; (1.8432 MHz) OUT DX,AL INC DX ;BAH REG MOV AL,0 OUT DX,AL MOV DX,RS1B+3 ;LCR MOV AL,3 ;NO PARITY, 1 STOP, 8 DATA OUT DX,AL ; & LATCH BAL/BAH ; -2- ACTIVATE OUT2, RTS & DTR (BIT 3, 1 & 0) MOV AL,0BH ;OUT2=RTS=DTR=1 MOV DX,RS1B+4 ;MCR OUT DX,AL ; -3- TEST/CLEAR INPUT BUFFER CONT: MOV CX,2000 LOOP $ ;WAIT MOV DX,RS1B+5 ;LSR IN AL,DX ;STATUS AND AL,1 ;TEST DR JZ CONT1 ;IF EMPRY MOV DX,RS1B ;R/W REG COM1 IN AL,DX ;READ JMP CONT ;REPEAT ; -4- INITIALISE POINTERS TO RBUF/WBUF CONT1: MOV BX,OFFSET RS_RIN MOV AX,OFFSET RS_RBUF MOV [BX],AX ;TO RS_RIN MOV [BX+2],AX ;TO RS_ROUT MOV BX,OFFSET RS_WOUT MOV [BX],DS ;DS MOV AX,OFFSET RS_WBUF MOV [BX+2],AX ;FIRST ADDR MOV [BX+4],AX ;LAST=FIRST ; -5- SAVE/SET INT #4 COM1 VECTOR ADDRESS MOV SI,OFFSET I4_ADDR ;OLD I4 VECT MOV AX,0 MOV ES,AX ;ES=0 MOV BX,I4_VEC MOV AX,ES:[BX] ;OLD MOV [SI],AX MOV AX,ES:[BX+2] MOV [SI+2],AX ;SAVE OLD MOV AX,SEG M_INT ;NEW MOV ES:[BX+2],AX MOV AX,OFFSET M_INT MOV ES:[BX],AX ; -6- ENABLE WRITE/READ & INTERRUPT - IR4 MOV DX,RS1B+1 ;IER MOV AL,1 ;RXD INT.EN OUT DX,AL MOV INT_IER,AL ;SAVE IER MOV RS_WFLG,0 ;EN START M_WRIT MOV _m_loc,0 IN AL,21H ;GET INT MASK AND AL,0EFH ;IR4=0 OUT 21H,AL ;ENABLE IR4 POP DS POP ES POP SI POP DX POP CX POP BX POP AX RET _m_init ENDP page ; void m_dis( void ) ; *** DISABLE MODEM INTERRUPTS - COM1 _m_dis PROC PUBLIC _m_dis PUSH AX PUSH BX PUSH DX PUSH SI PUSH ES PUSH DS ASSUME DS:@DATA MOV AX,@DATA MOV DS,AX ; -1- CLEAR RTS (BIT 1) MOV AL,9 ;RTS=0, (OUT2=DTR=1) MOV DX,RS1B+4 ;MCR OUT DX,AL ; -2- DISABLE WRITE/READ COM1 MOV DX,RS1B+1 ;IER MOV AL,0 ;TXD/RXD INT.DIS OUT DX,AL ; -3- DISABLE PIC INTERRUPT - IR4 IN AL,21H ;GET INT MASK OR AL,10H ;IR4=1 OUT 21H,AL ;DISABLE IR4 ; -4- RESTORE I4_ADDRESS MOV SI,OFFSET I4_ADDR ;OLD I4 VECT MOV AX,0 MOV ES,AX ;ES=0 MOV BX,I4_VEC MOV AX,[SI] ;OLD MOV ES:[BX],AX MOV AX,[SI+2] MOV ES:[BX+2],AX ;SAVE OLD POP DS POP ES POP SI POP DX POP BX POP AX RET _m_dis ENDP page ; void m_DTR1( void ) ; *** SET DTR=1 OF COM1 _m_DTR1 PROC PUBLIC _m_DTR1 PUSH AX PUSH DX MOV AL,0BH ;OUT2=RTS=DTR=1 MOV DX,RS1B+4 ;MCR OUT DX,AL POP DX POP AX RET _m_DTR1 ENDP ; ********************************************* ; void m_DTR0( void ); ; *** CLEAR DTR=0 OF COM1 _m_DTR0 PROC PUBLIC _m_DTR0 PUSH AX PUSH DX MOV AL,0AH ;DTR=0, (OUT2=RTS=1) MOV DX,RS1B+4 ;MCR OUT DX,AL POP DX POP AX RET _m_DTR0 ENDP page ; *** READ/WRITE INTERRUPT ROUTINE - IR4 @@@ M_INT PROC PUBLIC M_INT PUSH AX PUSH BX PUSH DX PUSH SI PUSH DI PUSH ES PUSH DS ASSUME DS:@DATA MOV AX,@DATA MOV DS,AX MOV ES,AX ;ES=DS CLD MOV DX,RS1B+2 ;IIR IN AL,DX AND AL,7 ;6 21-mar JZ MODEM ;IF MODEM INT CMP AL,2 JE INTWR1 ;IF TXD EMPTY CMP AL,4 JE INTRD1 ;IF DR JMP RET1 ;IF ?? INT INTWR1: JMP INTWR INTRD1: JMP INTRD ;IF RXD (DATA READY) ; *** M O D E M *** MODEM: MOV DX,RS1B+6 ;MSR IN AL,DX ;RESET INT REQ AND AL,1 JZ LRET1 ;IF DCTS=0 IN AL,DX AND AL,10H JZ LRET1 ;IF CTS=0 CMP RS_WFLG, 0 JE LRET1 ; IF NOT WRITE MOV BX,OFFSET INT_IER ;IF CTS=1 MOV AL,[BX] ;GET INT MASK AND AL,0F7H ;DIS MODEM INT OR AL,2 ;EN TXD INT MOV [BX],AL ;SAVE MASK MOV DX,RS1B+1 ;IER OUT DX,AL ;RE-ENABLE WRITE TO COM1 LRET1: JMP RET1 ;CONT WRITE page ; *** R E A D *** INTRD: MOV BX,OFFSET RS_RIN MOV DI,[BX] ; IN POINTER MOV SI,[BX+2]; OUT POINTER MOV DX,RS1B ;RXD REG IN AL,DX ; R E A D STOSB ;SAVE AL ES:[DI],INC DI CMP DI,OFFSET RS_REND JB ROK1 MOV DI,OFFSET RS_RBUF ROK1: MOV [BX],DI ;NEXT ADDR ; ----- ; *** TEST IF SPACE FOR NEXT DATA INC _m_loc CMP _m_loc,2000 ; HIGH JNE RET1 ;IF SPACE ; *** RBUF FULL -> RTS=0 (BIT 1) MOV DX,RS1B+4 ;MCR MOV AL,9 ;RTS=0, (OUT2=DTR=1) OUT DX,AL ; & INT OUT DISABLE JMP RET1 page ; *** W R I T E *** INTWR: MOV DX,RS1B+6 ;MSR IN AL,DX AND AL,10H ;TEST CTS JNZ CTS1 ;IF CTS=1 ; ----- ; * DIS TXD INT, EN MODEM INT (CTS) MOV BX,OFFSET INT_IER MOV AL,[BX] ;GET INT MASK AND AL,0FDH ;DIS TXD INT OR AL,8 ;EN MODEM INT MOV [BX],AL ;SAVE MASK MOV DX,RS1B+1 ;IER OUT DX,AL ;DISABLE WRITE TO COM1 JMP RET1 ; ----- CTS1: MOV BX,OFFSET RS_WOUT MOV ES,[BX] ;DS MOV SI,[BX+2] ;OUT POINTER MOV DI,[BX+4] ;LAST ADDRESS MOV AL,ES:[SI] ;GET BYTE MOV DX,RS1B ;R/W REG OUT DX,AL ; W R I T E INC SI MOV [BX+2],SI ;INC OUT POINTER CMP SI,DI ;LAST ADDRESS JNZ RET1 ;CONTINUE WRITE ; * IF RS_WBUF IF EMPTY -> ; 1 - CLR TXD INT EN ; 2 - RS_WFLG=0 (EN NEXT WRITE) MOV BX,OFFSET INT_IER MOV AL,[BX] ;GET INT MASK AND AL,0FDH ;CLR TXD BIT MOV [BX],AL ;SAVE MASK MOV DX,RS1B+1 ;IER OUT DX,AL ;DISABLE WRITE TO COM1 MOV BX,OFFSET RS_WFLG MOV BYTE PTR [BX],0 RET1: POP DS POP ES POP DI POP SI POP DX POP BX MOV AL,64H ;SPECIF EOI IR4 OUT 20H,AL ;OCW2 POP AX IRET M_INT ENDP page ; void m_read( char *buf, int *n ) ; *** MOVE n BYTES FROM RBUF TO buf ; IF LF -> STOP, RETURN NEW n ; SEG & OFFSET OF buf, n IS IN STACK _m_read PROC PUBLIC _m_read PUSH BP MOV BP,SP SUB SP,2 ;[BP-2] RETURN (local) n PUSH AX PUSH BX PUSH CX PUSH DX PUSH SI PUSH DI PUSH ES PUSH DS ASSUME DS:@DATA MOV AX,@DATA MOV DS,AX CLD MOV WORD PTR [BP-2],0 ;RET n=0 LES BX,[BP+10] ;ES:BX = ADDR n MOV CX,ES:[BX] ;CX=n LES DI,[BP+6] ;ES:DI = ADDR buf ; ----- RNEXT: MOV BX,OFFSET RS_RIN MOV SI,[BX+2] ;OUT POINTER TRY: CMP SI,[BX] ;CMP IN PTR JE TRY ;WAIT COM1 INPUT ; * MOVE BYTE FROM RBUF TO BUF MOV AL,[SI] ; R E A D RBUF INC SI CMP SI,OFFSET RS_REND JB OKR MOV SI,OFFSET RS_RBUF OKR: MOV [BX+2],SI ;INC OUT POINTER CMP AL,13 JE BEGEND ;SKIP CR CMP AL,10 JE BEGEND ;SKIP LF STOSB ; M O V E AL -> ES:[DI], INC DI INC WORD PTR [BP-2] ;RET n+1 BEGEND: page ; * DEC/TEST m_loc - SET RTS=1 DEC _m_loc CMP _m_loc,50 ; LOW JNE TESTLF ;IF NOT TIME SET RTS=1 ; --- MOV AH,AL ;SAVE AL MOV DX,RS1B+4 ;MCR MOV AL,0BH ;RTS=1 (OUT2=DTR=1) OUT DX,AL MOV AL,AH ;GET AL ; * TEST LF TESTLF: CMP AL,10 JE RRET ; E N D NOTLF: LOOP RNEXT ; ----- RRET: MOV AX,[BP-2] LES BX,[BP+10] ;ES:BX = ADDR n MOV ES:[BX],AX ;RET n POP DS POP ES POP DI POP SI POP DX POP CX POP BX POP AX MOV SP,BP POP BP RET _m_read ENDP page ; *************************************** ; void m_readb( char *buf, int *n ) ; *** MOVE n BYTES FROM RBUF TO buf ; SEG & OFFSET OF buf, n IS IN STACK _m_readb PROC PUBLIC _m_readb PUSH BP MOV BP,SP PUSH AX PUSH BX PUSH CX PUSH DX PUSH SI PUSH DI PUSH ES PUSH DS ASSUME DS:@DATA MOV AX,@DATA MOV DS,AX CLD LES BX,[BP+10] ;ES:BX = ADDR n MOV CX,ES:[BX] ;CX=n LES DI,[BP+6] ;ES:DI = ADDR buf ; ----- RNEXTb: MOV BX,OFFSET RS_RIN MOV SI,[BX+2] ;OUT POINTER TRYb: CMP SI,[BX] ;CMP IN PTR JE TRYb ;WAIT COM1 INPUT ; * MOVE BYTE FROM RBUF TO BUF MOV AL,[SI] ; R E A D RBUF INC SI CMP SI,OFFSET RS_REND JB OKRb MOV SI,OFFSET RS_RBUF OKRb: MOV [BX+2],SI ;INC OUT POINTER STOSB ; M O V E AL -> ES:[DI], INC DI ; * DEC/TEST m_loc - SET RTS=1 DEC _m_loc CMP _m_loc,50 ; LOW JNE TNEXTb ;IF NOT TIME SET RTS=1 MOV DX,RS1B+4 ;MCR MOV AL,0BH ;RTS=1 (OUT2=DTR=1) OUT DX,AL TNEXTb: LOOP RNEXTb ; ----- POP DS POP ES POP DI POP SI POP DX POP CX POP BX POP AX MOV SP,BP POP BP RET _m_readb ENDP page ; ************************************** ; void m_writ( char *buf, int *n ); ; *** WRITE n BYTES FROM buf TO COM1 ; SEG & OFFSET OF buf, n IS IN STACK _m_writ PROC PUBLIC _m_writ PUSH BP MOV BP,SP PUSH AX PUSH BX PUSH DX PUSH ES PUSH DS ASSUME DS:@DATA MOV AX,@DATA MOV DS,AX LES BX,[BP+10] ;ES:BX - ADDR n MOV AX,ES:[BX] PUSH AX ;n LES DX,[BP+6] ;ES:DX - ADDR buf MOV BX,OFFSET RS_WFLG WENDW: CMP BYTE PTR [BX],1 JE WENDW ;WAIT END OF TRANSMIT MOV BYTE PTR [BX],1 MOV BX,OFFSET RS_WOUT MOV [BX],ES MOV [BX+2],DX ;ADDR OF buf POP AX ;GET n ADD DX,AX MOV [BX+4],DX ;LAST ADDR ; ----- ; * ENABLE TXD INTERRUPT MOV BX,OFFSET INT_IER OR BYTE PTR [BX],2 ;TXD INT EN MOV AL,[BX] MOV DX,RS1B+1 ;IER OUT DX,AL POP DS POP ES POP DX POP BX POP AX MOV SP,BP POP BP RET _m_writ ENDP page ; int m_wait( void ); ; *** WAIT END OF TRANSFER TO COM1 ; IF OK -> int = 0, IF TIMEOUT -> int = 1 _m_wait PROC PUBLIC _m_wait PUSH BX PUSH CX PUSH DS ASSUME DS:@DATA MOV AX,@DATA MOV DS,AX MOV BX,OFFSET RS_WFLG MOV AX,1000 ; 6 sec WEOT: MOV CX,1000 LLKK: CMP BYTE PTR [BX],0 JE TIMEOK ;IF END OF TRANSFER LOOP LLKK DEC AX JNE WEOT ;WAIT END OF TRANSMIT ; *** ERROR -> 1 - DISABLE IR4 OF PIC ; 2 - RS_WFLG=0 (END OF WRITE) ; 3 - LAST ADDRESS TO OUT PTR IN AL,21H ;GET PIC IMR OR AL,10H ;IR3=0 OUT 21H,AL ;DISABLE IR4 MOV RS_WFLG,0 MOV BX,OFFSET RS_WOUT MOV AX,[BX+4] ;LAST ADDRESS MOV [BX+2],AX ;TO OUT POINTER MOV AX,1 ;TIMEOUT JMP TIMEOUT TIMEOK: MOV AX,0 ;IF OK TIMEOUT:POP DS POP CX POP BX RET _m_wait ENDP END