home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS - Coast to Coast
/
simteldosarchivecoasttocoast.iso
/
io_util
/
tandy232.asm
< prev
next >
Wrap
Assembly Source File
|
1994-03-04
|
9KB
|
363 lines
;----------------------------------------------------------------------------
;
; Replacement for the Tandy 2000 RS232 handler
;
; Copyright 1985 by John McNamee.
;
; This software is made available for non-commercial use. If I find
; you selling it, my lawyers will teach you a lesson in the copyright
; laws that you will never forget.
;
;----------------------------------------------------------------------------
;
; There are some differences between these routines and the BIOS.
; I do not check Data Set Ready, or any other modem status, before
; sending characters. If the UART is ready, I send the character.
; This makes it easier to do machine-to-machine hardwire connections.
; I do not fully implement the XON/XOFF processing. Only "HOST" type
; processing is done: if the other side sends an XOFF to the 2000, I
; stop transmitting until I get an XON. Nothing is done if the 2000
; input buffer fills up; no XOFF is sent, and excess characters are
; just ignored. This was the easiest way to implement things, and
; should be OK for most people. It should be noted that the IBM PC
; doesn't do either type, so many programs handle all their own
; XON/XOFF processing already.
;
;----------------------------------------------------------------------------
bufsiz equ 256 ;Size of input buffer
code segment public 'code'
assume cs:code, ds:code
org 100h
entry: jmp setup
;----------------------------------------------------------------------------
; Runtime data area
;----------------------------------------------------------------------------
port12: db ? ;Copy of last byte sent to port 12
hold: db ? ;XON/XOFF status flags
inptr: dw ? ;Buffer input pointer
outptr: dw ? ;Buffer output pointer
inbuf: db bufsiz dup (?)
;----------------------------------------------------------------------------
; INT 14 handler
;----------------------------------------------------------------------------
int14 proc near
push bx
push cx
push dx
push ds
push cs
pop ds ;DS=CS
cmp ah,00 ;Reset Comm Port
jnz not_0
and ah,3 ;We only want bits 0 and 1
mov byte ptr hold,dh ;Set XON/XOFF flags
pushf
db 9Ah ;Opcode for long jump
oldint: dw ?,?
call flush ;Flush the buffer
mov al,36h ;Disable transmitter
call outctl ;Output to control port
call stat
jmp exit14
not_0: cmp ah,01 ;Transmit Character
jnz not_1
call send
jmp exit14
not_1: cmp ah,02 ;Receive Character
jnz not_2
call recv
jmp exit14
not_2: cmp ah,03 ;Get Current Comm Status
jnz not_3
call stat
jmp exit14
not_3: cmp ah,04 ;Flush Comm Buffer
jnz exit14
call flush
exit14: pop ds
pop dx
pop cx
pop bx
iret
int14 endp
;----------------------------------------------------------------------------
; Send a character
;----------------------------------------------------------------------------
send proc near
push ax
mov al,37h ;Enable transmitter
call outctl
mov cx,0000 ;Timeout counter
mov dl,2
wait1: in al,12h ;Get UART status
test al,01 ;UART ready?
jz wait2
test byte ptr hold,10h ;Is "stop transmitting" flag set?
jz send1
wait2: loop wait1
dec dl ;Bump counter
jnz wait1
pop ax
call stat ;Get status
or ah,80h ;Set timeout error
ret
send1: pop ax
out 10h,al ;Send character
call stat ;Return status
ret
send endp
;----------------------------------------------------------------------------
; Receive a character
;----------------------------------------------------------------------------
recv proc near
cli
mov bx,outptr
cmp bx,inptr ;Is buffer empty?
jnz recv1
sti ;Allow interrupt to happen
nop
nop
jmp recv ;Go back and try again
recv1: mov al,cs:[bx] ;Get character
inc bx
cmp bx,offset inbuf+bufsiz ;At end of buffer?
jnz recv2
mov bx,offset inbuf ;Wrap around
recv2: mov outptr,bx
mov ah,00h ;No errors returned
sti
ret
recv endp
;----------------------------------------------------------------------------
; Flush input buffer
;----------------------------------------------------------------------------
flush proc near
cli
and dh,3
mov byte ptr hold,dh
mov ax,offset inbuf
mov outptr,ax
mov inptr,ax
sti
ret
flush endp
;----------------------------------------------------------------------------
; Get status
;----------------------------------------------------------------------------
stat proc near
xor ah,ah
push bx
cli
mov bx,inptr
cmp bx,outptr
sti
pop bx
jz stat1
or ah,01h ;There is data in the buffer
stat1: in al,12h ;Get UART status
push ax
mov al,byte ptr port12 ;Get last value sent to UART
call outctl ;Send it again to clear error status
pop ax
test al,10h ;Overrun error?
jz stat2
or ah,02h
stat2: test al,08h ;Parity error?
jz stat3
or ah,04h
stat3: test al,20h ;Framing error?
jz stat4
or ah,08h
stat4: test al,08h ;Break detected?
jz stat5
or ah,10h
stat5: test al,01h ;TxRDY?
jz stat6
or ah,60h
stat6: mov al,20h ;Fake modem status (CTS and DSR set)
ret
stat endp
;----------------------------------------------------------------------------
; INT 72 handler
;----------------------------------------------------------------------------
int72 proc near
cli
push ax
push bx
push cx
push dx
push ds
push cs
pop ds ;DS = CS
; Get UART status. Check if a received character is ready.
in al,12h
test al,02h
jz exit72
; Get character from UART and stuff in buffer
in al,10h
push ax
and al,7Fh ;Strip parity
test byte ptr hold,02 ;Should we do XON/XOFF processing?
jz int72b
cmp al,'S'-40h ;Did we get an XOFF?
jne int72a
or byte ptr hold,10h ;Set "stop transmitting" flag
pop ax
jmp exit72
int72a: cmp al,'Q'-40h ;Did we get an XON?
jne int72b
and byte ptr hold,0EFh ;Clear "stop transmitting" flag
pop ax
jmp exit72
int72b: pop ax
mov bx,inptr ;Get buffer input pointer
mov [bx],al ;Store character in buffer
inc bx
cmp bx,offset inbuf+bufsiz ;At end of buffer
jnz ckfull
mov bx,offset inbuf ;Wrap around
ckfull: cmp bx,outptr ;Buffer full?
jz exit72
mov inptr,bx
; Clear interrupt and return
exit72: mov al,36h ;Leave transmitter disabled
call outctl
mov dx,0060h
mov al,20h
out dx,al
mov al,0Bh
out dx,al ;Clear 8259 interrupt controler
sti
nop
nop
in al,dx
or al,al
jnz not186
cli
mov dx,0FF22h
mov ax,8000h
out dx,ax ;Clear 186 interrupt controler
not186: sti
pop ds
pop dx
pop cx
pop bx
pop ax
iret
int72 endp
;----------------------------------------------------------------------------
; Output byte to UART control port
;----------------------------------------------------------------------------
outctl proc near
out 12h,al
mov byte ptr port12,al
ret
outctl endp
;----------------------------------------------------------------------------
; Initialize everything
;----------------------------------------------------------------------------
setup proc near
push cs
pop ds ;DS=CS
; Test version number
mov ah,30h
int 21h ;GetVersion
cmp ax,0B02h ;Is it 02.11.xx?
jz ver_ok
mov dx,offset badver
call prtmsg ;Print bad version message
mov ax,4C01h
int 21h ;Exit
ver_ok:
; Get old vector
mov ax,3514h ;Get vector for INT 14h
int 21h
mov oldint+2,es ;Save old interrupt segment
mov oldint,bx ;Save old interrupt offset
mov ax,es
cmp ax,0060h ;Already installed
jz not_in
mov dx,offset inserr
call prtmsg ;Print already installed message
mov ax,4C01h
int 21h ;Exit
not_in:
; Setup pointers
cli ;We need silence for this next trick
xor al,al
mov byte ptr hold,al
mov ax,offset inbuf
mov inptr,ax ;Set input pointer
mov outptr,ax ;Set output pointer
; Install new vectors
mov ax,2514h ;Set vector for INT 14h
mov dx,offset int14
int 21h
mov ax,2553h ;Set vector for INT 53h
int 21h
mov ax,2572h ;Set vector for INT 72h
mov dx,offset int72
int 21h
sti
; Initialize RS232 port to 300 baud, 8 bits, No parity, 1 stop bit
mov ah,00h
mov al,43h
mov dx,0000h
int 14h
; Let the user know everything is OK and exit
mov dx,offset insmsg
call prtmsg ;Print installed message
mov ax,offset setup ;First byte after resident code
mov cl,4
shr ax,cl ;Turn into paragraph count
inc ax ;Keep one extra paragraph
mov dx,ax ;DX=final paragraph count
mov ax,3100h ;Keep process
int 21h
setup endp
;----------------------------------------------------------------------------
; Print message
;----------------------------------------------------------------------------
prtmsg proc near
mov ah,09
int 21h
ret
prtmsg endp
db 'Copyright 1985 by John McNamee.'
insmsg: db 13,10,'RS232 fix for Tandy 2000 BIOS installed.',13,10,'$'
badver: db 13,10,'This fix is only needed on MSDOS 02.11.02!',13,10,'$'
inserr: db 13,10,'RS232 fix already installed!',13,10,'$'
code ends
end entry