home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
msr313src.zip
/
msxz10.asm
< prev
next >
Wrap
Assembly Source File
|
1993-07-12
|
65KB
|
2,157 lines
NAME msxz10
; File MSXZ10.ASM
include mssdef.h
; Copyright (C) 1982,1991, Trustees of Columbia University in the
; City of New York. Permission is granted to any individual or
; institution to use, copy, or redistribute this software as long as
; it is not sold for profit and this copyright notice is retained.
; Kermit system dependent module for Heath/Zenith Z100
; Edit history
; 2 March 1991 version 3.10
; Last change: 3 November 1990.
;
; OUTCH2 defined as far label.
; Replay code in PRTCHR modified per ibm pc version and call serrst added at
; label coms0. These two last changes are for version 3.02.
; New code for VTS and VTSTAT added and under revision but not active. These
; two routines and corresponding data really belong in msy but the routines
; and some of their data are kept here to make msy small enough to assemble
; with MASM 4. DUMPSCR moved to msyz10.asm.
; A number of calls to SPRTCH added in order to allow windowing for the non
; interupt driven S-100 modem ports COM3/COM4. Some very limited success at
; 1200 baud would indicate that it might work at 300 (untested).
; SERISR optimized and performance improved for COM1/COM2. However, there are
; still some problems from 19200 baud and up, in particular with windowing.
; OUTCHR significantly rewritten. Modified CHKXON (COM1/2) and CHKXOF (COM3/4)
; to call OUTCH5 and OUTCH2 respectively rather than OUTCHAR.
; SERISR significantly modified to improve flow control for COM1/2 and SPRTCH
; fixed to ignore flow control for COM3/4 if not called for.
; Minor correction to WAIT01. CLEARL and CTLU merged.
; PUTHLP display routine improved and replay command implemented.
; Increased size of buffilen and buffolen. Added register save to BEEP.
; Added routines ENA_WRP and DIS_WRP and several calls to these to make serial
; display behave. Help message for 'set port' improved.
; Various cosmetic changes.
;
; First version of this file for MS-Kermit 3.0: 8 May 1990.
; Bo Gedda
;
; Support for 2 US Robotics S-100 modems at ports 20H (com3) and 2EH (com4).
; com1 (1 in status list) means serial port B.
; com2 (2 in status list) means serial port A.
; com3 (3 in status list) means S-100 port 1 (20H).
; com4 (4 in status list) means S-100 port 2 (2EH).
;
public getbaud, serini, serrst, clrbuf, outchr, coms, vts, vtstat
public ctlu, cmblnk, locate, prtchr, baudst, clearl, bdtab, dodel
public beep, sprtch, klen, ktab, krpl, getivec, setivec, dupflg
public count, xofsnt, puthlp, putmod, clrmod, poscur, pcwait
public sendbr, sendbl, machnam, lclini, outch2, dis_scan
public ihosts, ihostr, dtrlow, mdmhand, shomodem, getmodem
public portval, port1, port2, port3, port4, serhng, ena_scan
public flowon, flowoff, sescur, sesdisp, setnbios, peekcom, parmsk
off equ 0
false equ 0
true equ 1
bufon equ 1 ; buffer level xon/xoff on-state control flag
usron equ 2 ; user level xon/xoff on-state control flag
mntrgh equ bufsiz*3/4 ; High point = 3/4 of buffer full
mntrgl equ bufsiz/4 ; Low point = 1/4 buffer full
xoftime equ 15 ; 15 seconds time out for xoff, see timer
; constants used by serial port handler
; Z-100 standard serial ports A (J1) and B (J2), called COM2 and COM1 here.
; Note that A=J1=COM2=2 and B=J2=COM1=1. Port B is the standard modem port
; similar to an IBM PC port. Thats why.
; serial port information
TSRE EQU 004H
THBE EQU 001H
DTR EQU 002H
DTROFF EQU 0fdH
RTS EQU 020H
RTSOFF EQU 0dfH
DCD EQU 040H
DSR EQU 080H
RDA EQU 002H
J1_ADDR EQU 0e8H
J2_ADDR EQU 0ecH
PDATA EQU 0
PSTATUS EQU 1
PMODE EQU 2
PCOMM EQU 3
TXON EQU 001H
TXOFF EQU 0feH
RXON EQU 004H
RXOFF EQU 0fbH
MODE1 EQU 04dH
MODE2 EQU 030H ; must be ORed with appropriate baud rate
Z8259 EQU 0f2H
EOI EQU 020H
J1INT EQU 68
J2INT EQU 69
BUFILEN EQU bufsiz
BUFOLEN EQU bufsiz/2
BRKBIT EQU 048H ; Send-break bit.
mdmdat1 equ J2_ADDR ; Address of serial port B (J2)
mdmcom1 equ J2_ADDR + PCOMM ; Address of serial port B command
mdmdat2 equ J1_ADDR ; Address of serial port A (J1)
mdmcom2 equ J1_ADDR + PCOMM ; Address of serial port A command
;US Robotics S-100 modem using 8251A USART data
mdmdat3 equ 020h ; Address of USR S-100 port 1
mdmcom3 equ mdmdat3 + 1 ; Address of USR S-100 command port
mdmdat4 equ 02eh ; Address of USR S-100 port 2
mdmcom4 equ mdmdat4 + 1 ; Address of USR S-100 command port
modsndb equ 1h ; Bit to test for send S-100 modem
modrcvb equ 2h ; Bit to test for receive S-100 modem
modperb equ 8h ; Parity error detect bit S-100 modem
modorub equ 10h ; Overrun error detect bit
moddcdb equ 80h ; Carrier detect bit S-100 modem
COLUMNS EQU 80 ; Characters per screen line.
ROWS EQU 24 ; Text lines per screen
VID_CMD EQU 0d8h ; Video-memory control port.
PAR_GRN EQU 0e000h ; Green video plane segment address.
; external variables used:
; flags - global flags as per flginfo structure defined in pcdefs
; trans - global transmission parameters, trinfo struct defined in pcdefs
; portval - pointer to current portinfo structure (currently either port1,
; port2, port3 or port4 )
; port1, port2, port3, port4 - portinfo structures for the corresponding ports
; monmode - color/monochrome mode of monitor
; dmpname - file name for screen dump file
; global variables defined in this module:
; xofsnt, xofrcv - tell whether we saw or sent an xoff.
BIOS_SEG SEGMENT AT 40H ; Define segment where BIOS really is
ORG 1*3
BIOS_STATUS LABEL FAR ; Console input status
ORG 2*3
BIOS_CONIN LABEL FAR ; Console input
ORG 3*3
BIOS_CONOUT LABEL FAR ; Console output
ORG 4*3
BIOS_PRINT LABEL FAR ; Printer output
ORG 6*3
BIOS_AUXOUT LABEL FAR ; AUX output routine
ORG 25*3
BIOS_PRNFUNC LABEL FAR ; PRN: FUNCTION
ORG 26*3
BIOS_AUXFUNC LABEL FAR ; AUX: function
ORG 27*3
BIOS_CONFUNC LABEL FAR ; CON: function
BIOS_SEG ENDS
; Define functions of BIOS_CONFUNC, BIOS_PRNFUNC, and BIOS_AUXFUNC
CHR_WRITE EQU 0 ; Write function
CHR_READ EQU CHR_WRITE+1 ; Read function
CHR_STATUS EQU CHR_READ+1 ; Status function
CHR_SFGS EQU 0 ; Get status subfunction
CHRS_WA EQU 00000001B ; <ETX> sent, waiting for <ACK>
CHRS_WD EQU 00000010B ; <DC3> seen, waiting for <DC1>
CHRS_SN EQU 00000100B ; Sending nulls
CHRS_TXR EQU 10000000B ; Transmitter ready to send data
CHRS_RXR EQU 01000000B ; Receiver has data
CHRS_RXOF EQU 00100000B ; Receiver queue overflow
CHRS_RXE EQU 00010000B ; Other type of reciver error
CHRS_TXE EQU 00001000B ; Transmitter error
CHR_SFGC EQU CHR_SFGS+1 ; Get configuration info subfunction
CHR_CONTROL EQU CHR_STATUS+1 ; Control function
CHR_CFSU EQU 0 ; Setup new configuration parms subfunction
CHR_CFCI EQU CHR_CFSU+1 ; Clear input subfunction
CHR_CFCO EQU CHR_CFCI+1 ; Clear output subfunction
CHR_LOOK EQU CHR_CONTROL+1; Nondestructive read function
CHR_FMAX EQU CHR_LOOK ; Maximum function number
; storage for port configuration
cfginfo struc
cfclass db 0
cfattr db 0
cfport dw 0
cfbaud db 0
cfhshk db 0
cfbctl db 0
cfecnt db 0
cfncnt db 0
cfnchr db 0
cfres db 6 dup(?)
cfsize db 0
cfginfo ends
; structure for status information table sttab.
stent struc
sttyp dw ? ; type (actually routine to call)
msg dw ? ; message to print
val2 dw ? ; needed value: another message, or tbl addr
tstcel dw ? ; address of cell to test, in data segment
basval dw 0 ; base value, if non-zero
stent ends
data segment
extrn flags:byte, trans:byte, taklev:byte, verident:byte
extrn comptab:byte, termtb:byte, ontab:byte, scrtab:byte
extrn cntltab:byte, beltab:byte, curtab:byte, chatab:byte
extrn kpamtab:byte, dirtab:byte, doscol:byte
extrn lclsusp:word, lclrest:word, lclexit:word, dosflg:byte
extrn dosflg1:byte, repflg:byte, diskio:byte, kstatus:byte
extrn holdscr:byte, vtemu:word, lincur:word
extrn belltype:byte, vtroll:byte
oldoff dw 0
oldseg dw 0
sescur dw 0
dupflg db 0 ; full (0) or half (1) duplex on port
brkval db 0 ; What to send for a break.
brkdur dw 0 ; Length of break in centiseconds
badbd db cr,lf,'Unimplemented baud rate$'
noimp db cr,lf,'Not implemented$'
coms0msg db cr,lf,'No US Robotics S-100 modem detected at this port!'
db cr,lf,'$'
comsmsg db ' One of the following:'
db cr,lf,' 1 2 3 4 COM1 COM2 COM3 COM4 A B J1 J2'
db cr,lf,lf,'Where'
db cr,lf,' 1 = COM1 = Serial Port B = J2'
db cr,lf,' 2 = COM2 = Serial Port A = J1'
db cr,lf,' 3 = COM3 = US Robotics S-100 modem at port 20H'
db cr,lf,' 4 = COM4 = US Robotics S-100 modem at port 2EH$'
vtsmsg db cr,lf,'The Z-100 terminal has inherent HEATH-19 support.'
db cr,lf,' Set terminal none activates native Heath-19 '
db 'properties.',cr,lf
db ' This deactivates key mapping and scan codes.$'
msmsg0 db cr,lf,' Modem may be ready: DSR is unknown$'
msmsg1 db cr,lf,' Modem is not ready: DSR is off$'
msmsg2 db cr,lf,' Modem is ready: DSR is on$'
msmsg3 db cr,lf,' no Carrier Detect: CD is off$'
msmsg4 db cr,lf,' Carrier Detect: CD is on$'
msmsg5 db cr,lf,' no Clear To Send: CTS is off$'
msmsg6 db cr,lf,' Clear To Send: CTS is on$'
msmsg7 db cr,lf,' Modem is not used by the Network$'
not_z db 'Sorry, wrong software!',cr,lf
db 'This Kermit will only run on the Z-100 -- a non '
db 'IBM PC compatible',cr,lf,lf
machnam db 'Heath-Zenith_Z-100$'
com3ms db 'Carrier detected at S-100 Port 20H, COM3',cr,lf,'$'
com4ms db 'Carrier detected at S-100 Port 2EH, COM4',cr,lf,'$'
com3ms1 db 'Modem detected at S-100 Port 20H, COM3',cr,lf,'$'
com4ms1 db 'Modem detected at S-100 Port 2EH, COM4'
crlf db cr,lf,'$'
infmsg db 'S-100 MODEM INITIALIZATION FAILURE',cr,lf,'$'
wmsg db cr,lf,' CARRIER detected -- disconnecting',cr,lf,'$'
dscmsg db cr,lf,' DISCONNECTED',cr,lf,'$'
ndscmsg db cr,lf,' !!! WARNING >>> NOT DISCONNECTED !!!',cr,lf,'$'
hngstr db '+++$'
hngmsg db cr,lf,' The phone should have hungup.',cr,lf,'$' ; [jrd]
hnghlp db cr,lf,' The modem control lines DTR and RTS for the current'
db ' port are forced low (off)'
db cr,lf,' to hangup the phone. Normally, Kermit leaves them'
db ' high (on) when it exits.'
db cr,lf,lf,' The USR S-100 modem is hung up using "+++".'
db cr,lf,'$'
rdbuf db 80 dup (?) ; temp buf [jrd]
delstr db BS,BS,' ',BS,BS,'$' ; Delete string
clrlin db BS,BS,' ',cr,'$' ; Clear line (just the cr part)
home db ESCAPE,'H$' ; Home cursor
clrstr db ESCAPE,'E$' ; Home cursor and erase entire display
eeolstr db ESCAPE,'K$' ; Erase to end of line
enamod db ESCAPE,'x1$' ; Enable 25th line
dismod db ESCAPE,'y1$' ; Disable 25th line
enascan db ESCAPE,'y?$' ; Enable scan codes, disable key expansion
disscan db ESCAPE,'x?$' ; Disable scan codes, enable key expansion
begrev db ESCAPE,'p$' ; Enter reverse video
endrev db ESCAPE,'q$' ; Exit reverse video
lin25 db ESCAPE,'Y8 $' ; Column 1 row 25
savcur db ESCAPE,'j$' ; Save current cursor position
precur db ESCAPE,'k$' ; Restore cursor to previous position
monstr db ESCAPE,'i0$' ; Return montior information
portin db -1 ; Has comm port been initialized?
; -1=has not used, 1=is used, 0=has been used
xofsnt db 0 ; Say if we sent an XOFF
xofrcv db 0 ; Say if we received an XOFF
parmsk db 0ffh ; parity mask, 0ffh for no parity, 07fh with
flowoff db 0 ; flow-off char, Xoff or null (if no flow)
flowon db 0 ; flow-on char, Xon or null
tmp db 0,'$'
temp dw 0 ; Temporary storage.
mddat0 dw 0 ; Storage for modem data port
mdstat0 dw 0 ; Storage for modem status port
savedi dw offset source ; Temporary storage for di
srcpnt dw offset source ; where to read next serial port byte
source db bufsiz dup(0) ; S-100 port input buffer
timer db 0
timer0 db 0
; begin Terminal emulator data set
portmax equ 4 ; number of predefined ports
port1 prtinfo <0FFFH,0,defpar,1,0,defhand,floxon,0>
port2 prtinfo <0FFFH,0,defpar,1,0,defhand,floxon,0>
port3 prtinfo <0FFFH,0,defpar,1,0,defhand,floxon,0>
port4 prtinfo <0FFFH,0,defpar,1,0,defhand,floxon,0>
rept portmax-4
prtinfo <0FFFH,0,defpar,1,0,defhand,floxon,0>
endm
portval dw port1 ; Default is to use port 1
bdtab db 16 ; 16 entries
mkeyw '45.5',0
mkeyw '50 ',1
mkeyw '75 ',2
mkeyw '110 ',3
mkeyw '134.5',4
mkeyw '150',5
mkeyw '300',6
mkeyw '600',7
mkeyw '1200',8
mkeyw '1800',9
mkeyw '2000',10
mkeyw '2400',11
mkeyw '4800',12
mkeyw '9600',13
mkeyw '19200',14
mkeyw '38400',15
bdtab12 db 16 ; 16 (yes 16) entries for com1 and com2
mkeyw '45.5',0
mkeyw '50 ',1
mkeyw '75 ',2
mkeyw '110 ',3
lbdtab12 equ $-bdtab12 ; length of table
bdtab34 db 4 ; 4 entries for com3 and com4, s-100 modem
mkeyw '150 ',0
mkeyw '300',1
mkeyw '600',2
mkeyw '1200',3
; this table is indexed by the baud rate definitions given in
; bdtab. Unsupported baud rates should contain 0FFH.
bddat label word
dw 0 ; 45.5 baud
dw 1 ; 50 baud
dw 2 ; 75 baud
dw 3 ; 110 baud
dw 4 ; 134.5 baud
dw 5 ; 150 baud
dw 6 ; 300 baud
dw 7 ; 600 baud
dw 8 ; 1200 baud
dw 9 ; 1800 baud
dw 10 ; 2000 baud
dw 11 ; 2400 baud
dw 12 ; 4800 baud
dw 13 ; 9600 baud
dw 14 ; 19200 baud
dw 15 ; 38400 baud
lbddat equ $-bddat ; length of table
bddat12 label word ; for com1 and com2
dw 0 ; 45.5 baud
dw 1 ; 50 baud
dw 2 ; 75 baud
dw 3 ; 110 baud
dw 4 ; 134.5 baud
dw 5 ; 150 baud
dw 6 ; 300 baud
dw 7 ; 600 baud
dw 8 ; 1200 baud
dw 9 ; 1800 baud
dw 10 ; 2000 baud
dw 11 ; 2400 baud
dw 12 ; 4800 baud
dw 13 ; 9600 baud
dw 14 ; 19200 baud
dw 15 ; 38400 baud
bddat34 label word ; for com3 and com4, s-100 modem
dw 0 ; 150 baud
dw 1 ; 300 baud
dw 2 ; 600 baud
dw 3 ; 1200 baud
dw 0ffh
dw 0ffh
dw 0ffh
dw 0ffh
dw 0ffh
dw 0ffh
dw 0ffh
dw 0ffh
dw 0ffh
dw 0ffh
dw 0ffh
dw 0ffh
; baud rate data for S-100 modem
bd150 db 4fh ; Low speed mode byte (150/300)
db 17h ; Low speed command byte (150/600)
bd300 db 4fh ; Low speed mode byte (150/300)
db 37h ; High speed command byte(300/1200)
bd600 db 4eh ; High speed mode byte (600/1200)
db 17h ; Low speed command byte (150/600)
bd1200 db 4eh ; High speed mode byte (300/1200)
db 37h ; High speed command byte(300/1200)
; S-100 COM3/COM4 default baud rate: 0=150, 1=300, 2=600, 3=1200 baud
bds100 equ 3 ; Set to 0, 1, 2, or 3
; S-100 modem set up string
; echo commands, use extended result codes, do not answer call
set_str db 'ATE1X1S0=0',cr,'$'
auxconf cfginfo <>
; variables for serial interrupt handler
count dw 0 ; Number of chars in int buffer.
buffin db BUFILEN+2 dup(?) ; input buffer
bufibeg dw 0
bufiend dw 0
buffout db BUFOLEN+2 dup(?) ; output buffer
bufobeg dw 0
bufoend dw 0
portadr dw 0
intin db 0 ; port int installed flag
mdmhand db 0 ; Modem status
ourarg termarg <>
klen dw ? ; length of key redefinition table
ktab dw ? ; address of key redefinition table
krpl dw ? ; address of key replacement table
colortb db 0,4,2,6,1,5,3,7 ; color reversed-bit setting bytes
clrset db ? ; Temp for SET Term Tabstops xxx
; This is data for the extended set terminal parameters. It was put here
; in order to keep the size of msyz10.asm within limits for assembly by
; MASM 4. The corresponding code is conatained in VTS and VTSTAT below.
erms41 db cr,lf,'?More parameters are needed$'
vthlp db ' one of the following:',cr,lf
db ' terminal types of: None, Heath-19, VT52, VT102, VT320,'
db ' or Tek4010',cr,lf
db ' Newline-mode Cursor-style Character-set'
db cr,lf
db ' Keyclick Margin-bell Screen-background'
db ' (normal, reverse)',cr,lf
db ' Tabstops Wrap (long lines) Color (fore & background)'
db cr,lf,' Bell audible or visual'
db cr,lf,' Clear-screen (clears old startup screen)'
db cr,lf,' Controls 7-bit or 8-bit (permits VT320 to use'
db ' 8-bit control sequences (C1))'
db cr,lf,' Direction Left-to-right or Right-to-left'
db ' (screen writing direction)'
db cr,lf,' Graphics (type of display adapter when in Tek4010'
db ' mode)'
db cr,lf,' Keypad numeric (normal) or application mode'
db cr,lf,' Replay filespec (display a file through the emulator)'
db cr,lf,' Rollback (undo screen roll back before writing new'
db ' chars, default=off)$'
clrhlp db ' one of the following:'
db cr,lf,' AT #s (to set tabs at column #s) or'
db ' AT start-column:spacing'
db cr,lf,' Clear AT #s (clears individual tabs) or'
db ' AT start-column:spacing'
db cr,lf,' Clear ALL (to clear all tabstops)'
db cr,lf,' Ex: Set term tab at 10, 20, 34 sets tabs'
db cr,lf,' Ex: Set term tab at 1:8 sets tabs at 1, 9,'
db cr,lf,' Ex: Set term tab clear at 9, 17, 65 clears tabs'
db cr,lf,' Ex: Set term tab clear at 1:8 clears tabs at 1, 9,'
db ' 17,...$'
tbserr db cr,lf,'?Column number is not in range 1 to screen width-1$'
colhlp db cr,lf,' Set Term Color value, value, value, ...'
db cr,lf,' 0 no-snow mode on an IBM CGA and white on black'
db cr,lf,' 1 for high intensity foreground'
db cr,lf,' 10 for fast CGA screen updating (may cause snow)'
db cr,lf,' Foreground color (30-37) = 30 + sum of colors'
db cr,lf,' Background color (40-47) = 40 + sum of colors'
db cr,lf,' where colors are 1 = red, 2 = green, 4 = blue'
db cr,lf,' Ex: 0, 1, 37, 44 IBM CGA(0), bright(1) white(37)'
db ' chars on a blue(44) field'
db cr,lf,' Attributes are applied in order of appearance.$'
colerr db cr,lf,'?Value not in range of 0, 1, 10, 30-37, or 40-47$'
vtwrap db 'Term wrap-lines: $'
vtbellm db 'Term margin-bell: $'
vtnewln db 'Term newline: $'
vtcur db 'Term cursor-style: $'
vtcset db 'Term character-set: $'
vtclik db 'Term key-click: $'
vtscrn db 'Term screen-background: $'
colst1 db 'Term color foregnd:3$'
colst2 db ' backgnd:4$'
vtrolst db 'Term rollback: $'
vtdir db 'Term direction: $'
vtcntst db 'Term controls: $'
vtkpst db 'Term keypad: $'
vtbset db 'Term bell: $'
vtgchst db 'Term graph char: $'
; terminal emulator
vtstbl stent <srchkw,vtcset,chatab,vtemu.vtchset> ; char set
stent <srchkb,vtclik,ontab,vskeyclick,vtemu.vtflgop> ; keyclick
stent <srchkb,vtwrap,ontab,vswrap,vtemu.vtflgop> ; line wrap
stent <srchkb,vtcntst,cntltab,vscntl,vtemu.vtflgop> ; controls
stent <srchkb,vtbellm,ontab,vsmarginbell,vtemu.vtflgop>;margin bell
stent <srchkb,vtcur,curtab,vscursor,vtemu.vtflgop> ; cursor type
stent <srchkw,vtbset,beltab,belltype> ; bell
stent <srchkb,vtdir,dirtab,vswdir,vtemu.vtflgop> ; write direct
stent <srchkb,vtnewln,ontab,vsnewline,vtemu.vtflgop> ; newline
stent <srchkw,vtrolst,ontab,vtroll> ; rollback
stent <srchkb,vtkpst,kpamtab,deckpam,vtemu.vtflgop> ; keypad
stent <srchkb,vtscrn,scrtab,vsscreen,vtemu.vtflgop> ; screen
dw 0 ; end of table
; end of Terminal data set
vttbl db 19 ; number of entries
mkeyw 'Bell',8800h ; note 8800 flag for decoding
mkeyw 'Character-set',chaval+8300h
mkeyw 'Clear-screen',8500h ; 8500h = marker here
mkeyw 'Color',8200H ; screen fore/back colors; 200H=marker
mkeyw 'Controls',cntlval
mkeyw 'Cursor-style',curval
mkeyw 'Direction',dirval
mkeyw 'Graphics',8600h ; Tek graphics board, 800h=marker
mkeyw 'Heath-19',ttheath+8100H; note 8100H flag for decoding here
mkeyw 'Keyclick',keyval
mkeyw 'Keypad',kpamval
mkeyw 'Margin-bell',marval
mkeyw 'None',ttgenrc+8100H
mkeyw 'Newline',newval
mkeyw 'Replay',8700h ; note 8700H flag for file replaying
mkeyw 'Rollback',8400h ; note 8400H flag for decoding
mkeyw 'Screen-background',scrval
mkeyw 'Tabstops',tabval
mkeyw 'Wrap',wraval
vtsflg equ this word ; define small digits xxxval
newval equ $-vtsflg ; 0 and mask for bit in byte
dw vsnewline ; 1
wraval equ $-vtsflg ; 2
dw vswrap ; 2
chaval equ $-vtsflg ; 4
dw vsnrcm ; 4
dirval equ $-vtsflg ; 6
dw vswdir ; 8
keyval equ $-vtsflg ; 8
dw vskeyclick ; 10h
marval equ $-vtsflg ; 10
dw vsmarginbell ; 20h
curval equ $-vtsflg ; 12
dw vscursor ; 40h
scrval equ $-vtsflg ; 14
dw vsscreen ; 80h
cntlval equ $-vtsflg ; 16
dw vscntl ; 100h
kpamval equ $-vtsflg ; 18
dw deckpam ; 400h
numflgs equ ($-vtsflg)/2 ; 10
tabval equ $-vtsflg ; 20
dw 0
;vtrtns dw numflgs dup (flgset), tabmod ; dispatch table for vtsflg
data ends
code segment public
extrn comnd:near, dopar:near, defkey:near, getpos:near, atsclr:near
extrn lclyini:near, setcol:near, srchkb:near, srchkw:near
extrn csrtype:near
assume cs:code, ds:data, es:nothing
; local initialization
LCLINI proc near
jmp lclini1 ; Bypass the exit code
not_z10:mov ah,prstr
mov dx,offset not_z ; This is not a Z-100, IBM PC maybe?
int dos ; This program is for
mov dx,offset verident ; display version header
int dos
mov ah,4ch ; terminate process
int dos
; Find out if this is a Z-100
; We are doing that by looking for 0E9H at locations 0040:0000H
; and 0040:0003H which are in the Z-100 bios jump table.
lclini1:mov bx,BIOS_SEG ; The segment at 40h
mov ax,es ; Save es
mov es,bx ; Set up the extra segment
cmp byte ptr es:0,0e9h ; Z-100?
jnz not_z10 ; No, it's probably IBM compatible
cmp byte ptr es:3,0e9h ;Z-100?
jnz not_z10 ; No, it's probably IBM compatible
mov es,ax ; Restore es
;
mov flags.vtflg,ttheath ; Set Heath-19 emulation mode, allows macs
mov brkval,BRKBIT ; What to send for a break
in al,mdmcom4 ; Check this port
and al,modperb ; Is it there?
jnz lclini3 ; No, skip
mov dx,offset com4ms1
mov ah,prstr ; Tell user it is there
int dos
in al,mdmcom4 ; Check again
and al,moddcdb ; Carrier?
jz lclini3 ; No, skip
mov flags.comflg,4 ; Indicate s-100 port 2 for now
mov portval,offset port4
mov mddat0,mdmdat4
mov mdstat0,mdmcom4
mov ah,prstr ; Tell user
mov dx,offset com4ms
int dos
lclini3:in al,mdmcom3 ; Check this port
and al,modperb ; Is it there?
jnz lclini4 ; No, skip
mov dx,offset com3ms1
mov ah,prstr ; Tell user it is there
int dos
in al,mdmcom3 ; Check again
and al,moddcdb ; Carrier?
jz lclini4 ; No, skip
mov flags.comflg,3 ; Indicate s-100 port 1
mov portval,offset port3
mov mddat0,mdmdat3
mov mdstat0,mdmcom3
mov ah,prstr ; Tell user
mov dx,offset com3ms
int dos
lclini4:
call getbaud ; Which port of COM1/COM2 is default?
; Get baud rate from UARTs for this
call baudref ; Set up baud rate references bdtab, bddat
mov port3.baud,bds100 ; and put in default baud rate
mov port4.baud,bds100 ; and put in default baud rate
mov lclsusp,offset suspend ; call this when suspending to DOS
mov lclrest,offset restore ; call this when returning from DOS
mov lclexit,offset finexit ; call this when exiting Kermit
call ena_wrp ; Make terminal wrap to next line at line end
call lclyini ; let other modules initialize too...
ret ; We are all done with lclini
;
baudref:push di ; Rearrange bdtab and bddat
push si
push es
mov ax,ds ; Set up
mov es,ax ; pointers
mov di,offset bddat ; to move baud
mov si,offset bddat12 ; rate selection
mov cx,lbddat ; length of table
cmp flags.comflg,2 ; Ports 1/2
jle lclini5 ; or ports 3/4?
mov si,offset bddat34 ;Port 4!
lclini5:cld
rep movsb ; Move array
mov di,offset bdtab ; This too
mov si,offset bdtab12
mov cx,lbdtab12 ; Length of table
cmp flags.comflg,2 ; Ports 1/2
jle lclini6 ; or ports 3/4?
mov si,offset bdtab34 ;Port 4!
lclini6:rep movsb ; Move array
pop es ; Restore registers
pop si
pop di
ret ; We're done
LCLINI endp
; Call these routines when suspending Kermit to go to DOS
suspend proc near
call ihosts ; suspend the host
call serrst
call dis_scan ; disable scan code generation
call dis_wrp ; disable sreen line wrap around
ret
suspend endp
; Call these routines when returning to Kermit from DOS
restore proc near
call serini ; reinit serial port
call ihostr ; resume the host
call ena_wrp ; enable screen line wrap around
ret
restore endp
; Call these routines when doing final exit of Kermit
finexit proc near
call serrst ; reset serial port
call dis_scan ; disable scan code generation
call dis_wrp ; disable sreen line wrap around
ret
finexit endp
; This routine, ena_scan, enables Z-100 scan code generation. It also
; disables extended key code generation. Modifies ax.
ENA_SCAN PROC NEAR
push dx
mov ah,prstr
mov dx,offset enascan
int dos
or dosflg1,1 ; say scan codes enabled
pop dx
ret
ENA_SCAN ENDP
; This routine, dis_scan, disables Z-100 scan code generation. It also
; enables extended key code generatin. Modifies ax.
DIS_SCAN PROC NEAR
push dx
mov ah,prstr
mov dx,offset disscan
int dos
and dosflg1,0feh ; say scan codes disabled
pop dx
ret
DIS_SCAN ENDP
; This routine, ena_wrp, enables wrap around at end of line.
; Modifies ax.
ENA_WRP PROC NEAR
push dx
mov ah,conout
mov dl,ESCAPE
int dos
mov dl,'v'
int dos
pop dx
ret
ENA_WRP ENDP
; This routine, dis_wrp, disables wrap around at end of line.
; Modifies ax.
DIS_WRP PROC NEAR
push dx
mov ah,conout
mov dl,ESCAPE
int dos
mov dl,'w'
int dos
pop dx
ret
DIS_WRP ENDP
; SHOW MODEM, displays current status of lines DSR, CD, and CTS.
; Uses byte mdmhand, the modem line status register. [jrd]
shomodem proc near
mov ah,cmeol ; get a confirm
call comnd
jc shomd5 ; c = failure
mov dx,offset msmsg7 ; no modem status for network
call getmodem ; get modem status
mov ah,prstr
cmp flags.comflg,2 ; port 1 or 2
jle shomd0 ; yes, jump
mov dx,offset msmsg0 ; not supported function
jmp shomd1
shomd0: mov dx,offset msmsg1 ; modem not ready msg
test mdmhand,20h ; is DSR asserted?
jz shomd1 ; z = not ready
mov dx,offset msmsg2 ; modem ready msg
shomd1: int dos
mov dx,offset msmsg3 ; CD not asserted msg
test mdmhand,80h ; CD asserted?
jz shomd2 ; z = not asserted
mov dx,offset msmsg4 ; CD asserted msg
shomd2: int dos
clc
shomd5: ret
shomodem endp
; Get modem status and set global byte mdmhand. Preserve all registers but dx.
; Returns with byte mdmhand in al, ah=0.
getmodem proc near ; gets modem status upon request
cmp flags.comflg,2 ; COM1 or COM2?
jna getmodem2 ; na = yes, jump to handle these
mov dx,mdstat0 ; Port address
in al,dx ; Get status
and al,moddcdb ; Carrier?
mov mdmhand,0 ; Everything off
jz getmodem1 ; z = yes, no carrier, done
mov mdmhand,80h ; No, carrier detected
getmodem1:jmp getmodem4 ; Done with COM3/COM4
getmodem2:mov dx,portadr
add dx,PSTATUS
in al,dx
mov mdmhand,0 ; Everything off
test al,DSR ; DSR indicated?
jz getmodem3 ; z = no, go on
mov mdmhand,20h ; Indicate DSR
getmodem3:test al,DCD ; CD indicated?
jz getmodem4 ; z = no, go on
or mdmhand,80h ; Indicate CD, don't touch DSR
getmodem4:mov al,mdmhand ; Promised it here
xor ah,ah ; A promise too
clc ; Success
ret
getmodem endp
; Clear the input buffer. This throws away all the characters in the
; serial interrupt buffer. This is particularly important when
; talking to servers, since NAKs can accumulate in the buffer.
CLRBUF PROC NEAR
cmp flags.comflg,2 ; Ports 1/2?
jg clrbuf1 ; g = no, do S-100 stuff
cli
push bx
xor bx,bx
mov bufoend,bx
mov bufobeg,bx
mov bufiend,bx
mov bufibeg,bx
pop bx
mov count,0
sti
ret
clrbuf1:push ax ; First empty port
push dx
mov dx,mddat0 ; Get possible
in al,dx ; character
pop dx
pop ax ; then do it
mov count,0 ; Nothing in buffer
mov srcpnt,offset source ; Reset buffer
mov savedi,offset source ; pointers
ret
CLRBUF ENDP
; Put the char in AH to the serial port, assumimg the port is active.
; Returns carry clear if success, else carry set.
; 16 May 1987 Add entry point OUTCH2 for non-flow controlled sending to
; prevent confusion of flow control logic at top of outchr; used by receiver
; buffer high/low water mark flow control code. [jrd]
; 14 September 1990 add entry point OUTCH5 for priority sending of xon;
; used by CHKXON and SERISR.
OUTCHR PROC NEAR
cmp flowoff,0 ; Are we doing flow control
je outch2 ; No, just continue
cmp ah,flowoff ; sending xoff?
jne outch1 ; ne = no
mov xofsnt,usron ; indicate user level xoff being sent
jmp outch12
outch1:and xofsnt,not usron ; cancel user level xoff
cmp ah,flowon ; user sending xon?
jne outch12 ; ne = no
mov xofsnt,off ; say an xon has been sent (cancels xoff)
outch12:mov timer,xoftime+1 ; Set delay to xoftime minimum, maximum+1 sec
outch14:cmp xofrcv,true ; Are we being held (xoff received)?
jnz outch2 ; no - it's OK to go on
cmp flags.comflg,2 ; Check if S-100 ports
push ax ; Save regs
push bx
push cx
push dx
jle outch16 ; No, make it simple
push es
mov cx,1 ; No delay for sprtch
call sprtch ; Get possible char at port com3/4
pop es
outch16:mov ah,gettim ; Get time function
int dos
cmp dl,timer0 ; Normally 0
pop dx
pop cx
pop bx
pop ax
jnz outch14 ; No, go loop
xor timer0,50 ; Yes, move target 1/2 second
cmp timer0,0 ; This is only true every second
jnz outch14 ; No, continue looping
dec timer ; Yes, one second has passed (unless 1st time)
jnz outch14 ; No, have more seconds left, try again
mov xofrcv,off ; Timed out, force it off and fall thru.
OUTCH2 LABEL NEAR ; outch2 entry point without flow control
mov al,ah ; Routine works on AL.
call dopar ; Set parity appropriately.
cmp repflg,0 ; Doing REPLAY from a file?
je outch24 ; e = no
and al,7fh ; Strip parity
cmp al,'C'-40h ; Control-C? (to exit playback mode)
je outch22 ; e = yes, return failure
clc ; Return success, send nothing
ret
outch22:stc ; Return failure to exit playback mode
ret
;
outch24:push bx
push dx
cmp flags.comflg,2 ; Ports J1/J2
jle outch4 ; Yes, go handle J1/J2
mov bl,al ; No, do S-100, save byte to send
push cx
xor cx,cx ; Set loop counter
outch26:push bx ; Check on input
push cx
push es
mov cx,1 ; No delay
call sprtch ; Get char from port if any
pop es
pop cx
pop bx
mov dx,mdstat0
in al,dx ; Check this port
and al,modsndb ; for ready
jnz outch28 ; Ready, continue
loop outch26 ; Not ready, loop until ready or timeout
jmp short outch44 ; Timed out, return with carry set
outch28:pop cx
mov al,bl ; Get back byte to send
mov dx,mddat0
out dx,al ; Send it out
jmp outch8 ; All done S-100 modem
;
outch4: push cx
xor cx,cx ; Set loop counter
outch40:mov bx,bufobeg ; get pointer to beginning of que
sub bx,bufoend ; where are we?
jnl outch42 ; we did not wrap
add bx,BUFOLEN ; we have wrapped
outch42:cmp bx,BUFOLEN-2 ; we have bx char in buffer; is it full?
jnae outch53 ; no, go on
loop outch40 ; yes, loop until there is space or timeout
outch44:pop cx ; timed out
pop dx
pop bx
stc
ret
;
outch5: push bx ; OUTCH5 entry for SERISR and CHKXON
push dx ; ah will contain xon or xoff only
push cx
xor cx,cx ; Set loop counter
outch50:mov bx,bufobeg ; get pointer to beginning of que
sub bx,bufoend ; where are we?
jnl outch51 ; we did not wrap
add bx,BUFOLEN ; we have wrapped
outch51:cmp bx,BUFOLEN ; we have bx char in buffer; is it full?
jne outch52 ; no, go on
loop outch50 ; yes, loop until there is space or timeout
jmp short outch44 ; timed out, no space
outch52:mov al,ah ; Routine works on AL.
call dopar ; Set parity appropriately.
pop cx
jmp short outch54
;
outch53:pop cx ; restore stack
cmp bx,0 ; buffer empty?
jz outch58 ; yes, skip
cmp flowoff,0 ; Are we doing flow control
je outch58 ; No, skip
cmp al,flowoff ; Is it xoff?
je outch54 ; Yes, this is priority, expedite
cmp al,flowon ; Is it xon?
jne outch58 ; No, skip
;
outch54:cli
mov bx,bufobeg ; beginning of que
dec bx ; we want space in between, bx still >= 0
jae outch56 ; yes, go on
mov bx,BUFOLEN ; wrap
outch56:mov bufobeg,bx ; new beginning
mov byte ptr buffout[bx],al ; put char in it
sti
jmp short outch6
outch58:mov bx,bufoend
mov byte ptr buffout[bx],al ; put char in it
inc bx ; point to next spot in que
cmp bx,BUFOLEN ; looking at end of que ?
jne outch6 ; no, OK
xor bx,bx ; yes, reset pointer
outch6: mov bufoend,bx ; store new value
mov dx,portadr
add dx,PCOMM
cli
in al,dx
test al,TXON ; TX already on ?
jnz outch7 ; yes, OK
or al,TXON ; no, turn it on
out dx,al ; it's on
outch7: sti ; done with 2661
outch8: pop dx
pop bx
clc ; success, return with carry cleared
ret
OUTCHR ENDP
; Move the cursor to the left margin, then clear to end of line.
CTLU PROC NEAR
mov ah,prstr
mov dx,offset clrlin
int dos
; Clear to the end of the current line
CLEARL PROC NEAR
push ax
push dx
mov ah,prstr
mov dx,offset eeolstr ; Erase to end of line
int dos
pop dx
pop ax
ret
CLEARL ENDP
CTLU ENDP
; This routine blanks the screen and homes the cursor. Uses ax and dx.
CMBLNK PROC NEAR
mov ah,prstr
mov dx,offset clrstr ; Home cursor, blank screen
int dos
ret
CMBLNK ENDP
; Locate: homes the cursor. Uses ax and dx.
LOCATE PROC NEAR
mov ah,prstr
mov dx,offset home ; Go to top left corner of screen.
int dos
LOCATE ENDP
; write a line in inverse video at the bottom of the screen...
; the line is passed in dx, terminated by a $.
PUTMOD PROC NEAR
push ax ; save regs
push dx ; preserve message
mov ah,prstr
mov dx,offset savcur
int dos
mov dx,offset enamod
int dos
mov dx,offset lin25
int dos
mov dx,offset begrev
int dos
pop dx ; get message back
int dos ; write it out
mov dx,offset endrev
int dos
mov dx,offset precur
int dos
pop ax
ret ; and return
PUTMOD ENDP
; clear the mode line written by putmod.
CLRMOD PROC NEAR
mov ah,prstr
mov dx,offset dismod
int dos
ret
CLRMOD ENDP
BEEP PROC NEAR
push ax ; save regs
push dx ; preserve message
mov ah,conout
mov dl,BELL ; ASCII BEL
int dos ; Ring it
pop dx
pop ax
clc
ret
BEEP ENDP
; Put a help message on the screen. This one uses reverse video...
; pass the message in ax, terminated by a null. Messes up ax, bx, cx, dx.
PUTHLP PROC NEAR
push si
push ax ; preserve this
mov dx,offset crlf
int dos
pop si ; point to string again
jmp short puthl3 ; assume message begins with cr and lf
puthl2: call getpos ; get cursor pos into dx
mov ax,dx ; from row ah, col al
mov bx,dx
mov bl,COLUMNS ; to row bh, col bl
mov dx,word ptr doscol ; dos color reversed
call setcol ; set this color
call atsclr ; and clear the line
puthl3: mov cx,COLUMNS - 1 ; characters on a line less one (starts at 0)
puthl4: lodsb ; get a byte
mov ah,conout ; print char
cmp al,0 ; end of string?
je puthl5 ; yes, stop
cmp al,lf ; lf ?
je puthl7 ; end of line, do new one
cmp cx,0 ; last column
je puthl6 ; no more space on line, get new one
mov dl,al ; else, print char
int dos
jmp short puthl3 ; get next char
puthl5: pop si
ret
puthl6: mov dl,cr
int dos
puthl7: mov dl,lf
int dos
jmp short puthl2
PUTHLP ENDP
; Set the baud rate for the current port, based on the value
; in the portinfo structure. Returns carry clear.
BAUDST PROC NEAR
mov dx,offset bdtab ; baud rate table, ascii
xor bx,bx ; help is the table itself
mov ah,cmkey ; get keyword
call comnd
jc baudst1 ; c = failure
push bx ; save result
mov ah,cmeol ; get confirmation
call comnd
pop bx
jc baudst1 ; c = failure
push si
mov si,portval
mov ax,[si].baud ; remember original value
mov [si].baud,bx ; set the baud rate
pop si
call dobaud ; use common code
clc
baudst1:ret
BAUDST ENDP
DOBAUD PROC NEAR
push ax ; save some regs
push bx
push cx
push dx
mov bp,portval ; Pointer to port data structure
mov temp,ax ; Don't overwrite previous rate
mov ax,ds:[bp].baud ; Check if new rate is valid
shl ax,1 ; Get index into baud table
mov bx,offset bddat ; Start of table.
add bx,ax
mov ax,[bx] ; The data to output to port.
cmp ax,0FFH ; Unimplemented baud rate.
jne dobd0
mov ax,temp ; Get back orginal value.
mov ds:[bp].baud,ax ; Leave baud rate as is.
mov ah,prstr
mov dx,offset badbd ; Give an error message.
int dos
stc ; Failure
jmp dobd2
dobd0: mov ds:[bp].baud,ax ; Put in new baud rate
cmp flags.comflg,2 ; is it J1/J2?
jle dobd1 ; yes, go do J1/J2 stuff
call serini ; go set rate in S-100 modem
jmp dobd2
dobd1: mov dx,portadr ; get addr to send it
add dx,PMODE
push ax ; save baud
mov al,MODE1
cli ; none while setting 2661
out dx,al ; mode reg 1/2
pop ax ; get baud back
and al,0fH ; make sure it's clean
or al,MODE2 ; make complete mode 2/2 command
out dx,al ; set mode reg 2/2
sti ; done with 2661
clc ; Success
dobd2: pop dx ; restore regs
pop cx
pop bx
pop ax
ret
DOBAUD ENDP
; Get the current baud rate from the serial card and set it
; in the portinfo structure for the current port.
; Also finds out which serial port, A (COM2) or B (COM1), is defined
; as default by Zenith Configur.
; This is used during initialization.
GETBAUD PROC NEAR
cmp flags.comflg,2 ; J1/J2?
jg getbau3 ; No, all done
push ax
push bx
push dx
push di
cmp portadr,0 ; Just started Kermit?
jnz getbau2 ; No, skip this
mov bx,ds ; Set up pointer to config info
mov es,bx
mov bx,offset auxconf
mov ah,chr_status
mov al,chr_sfgc ; Get current config info
call bios_auxfunc
cmp auxconf.cfport,mdmdat1 ; Is it B?
jne getbau1 ; ne = no
mov flags.comflg,1 ; Set flag to indicate port B
mov portval,offset port1
mov mddat0,mdmdat1
mov portadr,mdmdat1
mov mdstat0,mdmcom1
jmp getbau2
getbau1:mov flags.comflg,2 ; Set flag to indicate port A
mov portval,offset port2
mov mddat0,mdmdat2
mov portadr,mdmdat2
mov mdstat0,mdmcom2
getbau2:mov dx,portadr ; Get addr to retrieve mode from
add dx,PMODE
in al,dx ; Read and discard mode 1/2
in al,dx ; mode 2/2 has baud rate
and ax,000fH ; Clean it up
mov bp,portval
mov ds:[bp].baud,ax ; Put it in portinfo struct
pop di
pop dx
pop bx
pop ax
getbau3:ret
GETBAUD ENDP
; Get Char from serial port buffer.
; returns carry set if no character available at port, otherwise prtchr
; returns carry clear with char in al, # of chars in buffer in dx and count.
PRTCHR PROC NEAR
cmp flags.comflg,2 ; check if S-100 ports
jg prtch4 ; Yes, go do S-100 stuff
call chkxon ; see if we need to xon
cmp repflg,0 ; REPLAY?
je prtch0 ; e = no
jmp prtch30 ; yes, do replay file reading
prtch0: cli ; dont let intterrupts touch buffers
mov dx,bufiend ; compute number of chars in
sub dx,bufibeg ; input que
jge prtch1 ; is it wrapped around
add dx,BUFILEN ; yes, make it +
prtch1: cmp dx,0 ; anything in there ?
jne prtch2 ; ne = yes. [jrd]
mov count,dx
sti
stc ; no
ret
prtch2: mov bx,bufibeg ; yes, get the char, get the position
mov al,byte ptr buffin[bx] ; get the char
inc bx ; bump the position ptr
cmp bx,BUFILEN ; wrap it ?
jne prtch3
xor bx,bx ; yes, reset pointer
prtch3: mov bufibeg,bx ; store new value
dec dx ; we took one char out
mov count,dx ; save
sti
clc ; yes, got it
ret
prtch4:
push ax ; First check port for possible input
push bx
push cx
push es
mov cx,1 ; Parameter for sprtch, cx=1 means don't loop
call sprtch ; Read port
pop es
pop cx
pop bx
pop ax
cmp repflg,0 ; REPLAY?
je prtch41 ; e = no
jmp prtch30 ; yes, do replay file reading
prtch41:cmp count,0 ; Buffer empty?
jne prtch5 ; ne = no, get char
mov dx,0 ; Nothing there Is this needed?
stc ; Got nothing
ret
prtch5: push si ; Don't mess up, used by spack
mov si,srcpnt ; Point to next character in que
cld
lodsb ; Get the next one
cmp si,offset source + bufsiz ; Bigger than buffer?
jb prtch6 ; No, keep going
mov si,offset source ; Yes, wrap around
prtch6: dec count
mov dx,count
mov srcpnt,si
pop si ; Left in good shape
clc ; Yes, got it
ret
prtch30:cmp repflg,2 ; at EOF already?
jne prtch31 ; ne = no
stc ; yes, return with no char
ret
prtch31:push bx ; REPLAY, read char from a file
push cx
xor dx,dx
test xofsnt,usron ; user level xoff sent?
jz prtch32 ; z = no
pop cx ; suppress reading here
pop bx
stc ; return with no char
ret
prtch32:mov ax,100
mov bx,1
jmp $+2 ; flush lookahead buffer
div bx ; burn some cpu cycles
div bx ; because a 1 ms wait is too long
div bx
div bx
mov ah,readf2
mov bx,diskio.handle ; file handle
mov cx,1 ; read one char
mov dx,offset rdbuf ; to this buffer
int dos
jc prtch34 ; c = read failure
cmp ax,cx ; read the byte?
jne prtch34 ; ne = no
pop cx
pop bx
mov al,rdbuf ; get the char into al
mov dx,1 ; external char count
clc
ret ; return it
prtch34:call beep
mov ax,40 ; wait 40 millisec
call pcwait
call beep
mov repflg,2 ; say at EOF
pop cx
pop bx
stc ; say no char
ret
PRTCHR ENDP
; Examine incoming communications stream for a packet SOP character.
; Return CX= count of bytes starting at the SOP character (includes SOP)
; and carry clear. Return CX = 0 and carry set if SOP is not present.
; Destroys AL.
peekcom proc far
mov cx,count ; qty in circular buffer
cmp cx,6 ; basic NAK
jb peekc4 ; b = two few chars, get more
push bx
cli ; interrupts off, to keep srcpnt & count consistent
mov bx,srcpnt ; address of next available slot in buffer
sub bx,cx ; minus number of unread chars in buffer
cmp bx,offset source ; located before start of buf?
jae peekc1 ; ae = no
add bx,bufsiz ; else do arithmetic modulo bufsiz
peekc1: mov al,[bx]
cmp al,trans.rsoh ; packet receive SOP?
je peekc3 ; e = yes
inc bx
cmp bx,offset source+bufsiz ; beyond end of buffer?
jb peekc2 ; b = no
mov bx,offset source ; wrap around
peekc2: loop peekc1 ; keep looking
sti
pop bx
stc ; set carry for no SOP
ret
peekc3: sti ; interrupts back on now
pop bx
inc cx ; include SOP in count
clc ; say SOP found
ret ; CX has count remaining
peekc4: xor cx,cx ; return count of zero
stc ; say no data
ret
peekcom endp
; local routine to see if we have to transmit an xon when com1/2
chkxon proc near
cmp xofsnt,false ; have we sent an xoff?
je chkxo1 ; no, forget it
cmp flowoff,0 ; Are wo doing flow control?
je chkxo1 ; no, skip all this
test xofsnt,usron ; did user send an xoff?
jnz chkxo1 ; nz = yes, don't contradict it here
test xofsnt,bufon ; have we sent a buffer level xoff?
jz chkxo1 ; z = no, forget it
cmp count,mntrgl ; below trigger?
jae chkxo1 ; no, forget it
mov ah,flowon ; xon
call outch5 ; send it
jc chkxo1 ; failure
and xofsnt,false ; remember we've sent the xon.
chkxo1: ret ; and return
chkxon endp
; Local routine to see if we have to transmit an xoff or xon when com3/4
; this is probably overdoing it
; called by sprtch
chkxof proc near
cmp flowoff,0 ; Are wo doing flow control?
je chkxof1 ; no, skip all this
test xofsnt,usron ; did user send an xoff?
jnz chkxof1 ; nz = yes, don't contradict it here
test xofsnt,bufon ; have we sent a buffer level xoff?
jz chkxof1 ; z = no, forget it
cmp count,mntrgh ; Buffer filling up?
jb chkxof3 ; no, go check that xon sent
cmp xofsnt,true ; yes, have we sent an xoff?
je chkxof1 ; yes, all done
mov ah,flowoff ; xoff
mov xofsnt,true ; remember we've sent the xoff.
jmp short chkxof2 ; go send xoff
chkxof3:cmp count,mntrgl ; below trigger
jae chkxof1 ; no, forget it
cmp xofsnt,false ; xon sent?
je chkxof1 ; all done
mov ah,flowon ; xon
chkxof2:call outch2 ; send it
chkxof1:ret ; and return
chkxof endp
; Read the serial port for the S-100 modem and put input in buffer.
; Call with delay loop count in cx, c = 1 means no delay.
; Input stream is monitored for xon/xoff.
; Called by outchr, prtchr and outtty.
; Destroys ax, bx, cx, dx, es
SPRTCH PROC NEAR
mov bx,ds ; Point to data segment
mov es,bx
mov dx,mdstat0 ; Check
in al,dx ; status
and al,modrcvb ; Character at port?
jnz sprtch2 ; Yes, go get it
call chkxof
loop sprtch0 ; Keep checking port if cx not=1
ret ; No data
sprtch0:push cx
xor cx,cx ; This is a delay loop to expand the delay for
mov cl,trans.rtime ; screen escape sequencies and capture.
or cx,cx ; avoid 0, it will loop for ever
jnz sprtch1
inc cx
sprtch1:loop sprtch1 ; The delay time is controlled through the
pop cx ; receive timeout setting.
jmp sprtch
sprtch2:mov dx,mddat0 ; Get
in al,dx ; character
mov ah,al ; Make working copy
and ah,parmsk ; Strip parity
mov bx,portval
cmp [bx].floflg,0 ; Are we doing flow control.
jz sprtch4 ; No, skip
mov dx,[bx].flowc
cmp ah,dh ; xon?
jne sprtch3 ; No, check xoff
mov xofrcv,off ; Set flag to indicate xoff not received (xon)
jmp short sprtch6 ; Get the next char
sprtch3:cmp ah,dl ; xoff?
jne sprtch4 ; No, go do normal buffer handling
mov xofrcv,true ; Set flag to indicatae xoff received
jmp short sprtch6 ; Get the next char
sprtch4:push di
mov di,savedi ; Point to last received char
cld
stosb ; Save the next one
cmp di,offset source + bufsiz ; Bigger than buffer?
jb sprtch5 ; No, keep going
mov di,offset source ; Yes, wrap around
sprtch5:inc count
mov savedi,di
pop di
sprtch6:call chkxof
loop sprtch0 ; Keep checking port if cx not=0
ret
SPRTCH ENDP
; IHOSTS - Initialize the host by sending XOFF, or equivalent.
; Requires that the port be initialized before hand.
; Do not send flow control if doing half duplex.
IHOSTS PROC NEAR
push ax ; save the registers
push cx
push dx
mov xofrcv,off ; clear old xoff received flag
mov xofsnt,off ; and old xoff sent flag
mov ah,flowoff ; put wait flow control char in ah
or ah,ah ; check for null char
jz ihosts1 ; z = null, don't send it
cmp dupflg,0 ; full duplex?
jne ihosts1 ; ne = no, half
call outchr ; send it
ihosts1:call clrbuf ; clear out interrupt buffer
pop dx ; empty buffer. we are done here
pop cx
pop ax
ret
IHOSTS ENDP
; IHOSTR - initialize the remote host for our reception of a file by
; sending the flow-on character (XON typically) to release any held
; data. Called by receive-file code just after initializing the serial
; port. 22 March 1986 [jrd]
IHOSTR PROC NEAR
push ax ; save regs
push bx
push cx
mov bx,portval ; port indicator
mov ax,[bx].flowc ; put Go-ahead flow control char in ah
or ah,ah ; check for null char
jz ihostr1 ; z = null, don't send it
call outchr ; send it (release Host's output queue)
ihostr1:pop cx
pop bx
pop ax
ret
IHOSTR ENDP
; Global proc to Hangup the Phone or Network by making DTR and
; RTS low (phone).
DTRLOW PROC NEAR
mov ah,cmline ; allow text, to be able to display help
mov bx,offset rdbuf ; dummy buffer
mov dx,offset hnghlp ; help message
call comnd ; get a confirm
jc dtrlow3 ; c = failure
cmp flags.comflg,'0' ; Bios?
jb dtrlow1 ; b = no, UART
cmp flags.comflg,'4' ; Bios?
jbe dtrlow2 ; be = yes, can't access modem lines
dtrlow1:call serhng ; drop DTR and RTS
cmp taklev,0 ; in a Take file or macro?
jne dtrlow2 ; ne = yes, no message
mov ah,prstr ; give a nice message
mov dx,offset hngmsg
int dos
dtrlow2:clc ; success
dtrlow3:ret
DTRLOW ENDP
; Hang up the Phone. Similar to SERRST except it just forces DTR and RTS low
; to terminate the connection. (com1 and com2)
; The USR S-100 modem will not respond to dropping of DTR. Instead the +++
; sequence must be sent.
; Calling this twice without intervening calls to serini should be harmless.
SERHNG PROC NEAR
cmp flags.comflg,2 ; Which port?
jg serhng1
cli
call porton ; Insure that DTR and RTS are high
sti
mov dx,portadr
add dx,PCOMM
in al,dx
xor al,DTR ; Drop DTR
xor al,RTS ; Drop RTS
out dx,al
mov ax,500 ; 500 millisec, for pcwait
call pcwait ; keep lines low for at least 500 millisec
clc
ret
serhng1:mov dx,mdstat0 ; Port address. [19b]
in al,dx ; Get status
and al,moddcdb ; Carrier?
jz serhng4 ; No, tell user
mov ah,prstr ; Yes, tell user to wait
mov dx,offset wmsg
int dos
mov ax,1100 ; 1100 milliseconds
call pcwait ; Wait before sending '+++'
push si
mov si,offset hngstr ; Point to '+++'
cld
lodsb ; Get the first byte of string
serhng2:push ax ; We need the loaded byte later
mov dx,mdstat0 ; The status port
serhng3:in al,dx ; Get status
and al,modsndb ; Mask for ready
jz serhng3 ; No, go on
pop ax ; Get byte back
mov dx,mddat0 ; The data port
out dx,al ; Send it out
lodsb ; Load next byte
cmp al,'$' ; Finished?
jnz serhng2 ; No, process next
pop si
mov ax,1100 ; 1100 milliseconds
call pcwait ; Wait after sending '+++'
mov dx,mdstat0 ; Port address. [19b]
in al,dx ; Get status
and al,moddcdb ; Carrier?
serhng4:mov ah,prstr
mov dx,offset dscmsg ; Point to message
clc
jz serhng5 ; Yes, no carrier, go tell user
inc cl ; No, carrier detected
cmp cl,3 ; Try three times
jnz serhng1 ; No, go try again
mov dx,offset ndscmsg ; Warn user
serhng5:int dos ; all done
ret
SERHNG ENDP
; Send a break out the current serial port.
SENDBR PROC NEAR
mov brkdur,28 ; Normal break 280ms
jmp sendbr1
sendbl: mov brkdur,180 ; Long break 1800ms
jmp sendbr1
sendbr1:push cx
push dx
push ax
mov dx,mdstat0 ; Port address
cmp flags.comflg,2 ; Which port?
jg sendbr3
in al,dx ; Get current setting
or al,brkval ; Set send-break bit(s)
out dx,al ; Start the break
mov bx,brkdur ; wait this long
call wait01 ; hold break for desired interval
xor al,brkval ; Clear send-break bit(s)
out dx,al ; Stop the break
sendbr2:pop ax
pop dx
pop cx
ret
sendbr3:call pickspd ; Point to speed
mov al,[bx+1] ; Command byte
sub al,8h ; Break byte 8h lower (1fh and 3fh)
cmp al,1fh
je sendbr4
mov al,3fh
sendbr4:out dx,al
mov bx,brkdur ; wait this long
call wait01
call initmod
jmp sendbr2
SENDBR ENDP
; Position the cursor according to contents of DX:
; DH contains row, DL contains column.
POSCUR PROC NEAR
push ax
push dx
cmp flags.comflg,2 ; Ports 1/2
jna poscur1 ; Yes, skip this
push bx ; No, check input port
push cx
push es
mov cx,1 ; No delay
call sprtch ; Get char from port if any
pop es
pop cx
pop bx
poscur1:mov ah,conout
mov dl,ESCAPE
int dos
mov dl,'Y'
int dos
pop dx
push dx
mov dl,dh
add dl,' '
int dos
pop dx
add dl,' '
int dos
pop ax
ret
POSCUR ENDP
; Delete a character from the terminal. This works by printing
; backspaces and spaces.
DODEL PROC NEAR
mov ah,prstr
mov dx,offset delstr ; Erase weird character.
int dos
ret
DODEL ENDP
; select port to be current. Returns with carry clear if success.
COMS PROC NEAR
; mov kstatus,0 ; global status, success
mov dx,offset comptab ; table of legal comms ports
mov bx,offset comsmsg ; point to comsmsg
mov ah,cmkey ; parse key word
call comnd
jnc coms0 ; nc = success
ret ; failure
coms0: call serrst ; uninstall interrupt
call comstrt
jnc coms1
mov ah,prstr
mov dx,offset coms0msg ; Point to no S-100 modem msg
int dos
coms1: clc
ret
comstrt:mov al,flags.comflg
mov tmp,al ; Save the old one in case
mov flags.comflg,bl ; Set the comm port flag.
cmp bl,1 ; COM1 (port B)?
je coms2 ; Yes
cmp bl,2 ; COM2 (port A)?
je coms3 ; Yes
cmp bl,3 ; COM3 (S-100 modem port 1)
je coms4 ; Yes
in al,mdmcom4 ; Check this port
and al,modperb ; Is it there?
jnz coms6 ; No, skip
mov portval,offset port4 ; Must be COM4
mov mddat0,mdmdat4
mov mdstat0,mdmcom4
jmp coms5
coms4: in al,mdmcom3 ; Check this port
and al,modperb ; Is it there?
jnz coms6 ; No, skip
mov portval,offset port3
mov mddat0,mdmdat3
mov mdstat0,mdmcom3
jmp coms5
coms2: mov mdstat0,mdmcom1 ; Set break address for B
mov portadr,mdmdat1 ; Set address for B
mov portval,offset port1 ; Point to portinfo for B
jmp coms5
coms3: mov mdstat0,mdmcom2 ; Set break address for A
mov portadr,mdmdat2 ; Set address for A
mov portval,offset port2 ; Point to portinfo for A
coms5: call baudref ; Set up bdtab and bddat
call getbaud ; See what is in the port now set
clc ; Success
ret
coms6: mov al,tmp
mov flags.comflg,al ; Get the old one back
stc ; Failure
ret
COMS ENDP
; Set heath emulation on/off.
; SET Term parameters, especially for use with VT100 emulator. [jrd]
; Taken from work done originally by James Harvey IUPUI.
; VTS is called only by mssset to set terminal type and characteristics.
; Enter via direct jmp. Exit ret with carry set for failure, else carry
; cleared.
VTS proc near ; SET TERM whatever
mov dx,offset termtb ; terminal table, ascii
xor bx,bx ; help is the table itself
mov ah,cmkey ; get keyword
call comnd
jnc vset1 ; nc = success
ret ; failure
vset1: mov flags.vtflg,bx ; Set the Heath emulation flag
and bx,bx ; emulating?
mov dosflg,0ffh ; set the flag, disable scan codes
mov flags.xltkbd,0 ; key translation disabled
jz vset2 ; nz=yes
mov dosflg,0 ; clear the flag, enable scan codes
mov flags.xltkbd,1 ; key translation enabled
vset2: mov dx,offset vtsmsg
mov ah,prstr
int dos
clc ; success
ret
VTS ENDP
VTSTAT PROC NEAR ; For Status display [jrd]
ret ; no emulator status to display
VTSTAT ENDP
; simple routine to insure that the port has RXON and DTR high
; assumes int are off
porton proc near
push dx
push ax
mov dx,portadr
add dx,PCOMM
in al,dx
or al,RXON
or al,DTR
or al,RTS
out dx,al
pop ax
pop dx
ret
porton endp
; routine to retrieve current int vector
; inputs: al = int number
; outputs: cx = seg for current isr
; dx = offset for current isr
getivec proc near
push es ; save registers
push bx
mov ah,35H ; Int 21H, function 35H = Get Vector.
int dos ; get vector in es:bx
mov cx,es ; addr of org vector (seg)
mov dx,bx ; and offset
pop bx
pop es
ret
getivec endp
; routine to set int vector
; inputs: al = int number
; cx = seg for isr
; dx = offset for isr
setivec proc near
push ds ; save ds around next DOS call.
mov ds,cx
mov ah,25H ; set interrupt address from ds:dx
int dos
pop ds
ret
setivec endp
; initialization for using serial port. This routine performs
; any initialization necessary for using the serial port, including
; setting up interrupt routines, setting buffer pointers, etc.
; Doing this twice in a row should be harmless (this version checks
; a flag and returns if initialization has already been done).
; SERRST below should restore any interrupt vectors that this changes.
SERINI PROC NEAR
cmp portin,0 ; did we initialize port already?
je serin1 ; e = yes
jl serin0 ; l = no, not yet
jmp serin2
serin0: mov bl,flags.comflg ; pass current port ident
call comstrt ; do SET PORT now
jnc serin1 ; nc = success
ret ; failed, exit now
serin1: cmp flags.comflg,2 ; COM1 or COM2?
jle serini1 ; Go do COM1/COM2 stuff
serin2: cmp flags.comflg,2 ; COM1 or COM2?
jg serini2 ; Go do COM3/COM4 stuff
jmp serini3 ; Update flow and leave
initmod: ; The S-100 modem set up routine
serini2:call pickspd ; Select baud and speed info
xor al,al ; Use this to reset modem
mov dx,mdstat0 ; Status port
out dx,al ; Send to port
jmp $+2 ; Wait a little
out dx,al
jmp $+2 ; Wait a little
out dx,al
jmp $+2 ; Wait a little
mov al,40h
out dx,al
jmp $+2 ; Wait a little
mov al,[bx]
out dx,al
jmp $+2 ; Wait a little
mov al,[bx+1]
out dx,al
jmp $+2
in al,dx ; Check port
and al,moddcdb ; for carrier
jnz serini0 ; Yes, don't do AT stuff
mov bx,10 ; Wait 10/100 seconds
call wait01 ; Call wait routine
push si
mov si,offset set_str;ATE1X1S0=0 sets up modem: echo commands, use
cld ; extended response codes, don't answer
lodsb ; Get the first byte of string
serini5:push ax ; We need the loaded byte later
serini6:xor cx,cx ; Reset loop counter. Loop to avoid hanging
mov dx,mdstat0 ; The status port
serini7:in al,dx ; Get status
and al,modsndb ; Mask for ready
jnz serini8 ; Yes, go on
inc cx ; No
or cx,cx ; Run out?
jnz serini7 ; No, try again
mov ah,prstr ; Yes, tell user failure in initialization
mov dx,offset infmsg; Tell user init failed
int dos
pop ax ; Restore stack
pop si
stc ; Failure
ret
serini8:pop ax ; Get byte back
mov dx,mddat0 ; The data port
out dx,al ; Send it out
lodsb ; Load next byte
cmp al,'$' ; Finished?
jnz serini5 ; No, process next
pop si ; Left in good order
mov bx,25 ; Wait 25/100 seconds
call wait01 ; Call wait routine
call prtchr ; Purge modem
jmp serini3 ; Success
serini1:mov ax,portval
cmp ax,offset port2
je seri2 ; setup for J1
cmp intin,2
jne seri0
serini0:clc ; Success
ret ; J2 (com3, com4) already set up
seri0: cmp intin,1
jne seri1 ; J1 currently installed
call serrst ; de-install current int
seri1: mov al,J2INT
call getivec
mov oldseg,cx
mov oldoff,dx
mov cx,cs
mov dx,offset serisr
mov al,J2INT
call setivec
mov portadr,J2_ADDR
call clrbuf
call porton
mov intin,2 ; show J2 installed
jmp serini3 ; Success
seri2: cmp intin,1
jne seri3
clc ; Success
ret ; J1 already set up
seri3: cmp intin,2
jne seri4 ; J2 currently installed
call serrst ; de-install current int
seri4: mov al,J1INT
call getivec
mov oldseg,cx
mov oldoff,dx
mov cx,cs
mov dx,offset serisr
mov al,J1INT
call setivec
mov portadr,J1_ADDR
call clrbuf
call porton
mov intin,1 ; show J1 installed
serini3:push bx
mov bx,portval ; get port data structure
mov [bx].portrdy,1 ; say the comms port is ready
mov parmsk,0ffh ; parity mask, assume parity is None
cmp [bx].parflg,parnon ; is it None?
je serini3a ; e = yes
mov parmsk,07fh ; no, pass lower 7 bits as data
serini3a:xor ax,ax
cmp [bx].floflg,0 ; flow control is off?
je serini3b ; e = yes
mov ax,[bx].flowc ; get flow control chars
serini3b:mov flowoff,al ; xoff or null
mov flowon,ah ; xon or null
mov xofrcv,off ; clear xoff received flag
pop bx
mov portin,1 ; say initialized
clc ; carry clear for success
ret ; We're done
pickspd:mov bp,portval ; Get speed for S-100 modem 'from' portval
cmp ds:[bp].baud,0 ; 150 baud?
mov bx,offset bd150
jz serini4
cmp ds:[bp].baud,1 ; 300 baud?
mov bx,offset bd300
jz serini4
cmp ds:[bp].baud,2 ; 600 baud?
mov bx,offset bd600
jz serini4
mov bx,offset bd1200; Default to 1200 baud
serini4:ret
SERINI ENDP
; Reset the serial port. This is the opposite of serini. Calling
; this twice without intervening calls to serini should be harmless.
SERRST PROC NEAR
cmp portin,0 ; Reset already?
jg serr0 ; g = no
clc
ret ; e = yes, l=not used yet, just leave
serr0: push dx
cmp intin,0 ; is any isr installed
je serr2 ; no, all done
push cx
push ax
mov ax,J2INT ; guess it's J2
cmp intin,2 ; yes,
je serr1 ; reset it
mov ax,J1INT ; no, must be J1
serr1: mov cx,oldseg ; original isr
mov dx,oldoff ; address
call setivec ; do it
mov intin,0 ; show nothing installed
call porton ; Insure that DTR and RTS are high
pop ax
pop cx
serr2: pop dx
mov portin,0 ; reset flag
push bx
mov bx,portval ; port data structure
mov [bx].portrdy,0 ; say port is not ready
pop bx
clc
ret
SERRST ENDP
; the serial port interrupt service routine
; this routine does int driven input and output
; once installed, it displaces the Z-100 serial isr
serisr: push ax ; Save regs
push bx
push cx
push dx
push ds ; Save data seg
mov ax,seg data ; Set our
mov ds,ax ; data seg
;
mov dx,portadr ; Get the port address
mov cx,dx ; and save a copy
add dx,PSTATUS
in al,dx ; Get port status
mov ah,al ; Save it
test ah,RDA ; Check for data available
jz isr5 ; No, nothing to receive, go send
;
mov dx,cx ; Port address
in al,dx ; Get the data
cmp flowoff,0 ; Are wo doing flow control?
jz isr2 ; No, skip
;
mov ch,al ; Make working copy of data
and ch,parmsk ; Strip parity, if any
cmp ch,flowon ; xon?
jne isr1 ; No, check xoff
mov xofrcv,false ; Indicate xoff not received (xon)
; Done with receiver
jmp short isr5 ; there should be time for send
isr1: cmp ch,flowoff ; xoff?
mov ch,0 ; We need this later in cx
jnz isr2 ; No, put regular char in buffer
cmp xofsnt,true ; Did we send an outstanding xoff?
jz isr5 ; Yes, ignore (possible echo), go send
mov xofrcv,true ; Set flag to indicatae xoff received
; Done with receiver
jmp short isr5 ; there should still be time for send
isr2: mov bx,bufiend ; Get where to put it
cmp count,BUFILEN ; Buffer full?
jne isr3 ; No, jump
dec bx ; Don't overwrite que
mov byte ptr buffin[bx],bell; Put Ctrl-G in the que as marker
jmp short isr5 ; We missed it anyway
isr3: mov byte ptr buffin[bx],al ; Stick it in the que
inc bx ; Bump que pointer
inc count ; One more in que
cmp bx,BUFILEN ; Pointing to end of que?
jne isr4 ; No, go on
xor bx,bx ; Reset pointer
isr4: mov bufiend,bx ; Store new pointer
; jmp short isr12 ; Pick ; We won't take time to send now
jmp short isr5 ; one ; There should still be time for send
;
isr5: test ah,TSRE+THBE ; Ready to send?
jz isr12 ; No, almost done
mov bx,bufobeg ; Pointer to beginning of output buffer
cmp count,mntrgh ; Past the high trigger point?
jnae isr6 ; no, make it simple
cmp flowoff,0 ; Are we doing flow control?
jz isr6 ; no, make it simple
cmp xofsnt,true ; Did we send an xoff already?
jz isr6 ; yes, make it simple
mov al,flowoff ; xoff
or al,al ; Null?
jz isr6 ; Don't send null
call dopar
mov dx,cx ; Port address
out dx,al ; Send the xoff out
mov xofsnt,true ; Remember
cmp bx,bufoend ; Buffer empty?
jz isr11 ; Yes, turn transmitter off
jmp short isr12 ; We have used transmitter already,
; so we need to go
isr6: cmp bx,bufoend ; Buffer empty?
jz isr11 ; Yes, turn transmitter off
mov al,byte ptr buffout[bx] ; Get char to send
cmp flowoff,0 ; Are we doing flow control?
jz isr7 ; No, just go on
mov ah,al ; Working copy
and ah,parmsk ; Strip parity
cmp ah,flowoff ; xoff?
jz isr7 ; Just send it
cmp ah,flowon ; xon?
jz isr7 ; Just send it
cmp xofrcv,true ; Being held?
jz isr12 ; Yes, don't send
isr7: mov dx,cx ; Port address
out dx,al ; Send it
inc bx ; Point to next char to send
cmp bx,BUFOLEN ; Pointing to end of que?
jne isr10
xor bx,bx ; Reset pointer
isr10: mov bufobeg,bx ; Save it
jmp short isr12 ; Almost done
;
isr11: mov dx,cx ; Port address
add dx,PCOMM
in al,dx ; Get current mode
and al,TXOFF ; Turn xmitter off
out dx,al ; Do it.
;
isr12: mov al,EOI ; Tell interrupt controller
out Z8259,al ; that interrupt serviced
;
pop ds ; Restore regs
pop dx
pop cx
pop bx
pop ax
iret
;; Wait for the # of milliseconds in ax, for non-IBM compatibles.
pcwait proc near
cmp ax,0
jz pcwait2 ; no wait
push bx
push cx
push dx
xor dx,dx
mov cx,10 ; we can not make it finer than 10ms
div cx
cmp ax,0
jnz pcwait1
inc ax ; make it 10ms for 1 to 9
pcwait1:mov bx,ax ; and 10ms for 10 to 19, 20ms for 20 to 29
call wait01 ; 10ms => 10 to 20ms by wait01
pop dx ; 20ms => 20 to 30ms by wait01
pop cx
pop bx
pcwait2:ret
pcwait endp
; Wait for the # of hundredths seconds in bx. Range 1 to 0ffffh.
; Accuracy within 10ms due to use of system clock.
; This uses dos calls and is compatible with all msdos systems.
; Preserves all registers.
wait01 proc near
push ax
push cx
push dx
push di
mov ah,gettim ; Get time function
int dos
wait011:mov di,dx ; Preset/reset di
wait012:int dos
cmp dx,di ; Changed?
je wait012 ; Yes, continue
dec bx ; 1/100 second passed
jnz wait011 ; Did not time out, keep waiting
pop di ; Timed out
pop dx
pop cx
pop ax
ret
wait01 endp
; Service SET NETBIOS-NAME name command at Kermit prompt level
setnbios proc near
ret
setnbios endp
sesdisp proc near
ret
sesdisp endp
code ends
end