[net.sources] flow control daemon for PC

bmw@aesat.UUCP (Bruce Walker) (12/13/84)

/*NOTEATEN*/

(See net.micro.pc, same subject)

===========================  pull down, tear off  =============================
	page	60,132
	title	flowcntl - alter serial port com1 to use ^S/^Q handshaking

;   By: Bruce Walker
; Date: Oct 23, 1984
;  Mod: Oct 25, 1984
;
; I hereby give permission to do any damn thing you want with this program
; provided you don't try to blame me for anything naughty it might do.
; It would be nice if you left this title comment block intact if you
; modify it, but feel free to add your own name to the blameless list.
; If you manage to remove any restrictions or otherwise improve it, please
; repost the result.
;
; How to Use (and What it Does):
;
;	Set up a batch file (or edit AUTOEXEC.BAT) with a line to set the mode
;	of COM1: to the required baud rate, and follow it with a line to invoke
;	this program. eg:
;
;		mode com1:9600,N,8,1
;		flowcntl
;
;	which will drive a 9600 baud, no parity, eight data-bit and one stop
;	bit serial printer.
;
;	The program then loads itself into memory (where it remains until you
;	reboot) and intercepts any conversations with COM1 and controls the
;	output flow according to the time-honoured ^S/^Q (DC3/DC1 or XON/XOFF)
;	protocol.
;
;	To control a serial printer, add a line to redirect the LPT1: device
;	to the COM1: device. eg:
;
;		mode LPT1:=COM1:
;
;	Now, if you invoke the PRINT command, and hit return when it asks you
;	what device to use for output, your serial printer will buzz away
;	happily to itself, while DOS thinks it's talking to a parallel Epson.
;
;
; How To Make:
;
;	Do something like the following:
;
;		masm flowcntl,,,nul;
;		link flowcntl,,nul;
;		exe2bin flowcntl flowcntl.com
;		del flowcntl.exe
;		del flowcntl.obj
;
;	It has been tested with PC-DOS 2.1 and with printers up to 9600 baud.
;	Because it operates at the BIOS level, it should also work with early
;	DOS's like DOS 1.1 .
;
; Limitations:
;
;	- this is an unabashed hack (it is NOT a "device driver", it should be).
;	- uses ("user-definable") interrupt 60H; this may conflict with
;	  someone, somewhere.
;	- only uses com1:.
;	- does not work with BIOS-internal routines such as "PRINT_SCREEN" (I
;	  am not sure why) therefore the "<SHIFT> PrtSc" button should not be
;	  pressed.
;	- as a consequence of the above, Wordstar (for example) does not work
;	  with this code so don't invoke it when using Wordstar, just use WS's
;	  WINSTALL program to set up their internal serial printer drivers.


abs0	segment at 0		; this is where the interrupt vectors live

	org	50h		; int 14h - rs232 io handler vector
com_off dw	?
com_seg dw	?

	org	180h		; int 60h - user-definable (so I used it!)
int60_o dw	?
int60_s dw	?

abs0	ends

code segment

	assume cs:code, ds:abs0

	org	100h

main proc far	; set up pointers to intercept calls to rs232 handler
		;  and arrange for this piece of code to remain in memory
		;   forever after.

	xor	ax,ax		; ds := absolute 0 segment
	mov	ds,ax
	mov	ax,com_off	; copy rs232 vectors to int 60h
	mov	int60_o,ax
	mov	ax,com_seg
	mov	int60_s,ax
	cli			; copy pointer to new handler to int 14h
	mov	com_off,offset intercept
	mov	ax,cs
	mov	com_seg,ax
	sti
	mov	dx,offset next_byte	; point to end of program
	int	27h		; terminate but stay resident


id_code db	"FLOWCNTL V1.0 Bruce Walker 1984"
flag	db	'Q'-40h         ; ^S means stop - ^Q means go again

; Whenever someone calls the rs232 (int 14h) handler now, we intercept and
; if the call was a "test serial line status"-type (command code 3 in AH),
; check for control-S / control-Q handshaking from the serial device.  We
; translate the serial handshake into a "fake" CTS bit in the status register
; by setting or resetting the CTS status bit in AH as appropriate, and passing
; it back to the calling program.

intercept:
	sti
	push	ds
	push	cs		; set data seg to current code segment
	pop	ds

	assume ds:code

	or	dx,dx		; we only twiddle com1
	jz	com1
let_em_go:
	int	60h		; let call thru unaltered
beat_it:
	pop	ds
	iret

com1:
	cmp	ah,3		; status call?
	jne	let_em_go
	int	60h		; get status bytes into ax
	push	ax
	and	ah,01h		; any rx'ed chars?
	jz	c3
	mov	ah,2		; rx
	int	60h
	cmp	al,'S'-40h
	je	c2
	cmp	al,'Q'-40h
	jne	c3
c2:
	mov	byte ptr flag,al
c3:
	cmp	flag,'S'-40h
	pop	ax
	jne	c4
	and	al,10h		; CTS low
	jmp	beat_it
c4:
	or	al,10h		; CTS high
	jmp	beat_it

next_byte:

main	endp

code ends

	end	main
===========================  pull down, tear off  =============================

Bruce Walker     {allegra,ihnp4,linus,decvax}!utzoo!aesat!bmw