;---------------------------------------------------------------------------- ; ; 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