home *** CD-ROM | disk | FTP | other *** search
- ;----------------------------------------------------------------------------
- ;
- ; 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
-