|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T U
Length: 53435 (0xd0bb)
Types: TextFile
Notes: Uncompressed file
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
└─⟦3e7b51185⟧ »EurOpenD3/network/uupc/uupc.dos.8.7.Z«
└─⟦this⟧
From uucp Wed Aug 12 02:39 PDT 1987
>From slynne Wed Aug 12 02:38:30 1987 remote from slmac
Received: by van-bc.uucp (smail2.3)
id AA17570; 12 Aug 87 02:38:30 PDT (Wed)
Received: by slmac.vnet.van-bc.uucp (pcmail) Wed Aug 12 02:37:07 1987
Date: Wed Aug 12 02:37:07 1987
From: Stuart Lynne - test a mac <slynne@slmac.vnet.van-bc.uucp>
Message-ID: <148@slmac.vnet.van-bc.uucp>
To: sl@van-bc
Subject: shar/uupc.dos.8.7
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# dos/README.DOS
# dos/Makefile.dos
# dos/comm.asm
# dos/comm.h
# dos/host.c
# dos/host.h
# dos/mlib.c
# dos/ndir.c
# dos/ndir.h
# dos/setup.bat
# dos/ulib.c
# This archive created: Wed Aug 12 02:03:59 1987
# By: Stuart Lynne - test a mac ()
export PATH; PATH=/bin:$PATH
if test -f 'dos/README.DOS'
then
echo shar: will not over-write existing file "'dos/README.DOS'"
else
cat << \SHAR_EOF > 'dos/README.DOS'
DOS August 3, 1987 Samuel Lam
This file describes the IBM-PC/DOS support for uupc.
After unpacking this shell-archive, you will have a set of files
in the subdirectory "dos". The eventual destinations of these
files and description of their content are shown below. (The
current directory is assumed to be the uupc source directory.)
Makefile - Makefile for the complete uupc project. This makefile
should be used with NDMAKE 4.0 and Microsoft C 4.0.
local\host.h - MS-DOS host header file.
local\host.c - Generic main program and routines used by both.
local\mlib.c - Routines used only by the uu program.
local\ulib.c - Routines used only by the mail program.
local\ndir.h - Directory scanning routines header file.
local\ndir.c - "Berkeley-style" directory scanning routines.
Setup.Bat - Template batch file for configuring your uupc node.
This should be edited appropriately before use.
To build a production copy of uupc from the distributed sources.
You will have to unpacking the two shell-archives containing the
sources for uu and mail into an empty work directory, create a
new subdirectory named "local" in this work directory, install
the content of the "dos" directory as described above, and then
issue a "make all" from within the work directory.
This, of course, assume that you have both Microsoft C 4.0 and
NDMAKE 4.0 (shareware by D. G. Kneller) installed on your
machine. Note that the "make" that was bundled with Microsoft C
is not an acceptable substitute for NDMAKE in this case. (The
makefile formats are not compatible between the two.)
This implementation of uupc has been tested on a regular IBM-PC
running PC-DOS 2.10. It should have no problem running with
newer versions of PC-DOS or MS-DOS.
Both uu and mail will run within 64K of free memeory and/or on a
single floppy-drive system. Although performance could be
significantly improved by using a harddisk and/or RAMdisk for the
data directories, the throughput on a minimaly configured system
is still fairly acceptable.
Although mail will work on basically any MS-DOS machine, uu will
only run on systems with an IBM-PC compatible serial port (i.e.
it must be compatible at the UART level) since uu drives the
serial port directly using its own interrupt driven I/O routines
when it talks to the remote system.
Currently, the mailboxes used by mail are being managed as binary
files, with line-feed instead of carriage-return and line-feed
being the line separator. Therefore, MS-DOS text file copies of
incoming messages can only be obtained through the s (save) and w
(write) commands in mail.
If you would like a copy of your mailbox to always be accessible
from your favorite text-editor in DOS, you might want to use the
s (save) command to archive all incoming messages to a text
archive file as soon as they arrive in your mailbox.
Pre-composed MS-DOS text files can be sent as messages without
any problems by simply using DOS' command line I/O redirection
facilities. e.g. mail user@host < textfile
When typing a message directly into mail through the keyboard, a
Control-Z (the MS-DOS end-of-file character) should be used to
generate an end-of-file to terminate the message input.
Since the MS-DOS file system (unlike UNIX) does not differentiate
between upper and lower cases file names, currently the system
names of all the systems which you have a direct connection to
must be in lowercase. i.e. All system names in the "systems"
file must be in all lowercase. This restriction does not apply
to systems which are more than one node away from your system.
The port specification in a systems file entry should be either
COM1 or COM2, which represents the serial ports at the port
addresses 0x3f8 and 0x2f8 respectively. Cases are significant in
port specifications. The line speed specification in the systems
file entry can specify any common baud rate up to 19200 bps.
For IBM-PC/DOS related uupc information, bug fixes, comments and
suggestions, please e-mail to:
UUCP: {seismo,ihnp4!alberta,uw-beaver}!ubc-vision!van-bc!sklpc!skl
Internet: <skl@sklpc.vnet.van-bc.UUCP>
-------
SHAR_EOF
chmod +x 'dos/README.DOS'
fi # end of overwriting check
if test -f 'dos/Makefile.dos'
then
echo shar: will not over-write existing file "'dos/Makefile.dos'"
else
cat << \SHAR_EOF > 'dos/Makefile.dos'
# Makefile for DCP by SKL, July/87
all: uupc mail
# The UUCP transport service program (an uucico work-alike)
UUOBJS=uuhost.obj dcp.obj dcpsys.obj dcpxfer.obj dcpgpkt.obj rmail.obj\
ulib.obj lib.obj comm.obj local\ndir.obj
uupc: uupc.exe
uupc.exe: $(UUOBJS)
link $(LFLAGS) /NOI /STACK:4096 $(UUOBJS),$@;
uuhost.obj: uuhost.c local\host.c host.h local\host.h
msc $(CFLAGS) $*;
dcp.obj: dcp.c dcp.h host.h local\host.h
msc $(CFLAGS) $*;
dcpsys.obj: dcpsys.c dcp.h host.h ndir.h local\host.h local\ndir.h
msc $(CFLAGS) $*;
dcpxfer.obj: dcpxfer.c dcp.h host.h local\host.h
msc $(CFLAGS) $*;
dcpgpkt.obj: dcpgpkt.c dcp.h host.h local\host.h
msc $(CFLAGS) $*;
rmail.obj: rmail.c pcmail.c host.h local\host.h
msc $(CFLAGS) $*;
ulib.obj: ulib.c local\ulib.c dcp.h comm.h
msc $(CFLAGS) $*;
comm.obj: comm.asm
masm /MX comm;
local\ndir.obj: local\ndir.c local\ndir.h
msc $(CFLAGS) local\ndir.c,local\ndir.obj;
# The mailer UA program (a mail work-alike)
MAILOBJS=mailhost.obj mail.obj lmail.obj mlib.obj lib.obj
mail: mail.exe
mail.exe: $(MAILOBJS)
link /NOI /STACK:4096 $(LFLAGS) $(MAILOBJS),$@;
lmail.obj: lmail.c pcmail.c host.h local\host.h
msc $(CFLAGS) $*;
mailhost.obj: mailhost.c local\host.c host.h local\host.h
msc $(CFLAGS) $*;
mail.obj: mail.c host.h local\host.h
msc $(CFLAGS) $*;
mlib.obj: mlib.c local\mlib.c
msc $(CFLAGS) $*;
# The common stuff
lib.obj: lib.c
msc $(CFLAGS) $*;
SHAR_EOF
chmod +x 'dos/Makefile.dos'
fi # end of overwriting check
if test -f 'dos/comm.asm'
then
echo shar: will not over-write existing file "'dos/comm.asm'"
else
cat << \SHAR_EOF > 'dos/comm.asm'
TITLE COM_PKG2 -- Last updated 10/6/85
PAGE 75,132
;
; modified to use MSC calling sequence.
; jrr 3/86
;
; Communications Package for the IBM PC, XT, AT and PCjr
; and strict compatibles.
; May be copied and used freely -- This is a public domain program
; Developed by Richard Gillmann, John Romkey, Jerry Saltzer,
; Craig Milo Rogers, Dave Mitton and Larry Afrin.
;
; We'd sure like to see any improvements you might make.
; Please send all comments and queries about this package
; to GILLMANN@USC-ISIB.ARPA
;
; o Supports both serial ports simultaneously
; o All speeds to 19200 baud
; o Compatible with PC, XT, AT and PCjr.
; o Built in XON/XOFF flow control option
; o Assembly language calling conventions
; o Logs all comm errors
; o Direct connect or modem protocol
;
; MAXIMUM BUFFER SIZES
R_SIZE EQU 500 ; SIZE OF RECEIVE BUFFERS
S_SIZE EQU 500 ; SIZE OF TRANSMIT BUFFERS rhl/4/86
; INTERRUPT NUMBERS
INT_COM1 EQU 0CH ; COM1: FROM 8259
INT_COM2 EQU 0BH ; COM2: FROM 8259
; 8259 PORTS
INTA00 EQU 20H ; 8259A PORT, A0 = 0
INTA01 EQU 21H ; 8259A PORT, A0 = 1
; COM1: LEVEL 4
IRQ4 EQU 2*2*2*2 ; 8259A OCW1 MASK, M4=1, A0=0
NIRQ4 EQU NOT IRQ4 AND 0FFH ; COMPLEMENT OF ABOVE
EOI4 EQU 4 OR 01100000B ; 8259A OCW2 SPECIFIC IRQ4 EOI, A0=0
; COM2: LEVEL 3
IRQ3 EQU 2*2*2 ; 8259A OCW1 MASK, M3=1, A0=0
NIRQ3 EQU NOT IRQ3 AND 0FFH ; COMPLEMENT OF ABOVE
EOI3 EQU 3 OR 01100000B ; 8259A OCW2 SPECIFIC IRQ3 EOI, A0=0
; FLOW CONTROL CHARACTERS
CONTROL_Q EQU 11H ; XON
CONTROL_S EQU 13H ; XOFF
; MISC.
DOS EQU 21H ; DOS FUNCTION CALLS
PAGE
;
; ROM BIOS Data Area
;
RBDA SEGMENT AT 40H
RS232_BASE DW 4 DUP(?) ; ADDRESSES OF RS232 ADAPTERS
RBDA ENDS
;
; ROM PC-Type IDENT
;
ROM SEGMENT AT 0F000H
ORG 0FFFEH
ROMID DB ? ; 0FFH=PC OR EARLY XT, 0FEH=XT, 0FDH=JR
ROM ENDS
PAGE
;
; TABLE FOR EACH SERIAL PORT
;
SP_TAB STRUC
PORT DB ? ; 1 OR 2
; PARAMETERS FOR THIS INTERRUPT LEVEL
INT_COM DB ? ; INTERRUPT NUMBER
IRQ DB ? ; 8259A OCW1 MASK
NIRQ DB ? ; COMPLEMENT OF ABOVE
EOI DB ? ; 8259A OCW2 SPECIFIC END OF INTERRUPT
; INTERRUPT HANDLERS FOR THIS LEVEL
INT_HNDLR DW ? ; OFFSET TO INTERRUPT HANDLER
OLD_COM_OFF DW ? ; OLD HANDLER'S OFFSET
OLD_COM_SEG DW ? ; OLD HANDLER'S SEGMENT
; ATTRIBUTES
INSTALLED DB ? ; IS PORT INSTALLED ON THIS PC? (1=YES,0=NO)
BAUD_RATE DW ? ; 19200 MAX
CONNECTION DB ? ; M(ODEM), D(IRECT)
PARITY DB ? ; N(ONE), O(DD), E(VEN), S(PACE), M(ARK)
STOP_BITS DB ? ; 1, 2
XON_XOFF DB ? ; E(NABLED), D(ISABLED)
; FLOW CONTROL STATE
HOST_OFF DB ? ; HOST XOFF'ED (1=YES,0=NO)
PC_OFF DB ? ; PC XOFF'ED (1=YES,0=NO)
; ERROR COUNTS
ERROR_BLOCK DW 8 DUP(?) ; EIGHT ERROR COUNTERS
; 8250 PORTS
DATREG DW ? ; DATA REGISTER
IER DW ? ; INTERRUPT ENABLE REGISTER
IIR DW ? ; INTERRUPT IDENTIFICATION REGISTER
LCR DW ? ; LINE CONTROL REGISTER
MCR DW ? ; MODEM CONTROL REGISTER
LSR DW ? ; LINE STATUS REGISTER
MSR DW ? ; MODEM STATUS REGISTER
; BUFFER POINTERS
START_TDATA DW ? ; INDEX TO FIRST CHARACTER IN X-MIT BUFFER
END_TDATA DW ? ; INDEX TO FIRST FREE SPACE IN X-MIT BUFFER
START_RDATA DW ? ; INDEX TO FIRST CHARACTER IN REC. BUFFER
END_RDATA DW ? ; INDEX TO FIRST FREE SPACE IN REC. BUFFER
; BUFFER COUNTS
SIZE_TDATA DW ? ; NUMBER OF CHARACTERS IN X-MIT BUFFER
SIZE_RDATA DW ? ; NUMBER OF CHARACTERS IN REC. BUFFER
; BUFFERS
TDATA DB S_SIZE DUP(?) ; SEND BUFFER
RDATA DB R_SIZE DUP(?) ; RECEIVE BUFFER
SP_TAB ENDS
; SP_TAB EQUATES
; WE HAVE TO USE THESE BECAUSE OF PROBLEMS WITH STRUC
EOVFLOW EQU ERROR_BLOCK ; BUFFER OVERFLOWS
EOVRUN EQU ERROR_BLOCK+2 ; RECEIVE OVERRUNS
EBREAK EQU ERROR_BLOCK+4 ; BREAK CHARS
EFRAME EQU ERROR_BLOCK+6 ; FRAMING ERRORS
EPARITY EQU ERROR_BLOCK+8 ; PARITY ERRORS
EXMIT EQU ERROR_BLOCK+10 ; TRANSMISSION ERRORS
EDSR EQU ERROR_BLOCK+12 ; DATA SET READY ERRORS
ECTS EQU ERROR_BLOCK+14 ; CLEAR TO SEND ERRORS
DLL EQU DATREG ; LOW DIVISOR LATCH
DLH EQU IER ; HIGH DIVISOR LATCH
PAGE
; put the data in the DGROUP segment
; far calls enter with DS pointing to DGROUP
;
DGROUP GROUP _DATA
_DATA SEGMENT PUBLIC 'DATA'
;
DIV50PC EQU 2304 ; DIVISOR FOR 50 BAUD (PC,XT)
DIV50JR EQU 2237 ; DIVISOR FOR 50 BAUD (JR)
DIV50 DW 2304 ; ACTUAL DIVISOR FOR 50 BAUD IN USE
CURRENT_AREA DW AREA1 ; CURRENTLY SELECTED AREA
; DATA AREAS FOR EACH PORT
AREA1 SP_TAB <1,INT_COM1,IRQ4,NIRQ4,EOI4> ; COM1 DATA AREA
AREA2 SP_TAB <2,INT_COM2,IRQ3,NIRQ3,EOI3> ; COM2 DATA AREA
_DATA ENDS
PAGE
COM_TEXT SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:COM_TEXT,DS:DGROUP,ES:NOTHING
PUBLIC _select_port
PUBLIC _save_com
PUBLIC _install_com
PUBLIC _restore_com
PUBLIC _open_com
PUBLIC _close_com
PUBLIC _dtr_on
PUBLIC _dtr_off
PUBLIC _r_count
PUBLIC _s_count
PUBLIC _receive_com
PUBLIC _send_com
PUBLIC _sendi_com
PUBLIC _send_local
PUBLIC _break_com
PUBLIC _com_errors
PAGE
;
; SELECT WHICH PORT IS TO BE "ACTIVE"
; [bp+6] = port number
_select_port PROC FAR
push bp
mov bp,sp
mov AX,[bp+6] ; get aguement
TEST AL,1 ; FIRST PORT?
JZ SP1 ; IF NOT, IT MUST BE SECOND PORT
MOV AX,OFFSET DGROUP:AREA1 ; SELECT COM1 DATA AREA
JMP SHORT SPX ; CONTINUE
SP1: MOV AX,OFFSET DGROUP:AREA2 ; SELECT COM2 DATA AREA
SPX: MOV CURRENT_AREA,AX ; SET SELECTION IN MEMORY
mov sp,bp
pop bp
RET ; DONE
_select_port ENDP
PAGE
;
; SAVE ORIGINAL COM VECTOR
;
_save_com PROC FAR
push bp
mov bp,sp
push si
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
PUSH ES ; SAVE EXTRA SEGMENT
MOV AREA1.INT_HNDLR,OFFSET INT_HNDLR1
MOV AREA2.INT_HNDLR,OFFSET INT_HNDLR2
MOV AH,30H ; GET DOS VERSION NUMBER
INT DOS ; DOS FUNCTION
CMP AL,2 ; AT LEAST DOS 2?
JB SVC1 ; JUMP IF DOS 1
; SAVE OLD VECTOR WITH DOS 2 CALLS
MOV AH,35H ; FETCH INTERRUPT VECTOR CONTENTS
MOV AL,INT_COM[SI] ; INTERRUPT NUMBER
INT DOS ; DOS 2 FUNCTION
MOV OLD_COM_OFF[SI],BX ; SAVE
MOV BX,ES ; ES:BX
MOV OLD_COM_SEG[SI],BX ; FOR LATER RESTORATION
JMP SHORT SVCX ; DONE
; SAVE OLD VECTOR WITH DOS 1 CALLS
SVC1: MOV AX,0 ; ZERO SEGMENT
MOV ES,AX ; ES POINTS TO INTERRUPT VECTORS
MOV BL,INT_COM[SI] ; OUR INTERRUPT NUMBER
MOV BH,0 ; BL -> BX
SHL BX,1 ; TIMES FOUR
SHL BX,1 ; IS OFFSET OF VECTOR IN MEMORY
MOV AX,WORD PTR ES:[BX] ; SAVE
MOV OLD_COM_OFF[SI],AX ; THE
ADD BX,2 ; OLD
MOV AX,WORD PTR ES:[BX] ; INTERRUPT
MOV OLD_COM_SEG[SI],AX ; VECTOR
SVCX: POP ES ; RESTORE ES
pop si
mov sp,bp
pop bp
RET ; DONE
_save_com ENDP
PAGE
;
; INSTALL_COM: INSTALL THE ACTIVE PORT
;
; SET 8250 PORTS FROM RS-232 BASE IN ROM BIOS DATA AREA
; INITIALIZE PORT CONSTANTS AND ERROR COUNTS
; INSTALL INTERRUPT VECTOR
;
; return ax=1 on success ax=0 on failure
;
_install_com PROC FAR
push bp
mov bp,sp
push si
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
PUSH ES ; SAVE EXTRA SEGMENT
CMP INSTALLED[SI],1 ; ALREADY INSTALLED?
JNE INSTOK ; NO, CONTINUE
JMP INSTX ; ELSE JUMP IF ALREADY INSTALLED
; CLEAR ERROR COUNTS
INSTOK: MOV WORD PTR EOVFLOW[SI],0 ; BUFFER OVERFLOWS
MOV WORD PTR EOVRUN[SI],0 ; RECEIVE OVERRUNS
MOV WORD PTR EBREAK[SI],0 ; BREAK CHARS
MOV WORD PTR EFRAME[SI],0 ; FRAMING ERRORS
MOV WORD PTR EPARITY[SI],0 ; PARITY ERRORS
MOV WORD PTR EXMIT[SI],0 ; TRANSMISSION ERRORS
MOV WORD PTR EDSR[SI],0 ; DATA SET READY ERRORS
MOV WORD PTR ECTS[SI],0 ; CLEAR TO SEND ERRORS
; SENSE PC TYPE AND SET DIVISOR ACCORDINGLY
MOV BX,ROM ; HIGH ROM SEGMENT
MOV ES,BX ; TO ES
ASSUME ES:ROM
MOV DIV50,DIV50PC ; ASSUME PC OR XT
CMP ROMID,0FDH ; IS IT A PCjr?
JNE INST0 ; JUMP IF NOT
MOV DIV50,DIV50JR ; ELSE SET JR DIVISOR
; SET 8250 PORT ADDRESSES
INST0: MOV BX,RBDA ; ROM BIOS DATA AREA
MOV ES,BX ; TO ES
ASSUME ES:RBDA
TEST PORT[SI],1 ; PORT 1?
JZ INST1 ; JUMP IF NOT
MOV AX,3F8H ; COM1 BASE PORT ADDRESS
JMP SHORT INST2 ; CONTINUE
INST1: MOV AX,2F8H ; COM2 BASE PORT ADDRESS
INST2: CMP AX,RS232_BASE ; INSTALLED?
JE INST2A ; JUMP IF SO
CMP AX,RS232_BASE+2 ; INSTALLED?
JNE INST666 ; JUMP IF NOT
INST2A: MOV BX,DATREG ; OFFSET OF TABLE OF PORTS
MOV CX,7 ; LOOP SIX TIMES
INST3: MOV WORD PTR [SI][BX],AX ; SET PORT ADDRESS
INC AX ; NEXT PORT
ADD BX,2 ; NEXT WORD ADDRESS
LOOP INST3 ; RS232 BASE LOOP
; RESET VECTOR TO POINT TO OUR HANDLER
MOV AREA1.INT_HNDLR,OFFSET INT_HNDLR1
MOV AREA2.INT_HNDLR,OFFSET INT_HNDLR2
MOV AH,25H ; SET INTERRUPT VECTOR CONTENTS
MOV AL,INT_COM[SI] ; INTERRUPT NUMBER
MOV DX,OFFSET DGROUP:INT_HNDLR[SI] ; OUR INTERRUPT HANDLER
PUSH DS ; SAVE DATA SEGMENT
PUSH CS ; COPY CS
POP DS ; TO DS
INT DOS ; DOS FUNCTION
POP DS ; RECOVER DATA SEGMENT
; PORT INSTALLED
INSTX: MOV INSTALLED[SI],1 ; PORT INSTALLED
POP ES ; RESTORE ES
mov ax,1
pop si
mov sp,bp
pop bp
RET ; DONE
; PORT NOT INSTALLED
INST666:MOV INSTALLED[SI],0 ; PORT NOT INSTALLED ON THIS PC
POP ES ; RESTORE ES
mov ax,0
pop si
mov sp,bp
pop bp
RET ; DONE
_install_com ENDP
PAGE
;
; RESTORE ORIGINAL INTERRUPT VECTOR
;
_restore_com PROC FAR
push bp
mov bp,sp
push si
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
MOV INSTALLED[SI],0 ; PORT IS NO LONGER INSTALLED
MOV AH,25H ; SET INTERRUPT VECTOR FUNCTION
MOV AL,INT_COM[SI] ; INTERRUPT NUMBER
MOV DX,OLD_COM_OFF[SI] ; OLD OFFSET TO DX
MOV BX,OLD_COM_SEG[SI] ; OLD SEG
PUSH DS ; SAVE DS
MOV DS,BX ; TO DS
INT DOS ; DOS FUNCTION
POP DS ; RECOVER DS
pop si
mov sp,bp
pop bp
RET ; DONE
_restore_com ENDP
PAGE
;
; OPEN_COM ON CURRENT PORT
;
; CLEAR BUFFERS
; RE-INITIALIZE THE INTEL 8250 UART
; ENABLE INTERRUPTS ON THE INTEL 8259 INTERRUPT CONTROL CHIP
;
; [bp+6] = BAUD RATE
; [bp+8] = CONNECTION: M(ODEM), D(IRECT)
; [bp+10] = PARITY: N(ONE), O(DD), E(VEN), S(PACE), M(ARK)
; [bp+12] = STOP BITS: 1, 2
; [bp+14] = XON/XOFF: E(NABLED), D(ISABLED)
;
_open_com PROC FAR
push bp
mov bp,sp
push si
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
CLI ; INTERRUPTS OFF
mov ax,[bp+6]
MOV BAUD_RATE[SI],AX ; SET
mov bh,[bp+8]
MOV CONNECTION[SI],BH ; ARGS
mov bl,[bp+10]
MOV PARITY[SI],BL ; IN
mov ch,[bp+12]
MOV STOP_BITS[SI],CH ; MEMORY
mov cl,[bp+14]
MOV XON_XOFF[SI],CL
; RESET FLOW CONTROL
MOV HOST_OFF[SI],0 ; HOST FLOWING
MOV PC_OFF[SI],0 ; PC FLOWING
; RESET BUFFER COUNTS AND POINTERS
MOV START_TDATA[SI],0
MOV END_TDATA[SI],0
MOV START_RDATA[SI],0
MOV END_RDATA[SI],0
MOV SIZE_TDATA[SI],0
MOV SIZE_RDATA[SI],0
TEST INSTALLED[SI],1 ; PORT INSTALLED?
JNZ OC1 ; SKIP IF SO
JMP OCX ; ELSE ABORT
OC1:
; RESET THE 8250
MOV AL,0
MOV DX,MCR[SI]
OUT DX,AL
JMP $+2 ; I/O DELAY FOR JR
MOV DX,LSR[SI] ; RESET LINE STATUS CONDITION
IN AL,DX
JMP $+2 ; I/O DELAY FOR JR
MOV DX,DATREG[SI] ; RESET RECSIVE DATA CONDITION
IN AL,DX
JMP $+2 ; I/O DELAY FOR JR
MOV DX,MSR[SI] ; RESET MODEM DELTAS AND CONDITIONS
IN AL,DX
; CONVERT PASSED BAUD RATE TO 8250 DIVISOR
MOV AX,50 ; 50 BAUD
MUL DIV50 ; TIMES ITS DIVISOR
DIV BAUD_RATE[SI] ; OTHER SPEEDS ARE PROPORTIONAL
MOV BX,AX ; RESULT TO BX
; SET 8250 DIVISOR
MOV DX,LCR[SI] ; LINE CONTROL REGISTER
MOV AL,80H ; HI BIT ON
OUT DX,AL ; SET DLAB = 1
JMP $+2 ; I/O DELAY FOR JR
MOV DX,WORD PTR DLL[SI] ; LEAST SIGNIFICANT BYTE
MOV AL,BL ; LSB FROM TABLE
OUT DX,AL ; SET LSB ON 8250
JMP $+2 ; I/O DELAY FOR JR
MOV DX,WORD PTR DLH[SI] ; MOST SIGNIFICANT BYTE
MOV AL,BH ; MSB FROM TABLE
OUT DX,AL ; SET MSB ON 8250
JMP $+2 ; I/O DELAY FOR JR
; SET PARITY AND NUMBER OF STOP BITS
MOV AL,03H ; NONE OR SPACE PARITY IS THE DEFAULT
CMP PARITY[SI],'O' ; ODD PARITY REQUESTED?
JNE P1 ; JUMP IF NOT
MOV AL,0AH ; SELECT ODD PARITY
JMP SHORT P3 ; CONTINUE
P1: CMP PARITY[SI],'E' ; EVEN PARITY REQUESTED?
JNE P2 ; JUMP IF NOT
MOV AL,1AH ; SELECT EVEN PARITY
JMP SHORT P3 ; CONTINUE
P2: CMP PARITY[SI],'M' ; MARK PARITY REQUESTED?
JNE P3 ; JUMP IF NOT
MOV AL,2AH ; SELECT MARK PARITY
P3: TEST STOP_BITS[SI],2 ; 2 STOP BITS REQUESTED?
JZ STOP1 ; NO
OR AL,4 ; YES
STOP1: MOV DX,LCR[SI] ; LINE CONTROL REGISTER
OUT DX,AL ; SET 8250 PARITY MODE AND DLAB=0
; ENABLE INTERRUPTS ON 8259 AND 8250
IN AL,INTA01 ; SET ENABLE BIT ON 8259
AND AL,NIRQ[SI]
OUT INTA01,AL
MOV DX,IER[SI] ; ENABLE INTERRUPTS ON 8250
MOV AL,5 ; RECEIVE & LINE ERROR
OUT DX,AL
JMP $+2 ; I/O DELAY FOR JR
MOV DX,MCR[SI] ; SET DTR AND ENABLE INT DRIVER
MOV AL,0BH
OUT DX,AL
OCX: STI ; INTERRUPTS ON
pop si
mov sp,bp
pop bp
RET ; DONE
_open_com ENDP
PAGE
;
; CLOSE_COM - TURNS OFF INTERRUPTS FROM THE COMMUNICATIONS PORT
;
_close_com PROC FAR
push bp
mov bp,sp
push si
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
TEST INSTALLED[SI],1 ; PORT INSTALLED?
JZ CCX ; ABORT IF NOT
; TURN OFF 8250
MOV DX,IER[SI]
MOV AL,0
OUT DX,AL
; TURN OFF 8259
MOV DX,INTA01
IN AL,DX
OR AL,IRQ[SI]
JMP $+2 ; DELAY FOR AT
OUT DX,AL
CCX: pop si
mov sp,bp
pop bp
RET
_close_com ENDP
PAGE
;
; DTR_OFF - TURNS OFF DTR TO TELL MODEMS THAT THE TERMINAL HAS GONE AWAY
; AND TO HANG UP THE PHONE
;
_dtr_off PROC FAR
push bp
mov bp,sp
push si
PUSHF ; SAVE FLAGS
PUSH AX ; SAVE REGS
PUSH DX
PUSH SI
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
TEST INSTALLED[SI],1 ; PORT INSTALLED?
JZ DFX ; ABORT IF NOT
MOV DX,MCR[SI]
MOV AL,08H ; DTR OFF, RTS OFF, OUT2 ON
OUT DX,AL
DFX: POP SI ; RECOVER REGS
POP DX
POP AX
POPF ; RECOVER FLAGS
pop si
mov sp,bp
pop bp
RET
_dtr_off ENDP
;
; DTR_ON - TURNS DTR ON
;
_dtr_on PROC FAR
push bp
mov bp,sp
push si
PUSHF ; SAVE FLAGS
PUSH AX ; SAVE REGS
PUSH DX
PUSH SI
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
TEST INSTALLED[SI],1 ; PORT INSTALLED?
JZ DNX ; ABORT IF NOT
MOV DX,MCR[SI]
MOV AL,0BH
OUT DX,AL
DNX: POP SI ; RECOVER REGS
POP DX
POP AX
POPF ; RECOVER FLAGS
pop si
mov sp,bp
pop bp
RET ; DONE
_dtr_on ENDP
PAGE
;
; R_COUNT - RETURNS NUMBER OF BYTES IN THE RECEIVE BUFFER IN AX
; total in DX
;
_r_count PROC FAR
push bp
mov bp,sp
push si
PUSHF ; SAVE FLAGS
PUSH SI ; SAVE SI
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
MOV AX,0 ; NOTHING RECEIVED IF NOT INSTALLED
mov dx,R_SIZE
TEST INSTALLED[SI],1 ; PORT INSTALLED?
JZ RCX ; ABORT IF NOT
MOV AX,SIZE_RDATA[SI] ; GET NUMBER OF BYTES USED
RCX: POP SI ; RESTORE SI
POPF ; RESTORE FLAGS
pop si
mov sp,bp
pop bp
RET
_r_count ENDP
PAGE
;
; RECEIVE - RETURNS THE NEXT CHARACTER FROM THE RECEIVE BUFFER IN AL
; AND REMOVES IT FROM THE BUFFER
; THE PARITY BIT IS STRIPPED OFF
;
_receive_com PROC FAR
push bp
mov bp,sp
push si
PUSHF ; SAVE FLAGS
PUSH BX ; SAVE REGS
PUSH SI
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
mov ax,-1 ; -1 if bad call
TEST INSTALLED[SI],1 ; PORT INSTALLED?
JZ RCVX ; ABORT IF NOT
CMP SIZE_RDATA[SI],0 ; ANY CHARACTERS?
JE RCVX ; ABORT IF NOT
; GOOD CALL
mov ah,0 ; good call
MOV BX,START_RDATA[SI] ; GET POINTER TO OLDEST CHAR
MOV AL,RDATA[SI][BX] ; GET CHAR FROM BUFFER
; MOD BY LBA, 10/6/85 FOR PROPER SUPPORT OF NO PARITY COMMUNICATIONS
CMP PARITY[SI],'N' ; ARE WE RUNNING WITH NO PARITY?
JE L11 ; IF SO, DON'T STRIP HIGH BIT
; END OF MOD
AND AL,7FH ; STRIP PARITY BIT
L11: INC BX ; BUMP START_RDATA
CMP BX,R_SIZE ; SEE IF PAST END
JB L12 ; IF NOT THEN SKIP
MOV BX,0 ; ADJUST TO BEGINNING
L12: MOV START_RDATA[SI],BX ; SAVE THE NEW START_RDATA VALUE
DEC SIZE_RDATA[SI] ; ONE LESS CHARACTER
CMP XON_XOFF[SI],'E' ; FLOW CONTROL ENABLED?
JNE RCVX ; DO NOTHING IF DISABLED
CMP HOST_OFF[SI],1 ; HOST TURNED OFF?
JNE RCVX ; JUMP IF NOT
CMP SIZE_RDATA[SI],R_SIZE/20 ; RECEIVE BUFFER NEARLY EMPTY?
JGE RCVX ; DONE IF NOT
MOV HOST_OFF[SI],0 ; TURN ON HOST IF SO
PUSH AX ; SAVE RECEIVED CHAR
MOV AL,CONTROL_Q ; TELL HIM TO TALK
CLI ; TURN OFF INTERRUPTS
CALL SENDII ; SEND IMMEDIATELY INTERNAL
STI ; INTERRUPTS BACK ON
POP AX ; RESTORE RECEIVED CHAR
RCVX: POP SI ; RECOVER REGS
POP BX
POPF ; RECOVER FLAGS
pop si
mov sp,bp
pop bp
RET ; DONE
_receive_com ENDP
PAGE
;
; S_COUNT - RETURNS IN AX THE AMOUNT OF FREE SPACE
; REMAINING IN THE TRANSMIT BUFFER
; DX total size
;
_s_count PROC FAR
push bp
mov bp,sp
push si
PUSHF ; SAVE FLAGS
PUSH SI ; SAVE SI
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
MOV AX,0 ; NO SPACE LEFT IF NOT INSTALLED
mov dx,S_SIZE
TEST INSTALLED[SI],1 ; PORT INSTALLED?
JZ SCX ; ABORT IF NOT
MOV AX,S_SIZE ; GET THE SIZE OF THE X-MIT BUFFER
SUB AX,SIZE_TDATA[SI] ; SUBTRACT THE NUMBER OF BYTES USED
SCX: POP SI ; RECOVER SI
POPF ; RESTORE FLAGS
pop si
mov sp,bp
pop bp
RET
_s_count ENDP
PAGE
;
; SEND - SEND A CHARACTER
; [bp+6] = char
;
_send_com PROC FAR
push bp
mov bp,sp
push si
mov al,[bp+6]
PUSHF ; SAVE FLAGS
PUSH AX ; SAVE REGS
PUSH BX
PUSH DX
PUSH SI
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
TEST INSTALLED[SI],1 ; PORT INSTALLED?
JZ L44 ; ABORT IF NOT
CMP SIZE_TDATA[SI],S_SIZE ; BUFFER FULL?
JL L4A ; JUMP IF NOT
INC WORD PTR EOVFLOW[SI] ; BUMP ERROR COUNT
JMP SHORT L44 ; PUNT
L4A: MOV BX,END_TDATA[SI] ; BX POINTS TO FREE SPACE
MOV TDATA[SI][BX],AL ; MOVE CHAR TO BUFFER
INC BX ; INCREMENT END_TDATA
CMP BX,S_SIZE ; SEE IF PAST END
JL L4 ; IF NOT THEN SKIP
MOV BX,0 ; ADJUST TO BEGINNING
L4: MOV END_TDATA[SI],BX ; SAVE NEW END_TDATA
INC SIZE_TDATA[SI] ; ONE MORE CHARACTER IN X-MIT BUFFER
MOV DX,IER[SI] ; INTERRUPT ENABLE REGISTER
IN AL,DX ; GET IT
TEST AL,2 ; SEE IF TX INTERRUPTS ARE ENABLED
JNZ L44 ; JUMP IF SO
MOV AL,7 ; IF NOT THEN RCV, TX, LINE ERROR
OUT DX,AL ; ARE ENABLED
L44: POP SI ; RESTORE REGS
POP DX
POP BX
POP AX
POPF ; RESTORE FLAGS
pop si
mov sp,bp
pop bp
RET ; DONE
_send_com ENDP
PAGE
;
; SENDI - SEND A CHARACTER IMMEDIATELY
; [bp+6] = char to send
;
_sendi_com PROC FAR
push bp
mov bp,sp
push si
mov al,[bp+6]
PUSHF ; SAVE FLAGS
PUSH AX ; SAVE REGS
PUSH BX
PUSH DX
PUSH SI
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
TEST INSTALLED[SI],1 ; PORT INSTALLED?
JZ LQ44 ; ABORT IF NOT
CLI ; MASK INTERRUPTS
CALL SENDII ; CALL INTERNAL SEND IMMEDIATE
STI ; INTERRRUPTS BACK ON
LQ44: POP SI ; RESTORE REGS
POP DX
POP BX
POP AX
POPF ; RESTORE FLAGS
pop si
mov sp,bp
pop bp
RET ; DONE
_sendi_com ENDP
PAGE
;
; INTERNAL ROUTINE
; DEPENDS ON CALLER TO KEEP INTERRUPTS CLEARED AND SET SI
; SENDI - SEND A CHARACTER IMMEDIATELY (PUT AT BEGINNING OF QUEUE)
; AL = CHAR TO WRITE
;
SENDII PROC NEAR
PUSH DX ; SAVE DX
CMP SIZE_TDATA[SI],S_SIZE ; BUFFER FULL?
JB LI4A ; JUMP IF NOT
INC WORD PTR EOVFLOW[SI] ; BUMP ERROR COUNT
MOV BX,START_TDATA[SI] ; BX POINTS TO FIRST CHAR IN BUFFER
MOV TDATA[SI][BX],AL ; CLOBBER FIRST CHAR IN BUFFER
JMP SHORT LI4B ; CONTINUE
LI4A: MOV BX,START_TDATA[SI] ; BX POINTS TO FIRST CHAR IN BUFFER
DEC BX ; BACKUP THE PTR
CMP BX,-1 ; BEFORE BEGINNING?
JNE LI4 ; JUMP IF NOT
MOV BX,S_SIZE-1 ; POINT TO END IF SO
LI4: MOV TDATA[SI][BX],AL ; MOVE CHAR TO BUFFER
MOV START_TDATA[SI],BX ; SAVE NEW START_TDATA
INC SIZE_TDATA[SI] ; ONE MORE CHARACTER IN X-MIT BUFFER
LI4B: MOV DX,IER[SI] ; INTERRUPT ENABLE REGISTER
IN AL,DX ; GET IT
TEST AL,2 ; SEE IF TX INTERRUPTS ARE ENABLED
JNZ LI44 ; JUMP IF SO
MOV AL,7 ; IF NOT THEN RCV, TX, LINE ERROR
OUT DX,AL ; ARE ENABLED
LI44: POP DX ; RECOVER DX
RET ; DONE
SENDII ENDP
PAGE
;
; S_LOCAL
;
_send_local PROC FAR
push bp
mov bp,sp
push si
mov al,[bp+6]
PUSHF ; SAVE FLAGS
PUSH AX ; SAVE REGS
PUSH BX
PUSH SI
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
TEST INSTALLED[SI],1 ; PORT INSTALLED?
JZ SLX ; ABORT IF NOT
CLI ; INTERRUPTS OFF
CMP SIZE_RDATA[SI],R_SIZE ; SEE IF ANY ROOM
JB L13A ; SKIP IF ROOM
INC WORD PTR EOVFLOW[SI] ; BUMP OVERFLOW COUNT
JMP SHORT L14 ; PUNT
L13A: MOV BX,END_RDATA[SI] ; BX POINTS TO FREE SPACE
MOV RDATA[SI][BX],AL ; SEND DATA TO BUFFER
INC BX ; INCREMENT END_RDATA POINTER
CMP BX,R_SIZE ; SEE IF GONE PAST END
JL L13 ; IF NOT THEN SKIP
MOV BX,0 ; ELSE ADJUST TO BEGINNING
L13: MOV END_RDATA[SI],BX ; SAVE VALUE
INC SIZE_RDATA[SI] ; GOT ONE MORE CHARACTER
L14: STI ; INTERRUPTS BACK ON
SLX: POP SI ; RECOVER REGS
POP BX
POP AX
POPF ; RECOVER FLAGS
pop si
mov sp,bp
pop bp
RET ; DONE
_send_local ENDP
PAGE
;
; BREAK - CAUSES A BREAK TO BE SENT OUT ON THE LINE
;
_break_com PROC FAR
push bp
mov bp,sp
push si
PUSHF ; SAVE FLAGS
PUSH AX ; SAVE REGS
PUSH CX
PUSH DX
MOV SI,CURRENT_AREA ; SI POINTS TO DATA AREA
TEST INSTALLED[SI],1 ; PORT INSTALLED?
JZ BRX ; ABORT IF NOT
MOV DX,LCR[SI] ; LINE CONTROL REGISTER
IN AL,DX ; GET CURRENT SETTING
JMP $+2 ; I/O DELAY FOR JR
OR AL,40H ; TURN ON BREAK BIT
OUT DX,AL ; SET IT ON THE 8250
MOV CX,0C000H ; WAIT APPROX. 1/4 SEC.
BREAK1: LOOP BREAK1 ; BUSY WAIT
AND AL,0BFH ; TURN OFF BREAK BIT
OUT DX,AL ; RESTORE LINE CONTROL REGISTER
BRX: POP DX ; RECOVER REGS
POP CX
POP AX
POPF ; RECOVER FLAGS
pop si
mov sp,bp
pop bp
RET ; DONE
_break_com ENDP
PAGE
;
; COM_ERRORS - RETURN POINTER IN dx:ax TO ERROR COUNTS
;
_com_errors PROC FAR
push bp
mov bp,sp
mov ax,OFFSET DGROUP:CURRENT_AREA
add ax,ERROR_BLOCK
mov dx,ds
mov sp,bp
pop bp
RET ; DONE
_com_errors ENDP
PAGE
;
; INTERNAL ROUTINE
; BUMP ERROR COUNTS FROM LINE STATUS IN AL
;
E_BUMP PROC NEAR
TEST AL,2 ; OVERRUN ERROR?
JZ LSI1 ; JUMP IF NOT
INC WORD PTR EOVRUN[SI] ; ELSE BUMP ERROR COUNT
LSI1: TEST AL,4 ; PARITY ERROR?
JZ LSI2 ; JUMP IF NOT
INC WORD PTR EPARITY[SI] ; ELSE BUMP ERROR COUNT
LSI2: TEST AL,8 ; FRAMING ERROR?
JZ LSI3 ; JUMP IF NOT
INC WORD PTR EFRAME[SI] ; ELSE BUMP ERROR COUNT
LSI3: TEST AL,16 ; BREAK RECEIVED?
JZ LSI4 ; JUMP IF NOT
INC WORD PTR EBREAK[SI] ; ELSE BUMP ERROR COUNT
LSI4: RET ; DONE
E_BUMP ENDP
PAGE
;
; INTERNAL ROUTINE
; MODEM SEND PROTOCOL
;
M_PROTOCOL PROC NEAR
CMP CONNECTION[SI],'M' ; MODEM CONNECTION?
JNE S3 ; IF NOT, SKIP DSR & CTS PROTOCOL
; TELL MODEM WE'RE READY TO SEND
MOV DX,MCR[SI] ; MODEM CONTROL REGISTER
MOV AL,00001011B ; OUT 2, RTS, DTR
OUT DX,AL ; TERMINAL READY, REQUEST TO SEND
JMP $+2 ; I/O DELAY FOR JR
; WAIT UNTIL MODEM SAYS DATA SET READY
MOV CX,1000 ; TIMEOUT COUNT
MOV DX,MSR[SI] ; MODEM STATUS REGISTER
S1: IN AL,DX ; GET MODEM STATUS
TEST AL,20H ; DATA SET READY?
JNZ S1X ; YES, TEST CLEAR TO SEND
LOOP S1 ; NO, BUSY WAIT
INC WORD PTR EDSR[SI] ; BUMP ERROR COUNT
JMP SHORT S3 ; WE TIMED OUT
S1X:
; WAIT UNTIL MODEM SAYS IT'S CLEAR TO SEND
MOV CX,1000 ; TIMEOUT COUNT
S2: IN AL,DX ; GET MODEM STATUS
TEST AL,10H ; CLEAR TO SEND?
JNZ S2X ; YES
LOOP S2 ; NO, KEEP TRYING
INC WORD PTR ECTS[SI] ; BUMP ERROR COUNT - WE TIMED OUT
S2X:
; TEST FOR TRANSMITTER READY
S3: MOV DX,LSR[SI] ; LINE STATUS REGISTER
IN AL,DX ; GET LINE STATUS
TEST AL,20H ; TRANSMITTER READY?
JNZ S4 ; SKIP IF SO
INC WORD PTR EXMIT[SI] ; ELSE BUMP ERROR COUNT
S4: RET ; DONE
M_PROTOCOL ENDP
PAGE
;
; INTERNAL ROUTINES FOR FLOW CONTROL
;
; FLOW_IN - RESPOND TO FLOW CONTROL COMMANDS FROM HOST
; FLOW_OUT - ISSUE FLOW CONTROL COMMANDS TO HOST
;
FLOW_IN PROC NEAR
PUSH AX ; SAVE CHAR
CMP XON_XOFF[SI],'E'; FLOW CONTROL ENABLED?
JNE FI_2 ; DO NOTHING IF DISABLED
AND AL,7FH ; STRIP PARITY
CMP AL,CONTROL_S ; STOP COMMAND RECEIVED?
JNE FI_1 ; JUMP IF NOT
MOV PC_OFF[SI],1 ; WE MUST SHUT UP
JMP SHORT FI_2 ; CONTINUE
FI_1: CMP AL,CONTROL_Q ; GO COMMAND RECEIVED?
JNE FI_2 ; NO, MUST BE NORMAL CHAR
MOV PC_OFF[SI],0 ; WE START TALKING AGAIN
FI_2: POP AX ; RESTORE CHAR
RET ; DONE
FLOW_IN ENDP
;
FLOW_OUT PROC NEAR
CMP XON_XOFF[SI],'E'; FLOW CONTROL ENABLED?
JNE FO_X ; DO NOTHING IF DISABLED
CMP HOST_OFF[SI],1 ; HOST TURNED OFF?
JE FO_X ; JUMP IF SO
CMP SIZE_RDATA[SI],R_SIZE/2 ; RECEIVE BUFFER NEARLY FULL?
JLE FO_X ; DONE IF NOT
MOV AL,CONTROL_S ; TURN OFF HOST IF SO
CALL SENDII ; SEND IMMEDIATELY INTERNAL
MOV HOST_OFF[SI],1 ; HOST IS NOW OFF
FO_X: RET ; DONE
FLOW_OUT ENDP
PAGE
;
; INT_HNDLR1 - HANDLES INTERRUPTS GENERATED BY COM1:
;
INT_HNDLR1 PROC FAR
PUSH SI ; SAVE SI
MOV SI,OFFSET AREA1 ; DATA AREA FOR COM1:
JMP SHORT INT_COMMON ; CONTINUE
;
; INT_HNDLR2 - HANDLES INTERRUPTS GENERATED BY COM2:
;
INT_HNDLR2 PROC FAR
PUSH SI ; SAVE SI
MOV SI,OFFSET AREA2 ; DATA AREA FOR COM2:
;
; BODY OF INTERRUPT HANDLER
;
INT_COMMON:
PUSH AX ; SAVE REGS
PUSH BX
PUSH CX
PUSH DX
PUSH BP
PUSH DI
PUSH DS
PUSH ES
MOV AX,SEG _DATA ; OUR DATA SEG
MOV DS,AX ; TO DS
; CLEAR THE INTERRUPT CONTROLLER FLAG
MOV DX,INTA00 ; 8259 CONTROL PORT
MOV AL,EOI[SI] ; SPECIFIC END OF INTERRUPT
OUT DX,AL ; CLEAR FLAG
; FIND OUT WHERE INTERRUPT CAME FROM AND JUMP TO ROUTINE TO HANDLE IT
REPOLL:
MOV DX,IIR[SI] ; READ INTERRUPT STATUS REGISTER
IN AL,DX
CMP AL,4
JE RX_INT ; IF FROM THE RECEIVER
CMP AL,2
JE TX_INT ; IF FROM THE TRANSMITTER
CMP AL,6
JE LSTAT_INT ; INTERRUPT BECAUSE OF LINE STATUS
CMP AL,0
JE MSTAT_INT ; INTERRUPT BECAUSE OF MODEM STATUS
JMP FAR PTR INT_END ; DONE, EXIT (DON'T FIX FAR PTR STUFF)
LSTAT_INT:
MOV DX,LSR[SI] ; READ AND IGNORE LINE STATUS
IN AL,DX ;
CALL E_BUMP ; JUST BUMP ERROR COUNTS
JMP REPOLL ; SEE IF ANY MORE INTERRUPTS
MSTAT_INT:
MOV DX,MSR[SI] ; READ AND IGNORE MODEM STATUS
IN AL,DX ;
JMP REPOLL ; SEE IF ANY MORE INTERRUPTS
TX_INT:
CMP PC_OFF[SI],1 ; HAVE WE BEEN TOLD TO SHUT UP?
JNE GOODTX1 ; JUMP IF NOT
CMP HOST_OFF[SI],1 ; HAS HOST ALSO SHUT UP?
JNE SEND_NO_MORE ; JUMP IF NOT
; CLEAR XON/XOFF DEADLOCK
MOV PC_OFF[SI],0 ; WE SPEAK
MOV HOST_OFF[SI],0 ; THEY REPLY
MOV AL,CONTROL_Q ; BUT ONLY WHEN
CALL SENDII ; WE LET THEM
GOODTX1:
CMP SIZE_TDATA[SI],0 ; SEE IF ANY MORE DATA TO SEND
JG HAVE_DATA ; IF POSITIVE THEN THERE IS DATA TO SEND
; IF NO DATA TO SEND THEN RESET TX INTERRUPT AND RETURN
SEND_NO_MORE:
MOV DX,IER[SI] ;
MOV AL,5 ; JUST RCV AND LINE ERROR
OUT DX,AL ; ARE SET
JMP REPOLL ;
HAVE_DATA:
CALL M_PROTOCOL ; DO MODEM PROTOCOL IF NECESSARY
MOV BX,START_TDATA[SI] ; BX POINTS TO NEXT CHAR. TO BE SENT
MOV AL,TDATA[SI][BX] ; GET DATA FROM BUFFER
MOV DX,DATREG[SI] ; DX EQUALS PORT TO SEND DATA TO
OUT DX,AL ; SEND DATA
INC BX ; INCREMENT START_TDATA
CMP BX,S_SIZE ; SEE IF GONE PAST END
JB NTADJ ; IF NOT THEN SKIP
MOV BX,0 ; RESET TO BEGINNING
NTADJ: MOV START_TDATA[SI],BX ; SAVE START_TDATA
DEC SIZE_TDATA[SI] ; ONE LESS CHARACTER IN X-MIT BUFFER
JMP REPOLL
RX_INT:
MOV DX,DATREG[SI] ; 8250 DATA REGISTER
IN AL,DX ; GET DATA
CALL FLOW_IN ; RESPOND TO F.C. COMMANDS FROM HOST
CMP SIZE_RDATA[SI],R_SIZE ; SEE IF ANY ROOM
JL GOOD_RX1 ; CONTINUE IF SO
INC WORD PTR EOVFLOW[SI] ; BUMP OVERFLOW ERROR COUNT
JMP REPOLL ; PUNT
GOOD_RX1:
MOV BX,END_RDATA[SI] ; BX POINTS TO FREE SPACE
MOV RDATA[SI][BX],AL ; MOVE DATA TO BUFFER
INC SIZE_RDATA[SI] ; GOT ONE MORE CHARACTER
INC BX ; INCREMENT END_RDATA POINTER
CMP BX,R_SIZE ; SEE IF GONE PAST END
JB NRADJ ; IF NOT THEN SKIP
MOV BX,0 ; ELSE ADJUST TO BEGINNING
NRADJ: MOV END_RDATA[SI],BX ; SAVE VALUE
CALL FLOW_OUT ; ISSUE FLOW CONTROL COMMANDS TO HOST
JMP REPOLL ;
INT_END:
POP ES ; RESTORE REGS
POP DS
POP DI
POP BP
POP DX
POP CX
POP BX
POP AX
POP SI ; RESTORE SI, TOO
IRET
INT_HNDLR2 ENDP
INT_HNDLR1 ENDP
COM_TEXT ENDS
END
SHAR_EOF
fi # end of overwriting check
if test -f 'dos/comm.h'
then
echo shar: will not over-write existing file "'dos/comm.h'"
else
cat << \SHAR_EOF > 'dos/comm.h'
/* declarations for comm.asm
**
** compilation must use the Ze switch to enable the
** "far" keyword for the small memory model
**
** Robin Rohlicek 3/86
*/
void far select_port( int ); /* select active port (1 or 2) */
void far save_com(); /* save the interupt vectors */
void far restore_com(); /* restore those vectors */
int far install_com(); /* install our vectors */
void far open_com( /* open com port */
int, /* baud */
int, /* 'M'odem or 'D'irect */
int, /* Parity 'N'one, 'O'dd, 'E'ven, 'S'pace, 'M'ark */
int, /* stop bits (1 or 2) */
int); /* Xon/Xoff 'E'nable, 'D'isable */
void far close_com(); /* close com port */
void far dtr_off(); /* clear DTR */
void far dtr_on(); /* set DTR */
long far r_count(); /* receive counts */
/* high word = total size of receive buffer */
/* low word = number of pending chars */
#define r_count_size() ( (int) (r_count()>>16) )
#define r_count_pending() ( (int) r_count() )
int far receive_com(); /* get one character */
/* return -1 if none available */
long far s_count(); /* send counts */
/* high word = total size of transmit buffer */
/* low word = number of bytes free in transmit buffer */
#define s_count_size() ( (int) (s_count()>>16) )
#define s_count_free() ( (int) s_count() )
void far send_com(int); /* send a character */
void far send_local(int); /* simulate receive of char */
void far sendi_com(int); /* send immediately */
void far break_com(); /* send a BREAK */
int * far com_errors(); /* pointer to error counts
(in static area) */
#define COM_EOVFLOW 0 /* buffer overflows */
#define COM_EOVRUN 1 /* receive overruns */
#define COM_EBREAK 2 /* break chars */
#define COM_EFRAME 3 /* framing errors */
#define COM_EPARITY 4 /* parity errors */
#define COM_EXMIT 5 /* transmit erros */
#define COM_EDSR 6 /* data set ready errors */
#define COM_ECTS 7 /* clear to send errors */
#define COM_NERR 8 /* number of errors */
SHAR_EOF
fi # end of overwriting check
if test -f 'dos/host.c'
then
echo shar: will not over-write existing file "'dos/host.c'"
else
cat << \SHAR_EOF > 'dos/host.c'
/*
ibmpc/host.c
IBM-PC host program
*/
#include <stdio.h>
#include <setjmp.h>
#include <errno.h>
#include <direct.h>
#include <stdlib.h>
#include <malloc.h>
#include <assert.h>
#include <fcntl.h>
#include "host.h"
#define FILENAME "%s/%s"
char *curdir;
int debuglevel; /* debuglevelging level */
jmp_buf dcpexit;
void main(argc, argv)
int argc;
char *argv[];
{
loadenv();
curdir = getcwd(NULL, 80);
#ifdef CWDSPOOL
chdir(spooldir);
#endif
/* setup longjmp for error exit's */
if (setjmp(dcpexit) == 0)
MAIN(argc, argv);
#ifdef CWDSPOOL
chdir(curdir);
#endif
} /*main*/
/*
importpath - convert a canonical name to a format the host can handle
Thise routines convert file name between canonical form, which is
defined as a 'unix' style pathname, and the MS-DOS all uppercase
"xxxxxxxx.xxx" format.
Mung the canonical file name as follows:
1 - skip any path from the canonical name
2 - copy up to 8 character from the canonical name converting . to _
and uppercase to lowercase.
3 - if the name was longer than 8 character copy a . to the host name
and then copy the up to three characters from the tail of the
canonical name to the host name.
*/
#define min(x,y) (((x) < (y)) ? (x) : (y))
void importpath(host, canon)
char *host, *canon;
{
char *s, *out, c;
int i, j, l;
out = host;
/* get a pointer to the last component of the path */
if ((s = rindex(canon, '/')) == (char *)NULL)
s = canon;
else
s++;
j = min(l = strlen(s), 8);
for (i = 0; i < j; i++) {
c = *s++;
*out++ = (c == '.') ? '_' : tolower(c);
}
*out = '\0';
while (*s != '\0') s++;
if (l>8)
for (i=0; i<3; i++)
if (*--s == '.') {
s++;
break;
}
if (*s != '\0') {
(void)strcat(out, ".");
(void)strcat(out, s);
}
} /*importpath*/
/*
mkfilename - build a path name out of a directory name and a file name
*/
void mkfilename(filename, dirname, name)
char *filename;
char *dirname;
char *name;
{
sprintf(filename, FILENAME, dirname, name);
} /*mkfilename*/
/*
genv - obtain a value form an environment variable
*/
char *genv(envname, defvalue)
char *envname, *defvalue;
{
char *envvalue, *space;
if ((envvalue = getenv(envname)) != NULL) {
space = malloc((unsigned)(strlen(envvalue) + 1));
(void)strcpy(space, envvalue);
return(space);
} else
return(defvalue);
} /*genv*/
/* The following defines the environment variable names to look
for the various global parameters under. */
#define MAILBOX "MAILBOX"
#define HOME "HOME"
#define MAILDIR "MAILDIR"
#define CONFDIR "CONFDIR"
#define SPOOLDIR "SPOOLDIR"
#define PUBDIR "PUBDIR"
#define TEMPDIR "TEMPDIR"
#define DOMAIN "DOMAIN"
#define MAILSERV "MAILSERV"
#define DEVICE "DEVICE"
#define SPEED "SPEED"
/* The following are the default value for the global parameters */
#define DMAILBOX "mailbox"
#define DNAME ""
#define DHOME "/usr/guest"
#define DMAILDIR "/usr/mail"
#define DCONFDIR "/usr/lib/uucp"
#define DSPOOLDIR "/usr/spool/uucp"
#define DPUBDIR "/usr/spool/uupublic"
#define DTEMPDIR "/tmp"
#define DDOMAIN "pc.uucp"
#define DNODENAME ""
#define DMAILSERV "host"
#define DDEVICE "COM1"
#define DSPEED "1200"
/* The following variables points to the various global parameters */
char *mailbox, *name, *home;
char *maildir, *confdir, *spooldir, *pubdir, *tempdir;
char *domain, *nodename, *mailserv;
char *device, *speed;
/*
loadenv - define the global parameters
*/
void loadenv()
{
mailbox = genv(MAILBOX, DMAILBOX);
name = genv(NAME, DNAME);
home = genv(HOME, DHOME);
maildir = genv(MAILDIR, DMAILDIR);
confdir = genv(CONFDIR, DCONFDIR);
spooldir = genv(SPOOLDIR, DSPOOLDIR);
pubdir = genv(PUBDIR, DPUBDIR);
tempdir = genv(TEMPDIR, DTEMPDIR);
domain = genv(DOMAIN, DDOMAIN);
nodename = genv(NODENAME, DNODENAME);
mailserv = genv(MAILSERV, DMAILSERV);
device = genv(DEVICE, DDEVICE);
speed = genv(SPEED, DSPEED);
} /*loadenv*/
/*
filemode - default the text/binary mode for subsequently opened files
*/
void filemode(mode)
char mode;
{
assert((mode == 'b') || (mode == 't'));
_fmode = (mode == 't') ? O_TEXT : O_BINARY;
} /*filemode*/
SHAR_EOF
fi # end of overwriting check
if test -f 'dos/host.h'
then
echo shar: will not over-write existing file "'dos/host.h'"
else
cat << \SHAR_EOF > 'dos/host.h'
/* ibmpc/host.h */
#include <ctype.h>
#include <time.h>
#include <stddef.h>
#include <string.h>
#define MSDOS 1
#define TRUE 1
#define FALSE 0
#define SAME 0
#define TFILENAME "%.8d.Tmp" /* nnnnnnnn.Tmp */
#define SFILENAME "SEQF"
#define SEPCHAR '/'
#define SIGFILE "Signatur.e"
#define COPYFILE "Mail/MailSent"
#define NEWSDIR "usr/spool/rnews/%02d%02d%02d/%02d%02d%02d.%03d"
#define CALLFILE "c_%.6s"
#define XQTFILE "x_%.6s"
#define CONSOLE "con" /* "filename" of the console */
#define NAME "NAME"
#define NODENAME "NODENAME"
#define FILEMODE(type) filemode(type)
#define index strchr
#define rindex strrchr
extern char *strchr(), *strrchr;
extern char *maildir;
extern char *tempdir;
extern char *mailbox;
extern char *name;
extern char *device;
extern char *spooldir;
extern char *pubdir;
extern char *confdir;
extern char *home;
extern char *mailserv;
extern char *nodename;
extern char *domain;
extern char *speed;
extern void importpath();
extern void exportpath();
extern void mkfilename();
extern void loadenv();
extern FILE *hostfopen();
extern void filemode();
SHAR_EOF
chmod +x 'dos/host.h'
fi # end of overwriting check
if test -f 'dos/mlib.c'
then
echo shar: will not over-write existing file "'dos/mlib.c'"
else
cat << \SHAR_EOF > 'dos/mlib.c'
/* ibmpc/mlib.c
mail system-dependent library
Services to provide in mlib.c
get a single character from the console
*/
#include <conio.h>
int get_one()
{
return(getch());
} /*get_one*/
SHAR_EOF
fi # end of overwriting check
if test -f 'dos/ndir.c'
then
echo shar: will not over-write existing file "'dos/ndir.c'"
else
cat << \SHAR_EOF > 'dos/ndir.c'
/* ndir.c for MS-DOS by SKL, June/87 */
/*
Berkeley-style directory reading routine on MS-DOS
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <malloc.h>
#include <dos.h>
#include <assert.h>
#include "ndir.h"
/*
Open a directory
*/
DIR *opendir(dirname)
char *dirname;
{
union REGS inregs, outregs;
struct SREGS segregs;
char pathname[128];
DTA far *dtaptr;
char far *pathptr;
DIR *dirp;
/* build pathname to be scanned */
(void)strcpy(pathname, dirname);
(void)strcat(pathname, "/*.*");
/* allocate control block */
dirp = (DIR *)malloc(sizeof(DIR));
/* set DTA address to our buffer */
inregs.h.ah = 0x1a;
dtaptr = (DTA far *)&(dirp->dirdta);
segregs.ds = FP_SEG(dtaptr);
inregs.x.dx = FP_OFF(dtaptr);
intdosx(&inregs, &outregs, &segregs);
/* look for the first file */
inregs.h.ah = 0x4e;
pathptr = (char far *)pathname;
segregs.ds = FP_SEG(pathptr);
inregs.x.dx = FP_OFF(pathptr);
inregs.x.cx = 0; /* attribute */
intdosx(&inregs, &outregs, &segregs);
/* bad directory name? */
if (outregs.x.cflag && (outregs.x.ax == 2 || outregs.x.ax == 3)) {
free((char *)dirp);
return NULL;
}
dirp->dirfirst = outregs.x.cflag ? outregs.x.ax : 0;
(void)strcpy(dirp->dirid, "DIR");
return dirp;
} /*opendir*/
/*
Get next entry in a directory
*/
struct direct *readdir(dirp)
DIR *dirp;
{
int errcode;
assert(strcmp(dirp->dirid, "DIR") == 0);
if (dirp->dirfirst == -1) {
union REGS inregs, outregs;
struct SREGS segregs;
DTA far *dtaptr;
inregs.h.ah = 0x4f;
dtaptr = (DTA far *)&(dirp->dirdta);
segregs.ds = FP_SEG(dtaptr);
inregs.x.dx = FP_OFF(dtaptr);
intdosx(&inregs, &outregs, &segregs);
errcode = outregs.x.cflag ? outregs.x.ax : 0;
} else {
errcode = dirp->dirfirst;
dirp->dirfirst = -1;
};
/* no more files in directory? */
if (errcode == 18)
return NULL;
assert(errcode == 0);
dirp->dirent.d_ino = -1; /* no inode information */
{
char *from, *to;
for ( from = dirp->dirdta.filename, to = dirp->dirent.d_name;
;
from++, to++ ) {
*to = tolower(*from);
if (*from == '\0') break;
};
};
dirp->dirent.d_namlen = strlen(dirp->dirent.d_name);
dirp->dirent.d_reclen = sizeof(struct direct) - (MAXNAMLEN + 1) +
((((dirp->dirent.d_namlen + 1) + 3) / 4) * 4);
return &(dirp->dirent);
} /*readdir*/
/*
Close a directory
*/
void closedir(dirp)
DIR *dirp;
{
(void)strcpy(dirp->dirid, "XXX");
free((char *)dirp);
} /*closedir*/
SHAR_EOF
fi # end of overwriting check
if test -f 'dos/ndir.h'
then
echo shar: will not over-write existing file "'dos/ndir.h'"
else
cat << \SHAR_EOF > 'dos/ndir.h'
/* ndir.h for MS-DOS by SKL, June/87 */
#define MSDOS_MAXNAMLEN 12
#define MAXNAMLEN MSDOS_MAXNAMLEN
struct direct {
long d_ino;
short d_reclen;
short d_namlen;
char d_name[MAXNAMLEN + 1];
};
typedef struct {
char filereserved[21];
char fileattr;
int filetime, filedate;
long filesize;
char filename[MSDOS_MAXNAMLEN + 1];
} DTA;
typedef struct {
char dirid[4];
struct direct dirent;
DTA dirdta;
int dirfirst;
} DIR;
extern DIR *opendir();
extern struct direct *readdir();
extern void closedir();
SHAR_EOF
fi # end of overwriting check
if test -f 'dos/setup.bat'
then
echo shar: will not over-write existing file "'dos/setup.bat'"
else
cat << \SHAR_EOF > 'dos/setup.bat'
set MAILBOX=mailbox
set NAME=Full Name
set HOME=C:/home
set MAILDIR=C:/usr/spool/mail
set CONFDIR=C:/usr/lib/uucp
set SPOOLDIR=C:/usr/spool/uucp
set PUBDIR=C:/usr/spool/uupublic
set TEMPDIR=C:/tmp
set DOMAIN=ibmpc.vnet.van-bc.uucp
set NODENAME=ibmpc
set MAILSERV=van-bc
set DEVICE=COM1
set SPEED=1200
SHAR_EOF
fi # end of overwriting check
if test -f 'dos/ulib.c'
then
echo shar: will not over-write existing file "'dos/ulib.c'"
else
cat << \SHAR_EOF > 'dos/ulib.c'
/* ibmpc/ulib.c
DCP system-dependent library
Services provided by ulib.c:
serial I/O
UNIX commands simulation
login
*/
#include <string.h>
#include "dcp.h"
/*
login - login handler
*/
/* Currently a very dumb login handshake for PC in slave mode. */
login()
{
char line[132];
for ( ; ; ) {
msgtime = 9999; /* make it very long */
rmsg(line, 0); /* wait for a <CR> or <NL> */
msgtime = 2 * MSGTIME;
wmsg("Login:", 0);
rmsg(line, 0);
printmsg(0, "login: login=%s", line);
wmsg("Password:", 0);
rmsg(line, 0);
printmsg(14, "login: password=%s", line);
if (strcmp(line, "uucp") == SAME)
break;
};
return('I');
} /*login*/
/*
notimp - "perform" Unix commands which aren't implemented
*/
notimp(argc, argv)
int argc;
char *argv[];
{
fprintf(stderr, "shell: command '%s' is not implemented.\n", *argv);
} /*notimp*/
/*
shell - simulate a Unix command
Only the 'rmail' and 'rnews' command are currently supported.
*/
shell(command, inname, outname, errname)
char *command;
char *inname;
char *outname;
char *errname;
{
char *argvec[50];
int rmail();
int rnews();
char **argvp;
char argcp;
int (*proto)();
argcp = getargs(command, argvec);
argvp = argvec;
if ( debuglevel > 5 ) {
int args;
args = argcp;
while ( args )
fprintf(stderr, "shell: args: %d, %s\n", args--, *argvp++);
argvp = argvec;
}
proto = notimp;
if (strcmp(*argvp, "rmail") == SAME)
proto = rmail;
else if (strcmp(*argvp, "rnews") == SAME)
proto = rnews;
if (*inname != '\0') {
char localname[64];
importpath(localname, inname);
if (freopen(localname, "rb", stdin) == NULL) {
extern int errno;
fprintf(stderr, "shell: couldn't open %s (%s), errno=%d.\n",
inname, localname, errno);
}
}
(*proto)(argcp, argvp);
freopen("con", "r", stdin);
} /*shell*/
/* IBM-PC I/O routines */
/* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
/*************** BASIC I/O ***************************/
/* Saltzers serial pkg */
/* Some notes: When pkts are flying in both directions, there seems to */
/* be some interupt handling problems as far as recieving. checksum errs*/
/* may therfore occur often even though we recover from them. This is */
/* especially true with sliding windows. Errors are very few in the VMS */
/* version. RH Lamb*/
#include "comm.h"
#define STOPBIT 1
/*
swrite - write to the serial port
*/
swrite(data, num)
int num;
char *data;
{
int i;
for (i = 0; i < num; i++) send_com(*(data++));
return(i);
} /*swrite*/
/*
sread - read from the serial port
*/
/* Non-blocking read essential to "g" protocol.
See "dcpgpkt.c" for description.
This all changes in a multi-tasking system. Requests for
I/O should get queued and an event flag given. Then the
requesting process (e.g. gmachine()) waits for the event
flag to fire processing either a read or a write.
Could be implemented on VAX/VMS or DG but not MS-DOS. */
sread(buf, expected, timeout)
char *buf;
int expected, timeout;
{
long start;
start = time((long *)NULL);
for ( ; ; ) {
int pending;
pending = r_count_pending();
printmsg(20, "---> pending=%d expected=%d", pending, expected);
if (pending >= expected) {
int i;
for (i = 0; i < expected; i++)
*(buf++) = receive_com();
return(pending);
} else {
int elapsed;
elapsed = time((long *)NULL) - start;
if (elapsed >= timeout)
return(pending);
}
}
} /*sread*/
/*
openline - open the serial port for I/O
*/
openline(name, baud)
char *name, *baud;
{
int i;
sscanf(name, "COM%d", &i);
select_port(i);
save_com();
install_com();
sscanf(baud, "%d", &i);
open_com(i, 'D', 'N', STOPBIT, 'D');
dtr_on();
return(0);
} /*openline*/
/*
closeline - close the serial port down
*/
closeline()
{
dtr_off();
close_com();
restore_com();
} /*closeline*/
/*
sleep() - wait n seconds
Simply delay until n seconds have passed.
*/
void sleep(interval)
int interval;
{
long start;
start = time((long *)NULL);
while ((time((long *)NULL) - start) < interval);
} /*sleep*/
/*
SIOSpeed - re-specify the speed of an opened serial port
*/
void SIOSpeed(baud)
char *baud;
{
int speed;
dtr_off();
close_com();
sscanf(baud, "%d", &speed);
open_com(speed, 'D', 'N', STOPBIT, 'D');
dtr_on();
} /*SIOSpeed*/
SHAR_EOF
fi # end of overwriting check
# End of shell archive
exit 0
--
{ubc-vision,uunet}!van-bc!sl Stuart.Lynne@van-bc.uucp