home *** CD-ROM | disk | FTP | other *** search
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;
- ;; FOSSIL/Modem Testing Utility
- ;; Copyright (c) June, 1992
- ;; Unique Computing Pty Limited & David Nugent
- ;; FidoNet Node 3:632/348.0
- ;; Alternet Node 7:833/387.0
- ;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ;
- ; This utility is useful for testing various aspects of FOSSIL-aware software,
- ; by simulating a modem and enabling the user to set or reset certain status
- ; information returned by the FOSSIL to an application.
- ;
- ; It was created primarily to simulate a remote modem connect for testing
- ; purposes using a direct wire but allowing direct control from local keyboard.
- ;
- ; FUTIL installs as a TSR wedge between the FOSSIL and an application. It
- ; requires that a revision 5 FOSSIL driver be installed prior to it, and it
- ; will capture INT 14H (it looks like a FOSSIL to the application) and
- ; intercept certain FOSSIL calls in order to carry out its simulation.
- ;
- ; This utility is particularly useful because it is release WITH SOURCE.
- ; It can therefore be modified and re-assembled to carry out any simulation
- ; required, but this will take a little knowledge in how FOSSIL operates
- ; and some expertise in PC operations in general.
- ;
- ; Please read the accompanying documentation for license details and caveats.
- ;
-
- ; V1.00 June 1992 Original release
- ; V1.10 July 1992 Small bug fix: purging FOSSIL
- ; receive buffer now clears pending input
- ; status bit (previously this would look
- ; effectively hang a machine with some s/w).
-
- ;
- ; NOTE: MASM 5.10 or TASM 1.0 is required to assembly this program!
- ; Earlier versions of MASM will NOT work.
- ;
- ; Provides TASM->MASM compatibility
-
- ifdef ??version
- masm51
- quirks
- endif
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;
- ;; Definitions/readability section
- ;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- CDSIG equ 0F23DH ; FUTIL's signature
- MAGIC equ 01954H ; FOSSIL's magic number
- DOS equ 021H ; DOS interrupt
- TSR equ 027H ; .COM TSR call
- ; Keyboard shift key codes
- CTRL equ 004H ; Ctrl key is down
- SHIFTS equ 003H ; Any shift pressed
- LSHIFT equ 002H ; Left shift
- RSHIFT equ 001H ; Right shift
- ALT equ 008h ; Alt key pressed
- NUMLOCK equ 020H ; Numlock state
- ; BIOS ports, data area definitions
- SH_STATE equ 0417H ; Shift state byte
- KBD_PORT equ 060H ; Keyboard data port
- KBD_CTRL equ 061h ; Keyboard control port
- LSC equ (LSHIFT or CTRL) ; Shorthand for Ctrl-LShift
- KUSED equ 0FH ; Bits used in shift mask
- ; FOSSIL status bits
- PS_CARRIER equ 0080H ; Carrier signal from MSREG
- PS_RXCHARS equ 0100H ; Characters in input buffer
-
-
- ;;;;;;;;;;;;;;;;
- ;;
- ;; Start program
- ;;
- ;;;;;;;;;;;;;;;;
-
- _code segment para public 'code'
- assume CS:_code
- org 100h ; .COM start
-
- ; Jump to install (which is unloaded on TSR
-
- start:
- jmp install
-
- ;
- ; Int 14H entry point
- ;
- even
- Int_14:
- jmp SHORT parse
-
- ;
- ; FOSSIL data section
- ;
-
- oldvec dd 0 ; Old INT 14H vector
- dw MAGIC ; Make it look like a FOSSIL
- dw 001bH ; Revision 5 type
- dw CDSIG
- kbdvec dd 0 ; Old INT 09H vector
- ;
- port dw 0 ; Port number
- ;
- ; Status information
- ;
- ; WARNING: DO NOT CHANGE THE ORDER AND CONTENTS OF THIS SECTION
- ; WITHOUT CONSIDERING THE 'HOTKEYS' SECTION BELOW. THESE
- ; VARIABLES CORRESPOND DIRECTLY TO THE HOKEY STRUCTURE!!
- ;
- even
- cstate dw 0 ; Carrier detect mask (default no extra)
- cdmask dw -1 ; Status mask out bits (default leave alone)
- tdata dw 0 ; Ignore transmit data flag
- rdata dw 0 ; Receive data flag
- isdata dw 0 ; Is data to send flag
- strp dw 0 ; Pointer to current string
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;
- ;; INT 14H handler
- ;; Only a subset of commands are intecepted
- ;; Tests code in AH, otherwise passes control
- ;; to the installed FOSSIL driver
- ;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- parse PROC NEAR
-
- sti
- cld
- cmp DL,BYTE PTR CS:[port] ; Select only for current port
- je @F
- jmp DWORD PTR CS:[oldvec]
- @@:
- cmp AH,01H ; Transmit data
- je @istxch
- cmp AH,02H ; Receive data
- je @isrxch
- cmp AH,03H ; Port status
- jne @F
- jmp @isstat
- @@:
- cmp AH,0AH ; Receive buffer purge
- je @isrp
- cmp AH,0BH ; Transmit no wait
- je @istxnw
- cmp AH,0CH ; Read, no wait
- je @ispeek
- cmp AH,18H ; Receive block
- jne @F
- jmp @isrxb
- @@:
- cmp AH,19H ; Transmit block
- jne @norm
- jmp @istxb
-
-
- ; ---------------------
- ; Read, non-destructive
- ; ---------------------
-
- @ispeek:
- cmp CS:[isdata],0 ; Is there data to be returned?
- je @norm
- push BX
- mov BX,CS:[strp]
- mov AL,CS:[BX] ; Get next character
- pop BX
- xor AH,AH
- jmp @bye
-
- ; ---------------------
- ; Transmit no wait call
- ; ---------------------
-
- @istxnw:
- cmp CS:[tdata],0 ; Eat character
- je @norm
- mov AX,1 ; 1 = successfully sent
- jmp @bye
-
- ; -----------------------------------------
- ; Purge receive buffers (and pending input)
- ; -----------------------------------------
-
- @isrp:
- mov CS:[isdata],0
- mov CS:[strp],0
- and CS:[cstate],not PS_RXCHARS ; Reset "chrs in rx buf" status bit
- jmp SHORT @norm
-
- ; ------------------
- ; Transmit character
- ; ------------------
-
- @istxch:
- cmp CS:[tdata],0 ; Eat character
- jne @F
- jmp @isstat
- @@:
- mov AL,03H ; Force a status call
- jmp @isstat
-
- @norm:
- jmp DWORD PTR CS:[oldvec] ; Jump straight to old vector
-
- ; -----------------
- ; Receive character
- ; -----------------
-
- @isrxch:
- cmp CS:[isdata],0 ; Is there data to be returned?
- je @rch
- @isrxch1:
- push BX
- mov BX,CS:[strp]
- mov AX,CS:[BX] ; Get next character
- pop BX
- inc CS:[strp] ; Move pointer to next character
- or AH,AH ; Test for end of string
- jne @F
- and CS:[cstate],not PS_RXCHARS ; Reset "chrs in rx buf" status bit
- mov CS:[isdata],0
- @@:
- xor AH,AH
- jmp SHORT @bye
-
- @rch:
- cmp CS:[rdata],0 ; Give control to FOSSIL?
- je @norm
- sti
- push AX
- mov AH,3 ; Else get status
- int 14H
- test AX,PS_RXCHARS ; Are there characters in buffer?
- pop AX
- je @isrxch
- cmp CS:[isdata],0 ; Is there data to be returned?
- jne @isrxch1
- jmp SHORT @norm
-
- ; -------------------
- ; Transmit block data
- ; -------------------
-
- @istxb:
- cmp CS:[tdata],0 ; Eat character
- je @norm
- mov AX,CX ; Return number of characters 'sent'
- jmp SHORT @bye
-
- ; ------------------
- ; Receive block data
- ; ------------------
-
- @isrxb:
- cmp CS:[isdata],0 ; Is there data to be returned?
- je @norm
- push DI ; Hmm, better get to work ...
- push CX
- push BX
-
- cld ; Required for string opcodes
- mov BX,CS:[strp] ; Get pointer to string
- jcxz @up ; Opps, zero chrs requested
- @@:
- mov AX,CS:[BX] ; Get next character
- inc BX
- stosb ; Store it in user buffer
- or AH,AH ; Test for end of string
- je @F
- loop @B ; Until user buffer full
- jmp SHORT @up
- @@: ; No more available at this point
- and CS:[cstate],not PS_RXCHARS ; Reset "rx chrs avail" status bit
- mov CS:[isdata],0
- xor BX,BX
- @up:
- mov CS:[strp],BX ; Update string pointer
- mov AX,CX ; Save remaining number of characters
-
- pop BX ; Restore all registers
- pop CX
- pop DI
- sub AX,CX ; Calculate/return # of bytes received
- neg AX
- jmp SHORT @bye
-
- ; -------------------
- ; Status call handler
- ; -------------------
-
- @isstat:
- pushf ; Simulate the old INT 14H
- call DWORD PTR CS:[oldvec]
- or AX,CS:[cstate] ; OR in set mask
- and AX,CS:[cdmask] ; AND out reset mask
- @bye:
- iret ; Return to user
-
- parse ENDP
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;
- ;; Configuration section
- ;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ;
- ; This section contains information which can be modified to suit.
- ;
-
- ;
- ; Modem control strings
- ; Various strings returned by a typical modem, available by 'hotkey'
- ;
-
- ; STATUS
- nocarrier db 'NO CARRIER',13,10,0
- ok db 'OK',13,10,0
- error db 'ERROR',13,10,0
- busy db 'BUSY',13,10,0
- ring db 'RING',13,10,0
- rring db 'RRING',13,10,0
- voice db 'VOICE',13,10,0
- ; CONNECTS
- connect db 'CONNECT',13,10,0
- connect300 db 'CONNECT 300',13,10,0
- connect1200 db 'CONNECT 1200',13,10,0
- connect2400 db 'CONNECT 2400',13,10,0
- connect24rel db 'CONNECT 2400/REL',13,10,0
- connect9600 db 'CONNECT 9600',13,10,0
- connectfast db 'CONNECT FAST',13,10,0
-
-
- ;
- ; This next section is a series of structures which allows a 'hotkey'
- ; combination to be tied to a given action. The structures contain the
- ; contents of the INT 14H variables used in the above intercept routines
- ; and pressing the hotkey combination simply copies in values for these
- ; variables setting of a reaction by the next intercepted INT 14H call.
- ;
-
- notkey STRUC
- scanc db ? ; Keyboard scan code (returned by KB ROM)
- kshft db ? ; Keyboard shift state (BIOS)
- cmask dw ? ; Status OR mask (force these bits on)
- cbits dw ? ; Status AND mask (force these bits off)
- itx dw ? ; Ignore transmited data flag (don't give to FOSSIL)
- irx dw ? ; Don't call FOSSIL to receive data flag
- srx dw ? ; Is there data to 'receive' flag
- dofs dw ? ; Offset of string to 'receive'
- notkey ENDS
-
- SZ_ka equ <size notkey> ; Size of one hotkey structure
-
- KEYS equ 20 ; Defines how many structures to scan
-
- ;
- ; Hot keys table
- ;
- even
- KeyCodes label word
- notkey <29H, LSC, 0000H, not 0000H, 00H, 00H, 00H, 0 > ; cs` Turns all processing off
- notkey <0bH, LSC, 0000H, not 0080H, 00H, 00H, 00H, 0 > ; cs0 Force no carrier
- notkey <18H, LSC, 0100H, not 0080H, 00H, 01H, 01H, ok > ; csO 'OK'
- notkey <12H, LSC, 0100H, not 0080H, 00H, 01H, 01H, error > ; csE 'ERROR'
- notkey <31H, LSC, 0100H, not 0080H, 00H, 01H, 01H, nocarrier > ; csN 'NO CARRIER'
- notkey <30H, LSC, 0100H, not 0080H, 00H, 01H, 01H, busy > ; csB 'BUSY'
- notkey <21H, LSC, 0180H, not 0000H, 00H, 01H, 01H, connectfast > ; csF 'CONNECT FAST'
- notkey <0aH, LSC, 0180H, not 0000H, 00H, 01H, 01H, connect9600 > ; cs9 'CONNECT 9600'
- notkey <04H, LSC, 0180H, not 0000H, 00H, 01H, 01H, connect24rel> ; cs3 'CONNECT 2400/REL'
- notkey <03H, LSC, 0180H, not 0000H, 00H, 01H, 01H, connect2400 > ; cs2 'CONNECT 2400'
- notkey <02H, LSC, 0180H, not 0000H, 00H, 01H, 01H, connect1200 > ; cs1 'CONNECT 1200'
- notkey <13H, LSC, 0100H, not 0080H, 00H, 01H, 01H, ring > ; csR 'RING'
- notkey <2fH, LSC, 0100H, not 0080H, 00H, 01H, 01H, voice > ; csV 'VOICE'
- notkey <17H, LSC, 0100H, not 0080H, 00H, 01H, 01H, rring > ; csI 'RRING'
- notkey <00H, 00H, 0000H, not 0000H, 00H, 00H, 00H, 0 >
- notkey <00H, 00H, 0000H, not 0000H, 00H, 00H, 00H, 0 >
- notkey <00H, 00H, 0000H, not 0000H, 00H, 00H, 00H, 0 >
- notkey <00H, 00H, 0000H, not 0000H, 00H, 00H, 00H, 0 >
- notkey <00H, 00H, 0000H, not 0000H, 00H, 00H, 00H, 0 >
- notkey <00H, 00H, 0000H, not 0000H, 00H, 00H, 00H, 0 >
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;
- ;; Keyboard (hardware) interrupt handler
- ;;
- ;; This routine is triggered on make or break (press or release)
- ;; of ANY key on the keyboard. The KB port is then inspected to
- ;; see which key was pressed, and the current shift status read.
- ;; The above hotkeys table is then scanned for a match; if found,
- ;; the rest of the structure is copied into the variable space,
- ;; otherwise the call passes to the previous INT 9H handler.
- ;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
- Int_9 PROC FAR
-
- assume DS:nothing,ES:nothing ; Could (and will) be anywhere
-
- push AX ; Must preserve EVERY register here
- push CX
- push DI
- push ES
- xor AX,AX
- mov ES,AX
-
- in AL,KBD_PORT ; Scan code of key pressed
- mov AH,ES:[SH_STATE] ; Current shift state bits
- and AH,KUSED ; Mask out unused bits
- mov DI,offset KeyCodes ; Scan key codes table
- mov CX,KEYS
- @@:
- cmp AX,CS:[DI]
- je @F
- add DI,SZ_ka
- loop @B
- ; Key was not found
- pop ES ; Restore saved registers
- pop DI
- pop CX
- pop AX
- jmp CS:[kbdvec] ; Pass though to original vector
-
- ;
- ; Key combo found; take action
- ;
-
- @@:
- in AL,KBD_CTRL ; Save value of kbd control lines
- mov AH,AL
- or AL,80H ; Set kbd enable bit
- out KBD_CTRL,AL
- mov AL,AH
- out KBD_CTRL,AL
- mov AL,20H ; Signal end of HW interrupt to 8259A
- out 20H,AL
- push BX
- xor BX,BX
- mov CX,SZ_ka/2
- jmp SHORT @F
- @Clp:
- mov AX,CS:[DI+BX] ; Copy variables to intercept data area
- mov CS:[BX+offset cstate-2],AX
- @@:
- inc BX
- inc BX
- loop @Clp
-
- pop BX ; Restore registers
- pop ES
- pop DI
- pop CX
- pop AX
- iret
-
- Int_9 ENDP
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;
- ;; End resident section
- ;;
- ;; The rest of this code is discarded on installation as a TSR, and
- ;; does not consume additional memory
- ;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ; Installation messages
-
- msg_nofos db 7,'No FOSSIL driver installed',13,10,'$'
- msg_instald db 7,'FUTIL is already installed',13,10,'$'
- msg_instnot db 7,'FUTIL is not installed',13,10,'$'
- msg_instok db 'FUTIL is now active',13,10,'$'
- msg_inval db 7,'Invalid command line option',13,10,'$'
- msg_unloaded db 'FUTIL successfully unloaded',13,10,'$'
- msg_start db 'FUTIL v1.10 FOSSIL Communications Companion Utility',13,10
- db 'Copyright (C) 1992 David Nugent & Unique Computing Pty Ltd',13,10
- db '$'
-
- ; ----------------------
- ; Installation procedure
- ; ----------------------
-
- install PROC NEAR
- assume ds:_code ; DS = CS by default
- mov DX,offset msg_start ; Output our logo
- mov AH,9
- int DOS
- cld ; Required for string opcodes
- mov SI,81H ; Start of command line
- @Top:
- lodsb
- cmp AL,13 ; Test for end of cmdline
- je @Load
- cmp AL,0
- je @Load
- cmp AL,32 ; Skip spaces,
- je @Top
- cmp AL,9 ; and tabs
- je @Top
- cmp AL,'/' ; Looking for a valid switch
- je @F ; character (- or / will do)
- cmp AL,'-'
- je @F
- @nogood:
- mov AL,3 ; Something else is invalid
- mov DX,offset msg_inval
- jmp ExitMsg
- ;
- ; Read switch value
- ;
- @@:
- lodsb
- cmp AL,'a' ; Convert to uppercase
- jb @F
- cmp AL,'z'
- ja @F
- sub AL,'a'-'A'
- @@:
- cmp AL,'U' ; /U = Uninstall
- je @Unload
- cmp AL,'P' ; /P = Port number
- jne @nogood
- lodsb
- cmp AL,'0' ; Convert # to binary
- jb @nogood
- cmp AL,'9'
- ja @nogood
- sub AL,'0'
- xor AH,AH
- mov port,AX ; Save in our local variable
- jmp SHORT @Top
-
- ;
- ; Unload from memory
- ;
-
- @Unload:
- call ChkLoad ; See if FUTIL is loaded
- cmp ES:[BX+10],CDSIG ; Is this program installed?
- mov DX,offset msg_instnot
- mov AL,2
- jne ExitMsg
- push DS ; Preserve DS for later
- push ES
- push ES
- pop DS
- mov DX,word ptr [kbdvec]
- mov DS,word ptr [kbdvec+2]
- mov AX,2509H ; Release keyboard
- int DOS
- pop DS
- mov DX,word ptr [oldvec]
- mov DS,word ptr [oldvec+2]
- mov AX,2514H ; Release INT 14H
- int DOS
- pop DS
- mov AH,49H ; Deallocate memory (at ES)
- int DOS
- mov DX,offset msg_unloaded
- xor AL,AL
- jmp SHORT ExitMsg
-
- ;
- ; Load into memory
- ;
-
- @Load:
- call ChkLoad ; Check to see if we're loaded
- cmp ES:[BX+10],CDSIG ; Is this program installed?
- mov DX,offset msg_instald
- mov AL,2
- je ExitMsg
- mov DX,offset Int_14 ; Install vector for INT 14H
- mov AX,2514H
- int DOS
- mov AX,3509H ; Get keyboard vector
- int DOS
- mov word ptr [kbdvec],BX
- mov word ptr [kbdvec+2],ES
- mov DX,offset Int_9
- mov AX,2509H ; Intercept keyboard
- int DOS
- mov AX,CS
- mov ES,AX
- mov ES,ES:[02cH] ; Free our environment
- mov AH,049H
- int DOS
- mov DX,offset msg_instok
- mov AH,09H ; Print message
- int DOS
- mov DX,offset msg_nofos ; Stay resident
- int TSR
-
- install ENDP
-
- ;
- ; Exit (abort) with a message
- ;
-
- ExitMsg PROC NEAR
-
- push AX ; Save exit code
- mov AH,09H ; Print message
- int DOS
- pop AX
- mov AH,4cH ; And exit
- int DOS
-
- ExitMsg ENDP
-
- ;
- ; Check to see if already loaded
- ;
-
- ChkLoad PROC NEAR
- mov AX,3514H ; Get int 14H vector
- int DOS
- mov word ptr [oldvec],BX ; And save it
- mov word ptr [oldvec+2],ES
- cmp ES:[BX+6],MAGIC ; Is a FOSSIL there?
- mov DX,offset msg_nofos
- mov AL,1
- je @F
- pop BX
- mov BX,offset ExitMsg
- push BX
- @@:
- ret
- ChkLoad ENDP
-
- _code ends
-
- end start
-