home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
decpro300.tar.gz
/
decpro300.tar
/
proxk.mac
< prev
Wrap
Text File
|
1988-08-16
|
18KB
|
690 lines
.TITLE KERXK - XK driver routines
.SBTTL R McQueen/N Bush/D Stevens/S Hecht
; Version number
.IDENT /1.0.04/
; Directives
.LIBRARY /KERMLB/ ; PRO/Kermit macro library
.SBTTL Revision History
;++
; 1.0.00 By: Robert C. McQueen On: 1-December-1983
; Create this module from other modules
;
; 1.0.01 By: Robert C. McQueen On: 16-Feb-1984
; Use the correct timeout value.
;
; 1.0.02 By: Robert C. McQueen On: 17-Feb-1984
; Add an alternate entry point to the initialization.
; One to allow setting the routine and buffer size and
; the other to default to assembly limit and no routine.
;
; 1.0.03 By: Robert C. McQueen On: 9-March-1984
; Make $PLIT$ come out even and not odd.
;
; 1.0.04 By: Robert C. McQueen On: 26-March-1984
; Finish edit 1.0.01
;--
.SBTTL .MCALLs for RSX directives
; The following are the various MCALLs that KERXK uses.
.MCALL ASTX$S ; AST exiting command
.MCALL QIOW$S ; QIO and wait
.MCALL QIOW$C ; QIO and wait
.MCALL QIO$S ; QIO and no wait
.MCALL MRKT$S ; Set a mark time request
.MCALL CMKT$S ; Cancel mark time requests
.MCALL SETF$S ; Set event flags
.MCALL WTSE$S ; Wait for an event
.MCALL WTLO$S ; Wait for logical-or of event flags
; The following causes the KERMIT definitions to be read and defined
.MCALL KERDEF ; Get the KERMIT definitions
KERDEF ; Define all of the KERMIT symbols
.MCALL IOSBDF ; IOSB definitions
IOSBDF ; Define the symbols
.MCALL BLSRTN ; Macro to define entry point
.MCALL PJMP ; Jump and return macro
.MCALL ND ; If not defined macro
.MCALL BIT. ; Bit mask definition macro
; The following are local parameters for KERXK
ND NM.XCH, 64. ; Allow 64 characters in buffer
ND XKBUFLEN, 512. ; Length of XK buffer (must be power of two)
.GLOBL XKBUFLEN
.SBTTL Data for the module
.PSECT $OWN$, RW, D ; Make sure this goes in data space
XKSTAT: .BLKB 4 ; IO status block
XKBUFF::.BLKB XKBUFLEN ; Circular xk-queue.
.EVEN
XKFREE::.BLKW 1 ; Counter of free buffer space.
XKUSED::.BLKW 1 ; Counter of used buffer space.
XKNXTC::.BLKW 1 ; Pointer to first valid character.
XKFREC::.BLKW 1 ; Pointer to first free character.
QUEFLG: .BLKW 1 ; Flag to indicate I/O queue pending.
ERRFLG: .BLKB 1 ; Flag to store an error in.
.EVEN
DMPRTN: .BLKW 1 ; Routine to dump XK input
;
; XK output data
;
XKOBUF: .BLKB NM.XCH ; Number of XK characters allowed
XKONCH::.BLKW 1 ; Number of characters in XKOBUF
XKOIDX: .BLKW 1 ; Index to store characters into
XOIOSB: .BLKB IB.MSZ ; IOSB for QIO
.SBTTL XK.INI - Initialize the XK driver
;++
; This routine will initialize the XK port. It will read the initial
; parameters from the XK port and store them into an internal block. It
; will then set the XK port with the parameters from the [ZZSYS]KERMITXK.SYS
; file.
;
; Usage:
;
; Macro:
; R0/ Number of characters to buffer from XK port
; (Needed for slow speeds during terminal emulation)
; R1/ Adress of routine to call from XK.AST
; JSR PC,XK.INI
; (Return - R0 contains the error status if carry set, else good return)
;
; Bliss:
; Status = XK_INI();
;
;--
.PSECT $CODE$, RO, I
XK.INT::
CLR DMPRTN ; No dump routine
MOV #XKBUFLN-1,XKFREE ; Initialize the number free
BR XKINIT ; Join the common code
XK.INI::
MOV R1,DMPRTN ; Store the dump routine
;
; Determine the number of characters that we should be buffering
;
CMP #XKBUFLN-1,R0 ; Small enough?
BGT 4$ ; No, use the default
TST R0 ; Have to use the default?
BNE 5$ ; No, use the given
4$: MOV #XKBUFLN-1,R0 ; Yes, use the default
5$: MOV R0,XKFREE ; Store the amount we can buffer
XKINIT:
;
; First we will attach to the XK so that no one else can be screwing around
;with it behind our backs.
;
7$: QIO$S #IO.ATT,#XKLUN,#XKREFN,,#XKSTAT ; Grab the device
MOVB XKSTAT,R0 ; Get the status
BLE 90$ ; Branch if so
; Now read the current parameters. These will be saved and restored when
;we exit.
MOV #ORGXKP,R0 ; Point at parameter list
MOV #CURXKL,R1 ; And get the length
JSR PC,XK.RD ; Read the parameters
; Here to set the desired parameters.
30$: MOV #CURXKP,R0 ; Point at the parameter block
MOV #CURXKL,R1 ; And the length
JSR PC,XK.WT ; Read the info
CLR XKFREC ; Init. XKFREC index to zero.
CLR XKUSED ; Set the amount of used space to 0.
CLR XKNXTC ; Init. XKNXTC index to zero.
MOV #NM.XCH,XKONCH ; Store the max number we can output
;[02] MOV #XKBUFLEN-1,XKFREE ; Set the amount of free space to max
MOV #-1,QUEFLG ; No QIO pending yet
CLRB ERRFLG ; And no errors
; All done
CLC ; Clear carry
RTS PC ; Return to our caller
;
; Here if we failed to get the XK
;
90$: QIOW$C IO.KIL,XKLUN,XKREFN,,,,,$CODE$ ; Grab the device
SEC ; Set the carry bit
RTS PC ; Return to the caller
.SBTTL XK.SHT - Shutdown the XK port
;++
; This routine will shut down the XK port. It will restore the parameters
; from the orginal XK parameters. It will then return to the caller.
;
; Usage:
;
; Macro:
; JSR PC,XK.SHT
; (Return)
;
; Bliss:
;
; Status = XK_SHT ();
;--
; .PSECT $CODE$, RO, I
XK.SHT::MOV #ORGXKP,R0 ; Point at orignal parameters
MOV #CURXKL,R1 ; And the length of the block
JSR PC,XK.WT ; Set them
QIOW$C IO.KIL,XKLUN,XKWEFN,,,,,$CODE$ ; Kill pending I/O queues.
QIOW$C IO.DET,XKLUN,XKWEFN,,,,,$CODE$ ; Detach the device
RTS PC ; And return
.SBTTL XK.RD - Read XK parameters into parameter block
;++
; This routine will read XK parameters into the given parameter block.
; It will use the QIO to read the XK parameters and then move them into
; the internal KERMIT parameter block.
;
; Usage:
;
; Macro:
; MOV #Parameter.block,R0
; MOV #Parameter.block.length,R1 ; (in bytes)
; JSR PC,XK.RD
; (Return - R0 contains the status)
;
; Note that the length must be an even number of bytes
;--
.PSECT $CODE$, RO, I
; We assume that when we are called, the parameter block is in a totally
;random state. We will set to read as many of the interesting parameters
;as we can fit into the block supplied. This block should normally be
;long enough, but might not be if there is a version skew between two modules.
XK.RD:: JSR R1,$SAVE4 ; Save some registers
; If the block is large than our maximum, only use what we know about
CMP #PTPLEN*2,R1 ; Have enough items to fill the block?
BGE 5$ ; Yes, just enter loop
MOV #PTPLEN*2,R1 ; No, can only move what we have
5$: MOV R0,R2 ; Get a copy of the address
MOV R1,R3 ; And the length
; Now insert the parameter types into the block
MOV #PARTYP,R4 ; Point at list of interesting parameters
ASR R1 ; Make the length be words
10$: MOVB (R4)+,(R0)+ ; Store the parameter type
CLRB (R0)+ ; Clear its data byte
SOB R1,10$ ; Loop for all that we have room for
; Now just do the QIO to read the parameters
QIOW$S #SF.GMC,#XKLUN,#XKREFN,,,,<R2,R3> ; Get the information
MOV @#$DSW,R0 ; Get the result code
RTS PC ; And return
; List of parameters we should read. Most important parameters first.
.PSECT $PLIT$, RO, D ; Make sure this goes in data space
PARTYP: .BYTE TC.RSP ; Receive speed
.BYTE TC.XSP ; Transmit speed
.BYTE TC.FSZ ; Frame size
.BYTE TC.PAR ; Parity enable/disable
.BYTE TC.EPA ; Odd or even parity (if enabled)
.BYTE TC.STB ; Number of stop bits
.BYTE TC.8BC ; pass 8 data bits per character
.BYTE TC.BIN ; XON/XOFF enable/disable
.BYTE XT.MTP ; Modem type
.BYTE TC.ARC ; Auto-answer ring count
.BYTE TC.XMM ; Enable/disable maintenance
PTPLEN= .-PARTYP ; Number of parameters we handle
.EVEN ; Make this go to the next word
.SBTTL XK.WT - Write XK parameters from a parameter block
;++
; This routine will write the XK parameters from a given parameter block.
; This routine will move the internal parameters into the QIO block for the
; SMC QIO call.
;
; Usage:
;
; Macro:
; MOV #Parameter.block,R0
; MOV #Parameter.block.length,R1 ; (in bytes)
; JSR PC,XK.WT
;
;--
.PSECT $CODE$, RO, I
XK.WT:: CMP #PTPLEN*2,R1 ; Block larger than we know about?
BGE 10$ ; No, leave it alone
MOV #PTPLEN*2,R1 ; Yes, only use the portion which should be ok
10$: QIOW$S #SF.SMC,#XKLUN,#XKWEFN,,,,<R0,R1> ; Set the new parameters
RTS PC ; And return
.SBTTL XK.BRK - Send a break character to the XK port
;++
; This routine will set a break character to the XK port. It is used
; by the terminal emulation processing to handle the BREAK key.
;
; Usage:
; JSR PC,XK.BRK
; (Return)
;
;--
XK.BRK::
;
; First kill any pending I/O
;
QIOW$C IO.KIL,XKLUN,XKREFN,,,,,$CODE$ ; Kill the I/O
MOV #-1,QUEFLG ; No QIO pending
;
; Now send the break character
;
QIOW$C IO.BRK,XKLUN,XKAEFN,,,,0,$CODE$
RTS PC ; Return to the caller
.SBTTL XK.INP - Input a character from the XK port
;++
; This routine will input a single character from the XK port. It is used
; by RECEIVE to fill a packet buffer, and by SEND to clear the XK input
; buffer.
;
; Usage:
;
; Macro:
; MOV #Buffer.address,R1
; MOV #Time.to.wait,R2 ; Time in seconds, 0 = don't wait
; JSR PC,XK.INP
;
; On a good return (carry = 0):
;
; R0/ Number of characters read (0 or 1)
; R1 and R2 unchanged
;
; On a false return (carry = 1):
;
; R0/ IE.xxx error code
;
;--
.PSECT $CODE$, RO, I
XK.INP::JSR R1,$SAVE3 ; Save R1 to R3
;
; Before we do anything we check for an error in ERRFLG.
;
TSTB ERRFLG ; Any errors?
BNE 40$ ; Yes, handle them
;
; No error. Do we have any characters in the buffer ?
;
TST XKUSED ; Is the buffer empty ?
BEQ 20$ ; Yes, branch.
;
; Here if we have characters
;
10$: MOV XKNXTC,R3 ; Put index into R3
ADD #XKBUFF,R3 ; . . .
MOVB (R3),@R1 ; Return the char. pointed at.
INC XKNXTC ; Increment index to the next char.
BIC #^C<XKBUFLEN-1>,XKNXTC ; Clear the high order bits
INC XKFREE ; Increment the free space count.
DEC XKUSED ; Decrement the used space count.
JSR PC,XK.QIO ; Set up xk-que if necessary.
MOV #1,R0 ; Set up return in R0.
BR 30$ ; Branch.
;
; Que an I/O read if necessary then see if we need to time out.
;
20$: JSR PC,XK.QIO ; Set up xk-que if necessary.
TST R2 ; Do we have no time-out ?
BEQ 25$ ; Yes, branch.
;
; We need to time out, wait for GENEFN, or XKREFN flags to be set.
;
BIT. GENMSK,GENEFN ; Define mask bit for GENEFN
BIT. CONMSK,CONEFN ; Define mask bit for XKREFN
WTLO$S 0,#GENMSK!CONMSK ; Wait for one of the 2 EFNs to be set.
;
; We either timed out or we got some characters.
;
25$: TST XKUSED ; Is the buffer empty ?
BNE 10$ ; No, branch.
CLR R0 ; Set up "no char" return in R0.
;
; Exit routine provided we did not branch at first tst.
;
30$: CLC ; Clear carry.( no error )
RTS PC ; Return to caller.
;
; Exit routine for an error being detected.
;
40$: MOVB ERRFLG,R0 ; Move error code in R0.
SEC ; Set carry.( error )
RTS PC ; Return to caller.
.SBTTL XK.CIB - Clear input buffer
;++
; This routine will clear the XK's input buffer. This is used to dump any
;accumulated garbage before we send any data.
;
; Usage:
; JSR XK.CIB ; Clear the input buffer
; (return here always)
;
;--
.PSECT $CODE$, RO, I
XK.CIB::
INC QUEFLG ; Is the queue flag clear ?
BNE CIB.0 ; No, branch
QIOW$C SF.SMC,XKLUN,XKREFN,,,,<CIBBLK,CIBLEN>,$CODE$
; Just do the function
MOV #-1,QUEFLG ; Flag no QIO pending
CIB.0: CLR XKUSED ; Reset used space count to zero.
CLR XKFREC ; Reset index to zero.
CLR XKNXTC ; Reset index to zero.
MOV #XKBUFLEN-1,XKFREE ; Reset free space count to the
RTS PC ; And return
.PSECT $PLIT$, RO, D
CIBBLK: .BYTE TC.TBF,0 ; Clear buffer function
CIBLEN= .-CIBBLK ; Define the length
.SBTTL XK.TIM - Set up timeout
;++
; This routine will post the request for a timeout. It will ask that GENEFN
; be set when the timeout period has expired. If there is no timeout, it
; will not request the EFN.
;
; Usage:
; JSR PC,XK.TIM
; (return here always)
;
; On return:
; R0/ low order 0, high order number of seconds to wait on QIO's
; R1-R5 preserved
;
;--
.PSECT $CODE$, RO, I
XK.TIM::MOVB SEND.TIMEOUT,R0 ; Get the receive timeout
BNE 10$ ; Branch if time out
MOV #377,R0 ; Otherwise use maximum wait for QIO
10$: SWAB R0 ; So that we have seconds in high order
BIC #377,R0 ; Make sure 10 sec. portion is clear
TST SEND.TIMEOUT ; Check if any timeout at all
BEQ 99$ ; No, just go ahead and wait forever
CMKT$S #GENEFN ; Make sure any old timeout is cleared
MRKT$S #GENEFN,SEND.TIMEOUT,#2. ; Macro to wait (send.timeout) seconds.
; This uses the general EFN.
99$: RTS PC ; Return, R0 already set up
.SBTTL XK.QIO - Check for Qio read and issue one if none
;++
; This routine queues up a single character read from the comm-port.
; The characters read are stored in xkbuff starting at the offset
; in XKFREC. After the queue the flag is set to indicate that
; we have set up the queue.
;
; Usage:
;
; Macro:
; JSR PC,XK.QIO ( test to make sure the flag is not set)
;
;
; REGISTER USAGE:
; R0 => Offset into the buffer.
; (smashed)
;
;--
.PSECT $CODE$, RO, I
XK.QIO::INC QUEFLG ; Is the queue flag clear ?
BNE 99$ ; No, branch
TST XKFREE ; Make sure we have at least one
BLE 100$ ; Position free
MOV XKFREC,R0 ; Store the offset in R0.
ADD #XKBUFF,R0 ; Add offset to buffer address.
CLR QUEFLG ; Flag QIO outstanding now
QIO$S #IO.RAL,#XKLUN,#XKREFN,,#XKSTAT,#XK.AST,<R0,#1.>
99$: RTS PC ; All done, return to caller.
100$: MOV #-1,QUEFLG ; Nothing free, reset the flag
RTS PC ; Return to the caller
.SBTTL Support XK.INP -- AST handling routine -- XK.AST
;++
; This is the AST routine to handle the reception of characters from
; the communications port.
;
; Usage:
; Called when I/O from comm port reads chars.
; ( Returns to where ever it was when called)
;
; Register usage:
; R0, R1, R2, R3 => Temporary locations for computations.
; (No registers get smashed )
;
;--
.PSECT $CODE$, RO, I
XK.AST::MOV R0,-(SP) ; Save R0.
JSR PC,5$ ; Call ourself so we can use standard
; save routine.
TST DMPRTN ; Have a routine to call
BEQ 1$ ; No, just skip this
JSR PC,@DMPRTN ; Call the routine
1$: MOV (SP)+,R0 ; Restore R0.
TST (SP)+ ; Remove the IOSB from the stack.
ASTX$S ; And return.
;
; We must save Registers R1 thru R3. Then clear out their old contents.
;
5$: JSR R1,$SAVE4 ; Save the registers
MOV #-1,QUEFLG ; If we got here, QIO is done
;
; Make sure that connect processing runs
;
SETF$S #CONEFN ; Flag connect must do something
;
; Make sure we didn't get an error.
;
TSTB XKSTAT ; What was the status of the I/O ?
BMI 40$ ; Branch if an error.
;
; Here if we got no error. See if we got any characters.
;
TST XKSTAT+2 ; Were any characters gotten ?
BEQ 30$ ; No characters, branch.
;
; Here if we got characters.
;
MOV XKSTAT+2,R1 ; Get number of characters read
ADD R1,XKFREC ; Increment the index, clear
BIC #^C<XKBUFLEN-1>,XKFREC ; the high order byte.
ADD R1,XKUSED ; Increment the used count,
SUB R1,XKFREE ; Decrement the index, clear
TST XKFREE ; Test the free space count.
BEQ 20$ ; Branch if zero.
;
; Here if the buffer is not full.
;
; We want to queue up a request for the most characters we
; can. This is MIN(XKFREE,(XKBUFLEN-XKFREC)).
MOV #XKBUFLEN,R2 ; Get max length
SUB XKFREC,R2 ; Determine distance to end of buffer
CMP R2,XKFREE ; Can we fill all free space?
BLE 10$ ; If LE, we can only read to end of buffer
MOV XKFREE,R2 ; Yes, get the max amount to read
;
; All cases, queue an I/O for R2 number of characters with time-out 0.
;
10$: MOV XKFREC,R1 ; Get the index to store characters
ADD #XKBUFF,R1 ; Add it to the buffer address.
INC QUEFLG ; QIO now pending
QIO$S #IO.RAL!TF.TMO,#XKLUN,#XKREFN,,#XKSTAT,#XK.AST,<R1,R2,#0>
20$: RTS PC ; All done
;
; Here if we got no characters.
;
30$: PJMP XK.QIO ; Issue single character QIO
;
; Here if we got an I/O error
;
40$: MOVB XKSTAT,ERRFLG ; Save error code and flag the error.
RTS PC ; And return
.SBTTL XK.OUT - Output a buffered character to the XK
;++
; This routine will output characters to the XK port.
;
; Usage:
; R1/ Character
; JSR PC,XKOUT
; (Return)
;
;--
.PSECT $CODE$, RO, I
XK.OUT::TST XKONCH ; Have room for this character?
BNE 10$ ; Yes, output it
;
; Here to wait for output to finish
;
WTSE$S #XKWEFN ; No, wait for output to finish
BR XK.OUT ; Loop and try again
;
; Here to output the character to the XK port
;
10$: MOV XKOIDX,R0 ; Get the current index
MOVB R1,XKOBUF(R0) ; Store the character
DEC XKONCH ; Decrement the number free
ADD #XKOBUF,R0 ; Point to the byte
QIO$S #IO.WVB,#XKLUN,#XKWEFN,,#XOIOSB,#XKOAST,<R0,#1>
INC XKOIDX ; Point to the next free location
BIC #^C<NM.XCH-1>,XKOIDX ; Point to the next free slot
RTS PC ; Return to the caller
.SBTTL XKOAST - AST routine for XK output done QIOs
;++
; This routine is called as an asynchronous trap routine for the XK
; output QIOs. This will adjust the counts and set the event flag for the
; XK outputs.
;
; Usage:
; QIO AST routine
;
;--
.PSECT $CODE$, RO, I
XKOAST: INC XKONCH ; Count the character as sent
TST (SP)+ ; Remove the item from the stack
ASTX$S ; Return from AST
.SBTTL FNDXKP - Find an XK parameter in the parameter block
;++
; This routine will find the XK parameter in the current processing block.
; It will return the address of the item in the parameter block.
;
; Usage:
; R0/ Parameter type (TC.xxx or XT.xxx)
; R1/ Address of block (assumed to be CURXKL in length)
; JSR PC,FNDXKP
; (Return)
;
; On return:
; R0/ Offset or 0 if not found
;
;--
.PSECT $CODE$, RO, I
.GLOBL FNDXKP
FNDXKP: JSR R1,$SAVE2 ; Save R1 and R2
MOV #<CURXKL/2>,R2 ; Get the length of the block
; Here to loop attempting to find the parameter
10$: CMPB R0,(R1)+ ; Is this the item?
BEQ 20$ ; Yes, leave loop
TSTB (R1)+ ; Point to the next item
SOB R2,10$ ; Loop for all parameters
CLR R0 ; Return a zero
RTS PC ; Return the parameter
; Here if we found the parameter in the block. Return the address of
; the status of the parameter.
20$: MOV R1,R0 ; Point to the parameter
RTS PC ; Return
.SBTTL End of KERXK
.END