1dd8 ; RS232 routines ; ; ; Description Parameters ; ; comm_init(int port, Initialize com port ; int irq, ; long baud, ; int parity, ; int wordlen, ; int stopbits) ; ; comm_exit(void) De-initialize port None ; ; comm_send(char c) Send character if AX = 0 on return, ; Not clear to send ; ; int comm_rcv(void) Receive character if AX = 0 on return, ; No character waiting ; ; int comm_getflags(void) Get CTS, DSR and DCD AX on return contains ; status CTS in bit 2, DSR in bit 1 ; and DCD in bit 0 ; ;============================================================================ .MODEL SMALL .386 .DATA? Org_Int dword ? portadr word ? irq word ? irqmask byte ? intadr word ? _cts word ? _dsr word ? _dcd word ? charsnt word ? comm_buf byte 10000 DUP(?) .DATA bufhead word 0 buftail word 0 _overrun word 0 int_type word modemstat_int, thre_int, datavail_int, linestat_int .CODE PUBLIC _comm_init, _comm_exit PUBLIC _comm_send, _comm_rcv PUBLIC _comm_getflags _comm_init PROC push bp mov bp, sp push si push di push es cli mov ebx, [bp+8] ;Get baudrate xor edx, edx ;Divide 115200 with baudrate mov eax, 0001C200h ;to get divisor div ebx mov bx, ax ;Store divisor in bx for now xor ax, ax mov dx, [bp+12] ;Get parity cmp dl, 0 jz no_p cmp dl, 1 jz even_p no_p: or al, 00100000b jmp over_p even_p: or al, 00111000b over_p: mov dx, [bp+14] ;Get Word length cmp dx, 7 jz w7 cmp dx, 8 jz w8 w7: or al, 02h jmp over_w w8: or al, 03h over_w: mov dx, [bp+16] ;Stopbits cmp dx, 1 jz s1 cmp dx, 2 jz s2 s1: or al, 00000000b jmp over_s s2: or al, 00000100b over_s: mov dx, [bp+4] ;Port address mov portadr, dx add dx, 3 ;Line control register (xxB) or al, 080h ;Set divisor latch access bit out dx, al ;Out with Async parameters+latch bit sub dx, 3 ;Now set baudrate divisor in xx8 and xx9 mov al, bl out dx, al ;Divisor LSB to xx8 inc dx mov al, bh out dx, al ;Divisor MSB to xx9 add dx, 2 in al, dx and al, 07fh ;Clear divisor latch access bit in xxB... out dx, al sub dx, 2 mov al, 0Fh ;To be able to set interrupt bits in IER out dx, al add dx, 3 ;Activate tri-state gate between mov al, 0fh ;UART and PIC (OUT2) out dx, al ;------------------- mov dx, [bp+6] ;IRQ number mov irq, dx mov ax, 08h cmp dx, 8 jb not_high mov ax, 70h sub dx, 8 not_high: add ax, dx mov intadr, ax mov dx, 0 mov es, dx shl ax, 2 mov di, ax mov dx, word ptr es:[di] mov word ptr[Org_Int], dx ;Save Org_Rutin OFFSET mov dx, word ptr es:[di+2] mov word ptr[Org_Int+2], dx ;Save Org_Rutin Segment mov ax, OFFSET New_Comm_Int ;Install new routine stosw mov ax, cs stosw ;------------- mov cx, irq ;Build IRQ mask cmp cx, 8 jb not_hi1 shr cx, 8 not_hi1: mov ah, 1 shl ah, cl not ah ;IRQ mask now in ah mov irqmask, ah mov dx, 21h cmp irq, 8 jb not_hi2 add dx, 80h not_hi2: in al, dx and al, ah ;Mask off IRQ out dx, al mov ah, 7fh clean_lp: mov dx, portadr in al, dx ;Reset RBR add dx, 2 in al, dx ;Reset IIR add dx, 3 in al, dx ;Reset LSR inc dx in al, dx ;Reset MSR sub dx, 4 in al, dx test al, 1 ;Check if pending interrupt jnz all_clean dec ah jnz clean_lp all_clean: sti mov dx, portadr ;Get initial CTS,DCD and DSR status add dx, 6 in al, dx xor ah, ah mov dx, ax shr ax, 4 and ax, 1 mov _cts, ax mov ax, dx shr ax, 5 and ax, 1 mov _dsr, ax mov ax, dx shr ax, 7 and ax, 1 mov _dcd, ax pop es pop di pop si pop bp mov ax, 1 ret _comm_init ENDP _comm_exit PROC push di push es cli mov dx, portadr ;Reset interrupt bits in IER register inc dx mov al,0 out dx, al add dx, 3 ;Desactivate tri-state gate mov al, 0h ;UART and PIC (OUT2) out dx, al mov ah,irqmask not ah mov dx, 21h cmp irq, 8 jb not_hi4 add dx, 80h not_hi4: in al, dx or al, ah ;Mask off IRQ out dx, al mov ax, intadr mov dx, 0 ;Restore old comm routine mov es, dx shl ax, 2 mov di, ax mov ax, word ptr[Org_Int] stosw mov ax, word ptr[Org_Int+2] stosw pop es pop di sti ret _comm_exit ENDP _comm_send PROC xor ax, ax cmp _cts, 1 jnz not_cts push bp mov bp, sp mov charsnt, 0 mov dx, portadr mov al, byte ptr[bp+4] out dx, al wait_charsnt: cmp charsnt, 1 jnz wait_charsnt pop bp not_cts: ret _comm_send ENDP _comm_rcv PROC push si xor ax,ax mov si,buftail cmp si,bufhead jz no_char_in_buffer mov al, comm_buf[si] ;Get byte from ring buffer mov ah, 0ffh inc si cmp si, 9999 jbe no_twrap mov si,0 no_twrap: mov buftail, si no_char_in_buffer: pop si ret _comm_rcv ENDP _comm_getflags PROC mov ax, 0 or ax, _cts shl ax, 1 or ax, _dsr shl ax, 1 or ax, _dcd ret _comm_getflags ENDP New_Comm_Int PROC FAR push ax push dx push ds push si mov ax, @data mov ds, ax next_int: mov dx, portadr add dx, 2 ;Interrupt id register in al, dx test al, 1 ;Check for pending interrupt jnz exit_int and ax, 0Eh xor si, si mov si, ax jmp int_type[si] ;-------------------------------------------------------------------- modemstat_int: add dx, 4 ;Read modem status register in al, dx test al, 1 jz m1 jmp DCTS m1: test al, 2 jz m2 jmp DDSR m2: test al, 4 jz m3 jmp TERI m3: test al, 8 jz m4 jmp DDCD m4: jmp next_int DCTS: mov dx, ax shr dx, 4 and dx, 1 mov _cts, dx jmp m1 DDSR: mov dx, ax shr dx, 5 and dx, 1 mov _dsr, dx jmp m2 TERI: jmp m3 DDCD: mov dx, ax shr dx, 7 and dx, 1 mov _dcd, dx jmp m4 CTS: DSR: RI: DCD: ;------------------------------------------------------------------- thre_int: mov charsnt, 1 jmp next_int ;------------------------------------------------------------------- datavail_int: sub dx, 2 ;read received byte in al, dx mov si, bufhead mov byte ptr comm_buf[si], al ;store byte in receive ring buffer inc si cmp si, 9999 jbe no_hwrap xor si, si no_hwrap: mov bufhead, si jmp next_int ;-------------------------------------------------------- linestat_int: add dx, 3 ;Read line status register in al, dx test al, 1 jz l1 jmp DR l1: test al, 2 jz l2 jmp OE l2: test al, 4 jz l3 jmp PE l3: test al, 8 jz l4 jmp FE l4: test al, 16 jz l5 jmp BI l5: jmp next_int DR: jmp l1 OE: mov _overrun, 1 jmp l2 PE: jmp l3 FE: jmp l4 BI: jmp l5 THRE: TSRE: ;-------------------------------------------------------------------------- exit_int: sti mov al, 20h cmp irq, 8 jb not_hi_irq out 0a0h, al not_hi_irq: out 020h, al pop si pop ds pop dx pop ax iret New_Comm_Int ENDP END . 0