|
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