home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
extra
/
prodeh.mac
< prev
next >
Wrap
Text File
|
1988-08-16
|
23KB
|
812 lines
.TITLE DEHEX
.SBTTL Stuart Hecht
.IDENT /1.0.00/
.LIBRARY /LB:[1,5]RMSMAC/
.ENABLE LC
.NLIST BEX
;++
;This will take a set hexidecimal strings created by the hexify program and
; recreate the source file(s).
;--
.MCALL QIOW$C,QIO$C,QIOW$S,QIO$S,QIOW$,ALUN$S,EXIT$S
.MCALL FAB$B ; RMS calls
.MCALL RAB$B
.MCALL $CLOSE
.MCALL $CONNECT
.MCALL $CREATE
.MCALL $DISCONNECT
.MCALL $GET
.MCALL $OPEN
.MCALL $FETCH
.MCALL $WRITE
.MCALL $STORE
.MCALL $SET
.MCALL ORG$
.MCALL POOL$B
.SBTTL Definitions of symbols
TERLUN =7 ; Terminal LUN
XKLUN =8. ; XK LUN
TTEFN =1 ; Terminal Event Flag
XKREFN =2 ; XK read Event Flag
XKWEFN =3 ; XK write Event Flag
DWRLUN =1 ; Disk read LUN
DWWLUN =5 ; Disk write LUN
TRUE =1 ; True
FALSE =0 ; False
NULL =0 ; Null byte
KNORMAL =0 ; No error
RMS11 =1 ; RMS error
LEFTBYTE=377*400 ; All ones in left byte
RIGHTBYTE=377 ; All ones in right byte
HEXOFFSET=7 ; Offset to get to 'A from '9+1
MAX.MSG =256. ; Maximum number of chars from XK
RCV.SOH =': ; Receive start of packet
RCV.EOL =13. ; End of line character
UPPER ='a-'A ; Bit to clear for upper case
MSB =128. ; Most significant bit
; Packet types currently supported
PKDATA =00 ; Data packet code
PKRFM =255. ; Record format
PKRAT =254. ; Record attributes
PKMRS =253. ; Maximum record size
PKALQ =252. ; File length(blocks)
PKFILNM =251. ; File name
PKEOF =250. ; End of task file
;
.SBTTL RMS Initialization
POOL$B ; Allocate static pool for RMS
P$RAB 5 ; For internal RABs
P$BDB 5 ; For buffer descriptor blocks
P$FAB 4 ; For internal FABs
P$BUF 2048. ; Buffer space
POOL$E ; End of pool declarations
ORG$ SEQ ; $Open a sequential file
.SBTTL RMS 11 Data
.PSECT $PLIT$,RO,D
DEFALT: .ASCIZ 'SY:' ; System default.
DEFALN =.-DEFALT ; Size of the default device.
.EVEN
.SBTTL Data
M$PORT: .BYTE CR,LF
.ASCII 'Please choose device to use:'
.BYTE CR,LF
.ASCII '1. Communications port'
.BYTE CR,LF
.ASCII '2. Printer port'
.BYTE CR,LF
.ASCII '3. Disk file'
.BYTE CR,LF
.ASCII ' CHOICE (1-3): '
L$PORT= .-M$PORT
M$FILE: .BYTE CR,LF
.ASCII 'Please type the file name: '
L$FILE= .-M$FILE
M$SET: .BYTE CR,LF
.ASCII 'Is the port already setup correctly(baud rate)? '
L$SET= .-M$SET
M$BAUD: .BYTE CR,LF
.ASCII 'Choose a baud rate:'
.BYTE CR,LF
.ASCII '1. 300'
.BYTE CR,LF
.ASCII '2. 1200'
.BYTE CR,LF
.ASCII '3. 2400'
.BYTE CR,LF
.ASCII '4. 4800'
.BYTE CR,LF
.ASCII '5. 9600'
.BYTE CR,LF
.ASCII ' CHOICE (1-5): '
L$BUAD =.-M$BAUD
D$BAUD: .BYTE S.300,S.1200,S.2400,S.4800,S.9600 ; Baud rate code table
; for set multiple characteristics
M$CRLF: .BYTE CR,LF ; Data for carriage return/line feed
L$CRLF =.-M$CRLF
M$AK: .BYTE LF ; Data for aknowledged
.ASCII 'Y'
.BYTE CR
L$AK =.-M$AK
M$NAK: .BYTE LF ; Data for not aknowledged
.ASCII 'N'
.BYTE CR
L$NAK =.-M$NAK
M$UN: .BYTE LF ; Data for unrecognized code
.ASCII 'U'
.BYTE CR
L$UN =.-M$UN
M$RMS: .BYTE CR,LF,LF
.ASCII 'RMS ERROR'
L$RMS =.-M$RMS
M$INIT: .BYTE CR,LF,LF
.ASCII 'Port in use - Try again when free.'
L$INIT =.-M$INIT
M$REC: .BYTE CR,LF,LF
.ASCII 'RECEIVE ERROR - Try again.'
L$REC =.-M$REC
.EVEN
.SBTTL Data for set multiple characteristics
.PSECT $OWN$
T$SMC: .BYTE TC.RSP ; Receive speed
RSP: .BLKB 1
.BYTE TC.XSP ; Transmit speed
XSP: .BLKB 1
.BYTE TC.PAR,0 ; No parity
.BYTE TC.FSZ,8. ; Frame size
L$SMC =.-T$SMC
.SBTTL Storage locations
IOSTAT: .BLKW 1 ; QIO status
STAT1: .BLKW 1 ; Second word of status
WTCOUNT: .BLKW 1 ; Number of characters written
LENGTH: .BLKW 1 ; Length of data portion of packet
OPENFL: .BLKW 1 ; Tells us if the file is open
FILEFL: .BLKW 1 ; Flag that is set when reading from
; a file
LPFLAG: .BLKW 1 ; Flag that is set when reading from
; the printer port
CHKSUM: .BLKW 1 ; Checksum for the line
ADDRESS: .BLKW 1 ; Current address
ALQLOC: .BLKW 2 ; Storage for allocation
OUT.N: .BLKB 28. ; Space for output file name
OUT.L =.-OUT.N ; Length of output file name
INP.N: .BLKB 28. ; Space for input file name
INP.L =.-INP.N ; Length of input file name
.EVEN ; Need to start RDBUF on even boundary
RDBUF: .BLKB MAX.MSG ; XK read buffer
.EVEN
WTBUF: .BLKB 512. ; Disk write buffer
.EVEN
.SBTTL RMS 11 Data structures
RDFAB:: FAB$B
F$DNA DEFALT ; Address of default device.
F$DNS DEFALN ; Default length field.
F$FNA INP.N ; Address of file name
F$FNS INP.L ; Length of file name
F$LCH DWRLUN ; Logical channel to use
FAB$E
.EVEN
RDRAB:: RAB$B ; Beginning of RAB block.
R$FAB RDFAB ; Chain to FAB block.
R$RAC RB$SEQ ; Set the sequential access flag.
RAB$E ; End RAB block.
.EVEN
WTFAB:: FAB$B
F$DNA DEFALT ; Address of default device.
F$DNS DEFALN ; Default length field.
F$FNA OUT.N ; Address of file name
F$FNS OUT.L ; Length of file name
F$LCH DWWLUN ; Logical channel to use
FAB$E
.EVEN
WTRAB:: RAB$B ; Beginning of RAB block.
R$FAB WTFAB ; Chain to FAB block.
R$RAC RB$SEQ ; Set the sequential access flag.
RAB$E ; End RAB block.
.EVEN
.SBTTL Start of program
.PSECT $CODE$,RO,I
DEHEX::
ALUN$S #TERLUN,#"TI,#0 ; Assign terminal LUN
1$: MOV #M$PORT,R0 ; Output the port option list
MOV #L$PORT,R1
JSR PC,WRITE
MOV #RDBUF,R0 ; Input the port the user wants
MOV #2,R1
JSR PC,READ
CLR FILEFL ; Set flag to say we are reading from
CLR LPFLAG ; some port(assume correct)
CMPB RDBUF,#'1 ; Check and see if choice is XK
BNE 3$ ; No so branch
ALUN$S #XKLUN,#"XK,#0 ; Assign the LUN
BR 6$ ; Continue with program (set port)
3$: CMPB RDBUF,#'2 ; Check and see if choice is LP
BNE 4$ ; If no then branch
ALUN$S #XKLUN,#"TT,#2 ; Assign the LUN
MOV #TRUE,LPFLAG ; Set flag we're reading from LP
BR BEGIN ; Continue with program
4$: CMPB RDBUF,#'3 ; Make sure its the remaining choice
BNE 1$ ; If not then try again
JMP FILE ; Go do the disk file
; Set up XK port
6$: JSR PC,XKINIT ; Get the XK port
7$: MOV #M$SET,R0 ; Output the is port set up message
MOV #L$SET,R1
JSR PC,WRITE
MOV #RDBUF,R0 ; Get response
MOV #2,R1
JSR PC,READ
TST R0 ; Check for input
BEQ 7$ ; If none then reprompt
BICB #UPPER,RDBUF ; Convert to upper case
CMPB RDBUF,#'Y ; Check to see if afirmative
BNE 8$ ; If not then set it up
JMP BEGIN ; Port already set so don't do it
8$: MOV #M$BAUD,R0 ; Output baud rate message
MOV #L$BUAD,R1
JSR PC,WRITE
MOV #RDBUF,R0 ; Get response
MOV #2,R1
JSR PC,READ
TST R0 ; Check for input
BEQ 7$ ; If none then reprompt
MOVB RDBUF,R0 ; Get the answer
SUB #'1,R0 ; Subtract off ASCII
MOVB D$BAUD(R0),RSP ; Set the baud rate
MOVB D$BAUD(R0),XSP
; Set the characteristics
QIO$C SF.SMC,XKLUN,XKWEFN,,IOSTAT,,<T$SMC,L$SMC>,$CODE$
BR BEGIN ; Go do real stuff
; If here then we're doing a file
FILE: MOV #M$FILE,R0 ; Output the get file name message
MOV #L$FILE,R1
JSR PC,WRITE
MOV #INP.N,R0 ; Get the file name
MOV #INP.L,R1
JSR PC,READ
TST R0 ; Check for no input
BEQ FILE ; Go back and get some
;Open the file
MOV #RDFAB,R1 ; Put address of FAB into R1.
$STORE R0,FNS,R1 ; Tell RMS file name length
$OPEN #RDFAB ; Open the file
JSR PC,RMSERR ; Check for file error
MOV #RDRAB,R1 ; Put address of RAB into R1.
$STORE #RDBUF,UBF,R1 ; Put address of user buffer in RAB.
$STORE #RDBUF,RBF,R1 ; Put record buffer address in RAB
$STORE #MAX.MSG,USZ,R1 ; Put size of user buffer into RAB.
$STORE #MAX.MSG,RSZ,R1 ; Put record buffer size in RAB
$CONNECT #RDRAB ; Connect to record.
JSR PC,RMSERR ; Check for file error
MOV #TRUE,FILEFL ; Set flag to file reading
.SBTTL Do the real work
;++
; Do the actual work
;--
BEGIN: MOV #M$CRLF,R0 ; Get a return/linefeed and output them
MOV #L$CRLF,R1
JSR PC,WRITE
20$: CLR WTCOUNT ; Initialize the pointer
CLR ADDRESS ; Initialize the address
CLR OPENFL ; Set the file to not open
; Say we're ready for data
MOV #M$AK,R0 ; Get the address of stuff to send
MOV #L$AK,R1 ; Get the length
JSR PC,SEND ; Tell host that we got it
.SBTTL Main loop
; Main loop to get data
DOLIN:
CLR CHKSUM ; Clear the checksum
JSR PC,RECEIVE ; Get the line
JSR PC,CVTBIN ; Convert it to a real number
MOV R0,LENGTH ; Save the length
JSR PC,CVTBIN ;
MOV R0,R3 ; Save high order of address
SWAB R3 ; Shift to correct spot
JSR PC,CVTBIN ;
BIS R0,R3 ; Fill in the low order of address
JSR PC,CVTBIN ;
CMP #PKDATA,R0 ; Check to see if this is regular data
BNE NOTDAT ; If not then check the special cases
; Check for end of hex file
TST R3 ; Check to see if the address is all
BNE DATST ; zero, if not then branch
TST LENGTH ; Check to see if the length is zero
BNE DATST ; also, if not then branch
MOV #M$AK,R0 ; Send an AK for this line since we
MOV #L$AK,R1 ; never reach the place we normally
JSR PC,SEND ; do this
JMP FINISH ; Must be end of hex file so finish up
; Regular data to put into the file
DATST: TST OPENFL ; Check to see if the file is open yet
BNE DAT1 ; If it is then skip the open
JSR PC,OPEN ; Open the file
DAT1: CMP R3,ADDRESS ; Check for null compression
BEQ 10$ ; If none compressed then continue past
CLR R0 ; Make a null
JSR PC,PUT ; and put it into the file
INC ADDRESS ; Point to next address
BR DATST ; Go see if there are any more nulls
; Go to work on the HEX we got on the line
10$: MOV LENGTH,R2 ; Get the length
TST R2 ; See if there is any data
BEQ 30$ ; If not then branch
25$: JSR PC,CVTBIN ; Convert it
JSR PC,PUT ; Put the character in the file
INC ADDRESS ; Increment the address
SOB R2,25$ ; Repeat until all done
30$: BR LINDON ; Go finish this line
NOTDAT: MOV #WTFAB,R5 ; Get the FAB address
CMP #PKRFM,R0 ; Check to see if this is record fmt
BNE NOTRFM ; If not then don't do this stuff
; Store the Record format (FIX, VAR, ...)
JSR PC,CVTBIN ;
$STORE R0,RFM,R5 ; Store the record format
BR LINDON ; Go finish this line
NOTRFM: CMP #PKRAT,R0 ; Check to see if this is record type
BNE NOTRAT ; If not then branch
; Store the record type (CR, ...)
JSR PC,CVTBIN ;
$STORE R0,RAT,R5 ; Store the record type
BR LINDON ; Go finish this line
NOTRAT: CMP #PKMRS,R0 ; Check to see if this is max record
BNE NOTMRS ; size, branch if not
; Get the maximum record size (512. for tasks)
JSR PC,CVTBIN ; Convert high order byte
MOV R0,R3 ; Save it
SWAB R3 ; Shift it to the high order byte
JSR PC,CVTBIN ; Convert low order byte
BIS R0,R3 ; Put low order word into R3 also
$STORE R3,MRS,R5 ; Store the maximum record size
BR LINDON ; Go finish this line
NOTMRS: CMP #PKALQ,R0 ; Check to see if this is allocation
BNE NOTALQ ; If not then branch
; Get the file length (in blocks)
JSR PC,CVTBIN ; Convert high order byte
MOV R0,R3 ; Save it
SWAB R3 ; Shift it to the high order byte
JSR PC,CVTBIN ; Convert low order byte
BIS R0,R3 ; Put low order word into R3 also
MOV R3,ALQLOC ; Save it
CLR ALQLOC+2 ; clear out high word
$STORE ALQLOC,ALQ,R5 ; Store the allocation
BR LINDON ; Go finish this line
NOTALQ: CMP #PKFILNM,R0 ; Check to see if this is file name
BNE NOTFILNM ; If not then branch
; Get the file name
MOV LENGTH,R2 ; Get the length
$STORE R2,FNS,R5 ; Store the file name length
MOV #OUT.N,R3 ; Get the output file name address
25$: JSR PC,CVTBIN ; Convert next character of the name
MOVB R0,(R3)+ ; Save the character
SOB R2,25$ ; Repeat until all done
MOV #M$CRLF,R0 ;
MOV #L$CRLF,R1 ;
JSR PC,WRITE ; Output a return/line feed
MOV #OUT.N,R0 ;
MOV LENGTH,R1 ;
JSR PC,WRITE ; Output the file name
MOV #M$CRLF,R0 ;
MOV #L$CRLF,R1 ;
JSR PC,WRITE ; Output a return/line feed
BR LINDON ; Go finish this line
NOTFILNM:
CMP #PKEOF,R0 ; Check to see if this is end of task
BNE NOTPKEOF ; If not then branch
; End of ouput file record found
JSR PC,CLTSK ; Close the task file
CLR WTCOUNT ; Initialize the pointer
CLR ADDRESS ; Initialize the address
JMP LINDON ; Go finish this line
; Unknown code
NOTPKEOF: ; Since we don't know what the code
MOV #M$UN+1,R0 ; just send the unknown code text to
MOV #1,R1 ; the terminal and the port
JSR PC,WRITE ;
DEC R0 ; Move to beginning of data
MOV #L$UN,R1 ;
JSR PC,SEND ;
JMP DOLIN ; Go do next input line
.SBTTL Finished with this line
; Line processed without a problem
LINDON:
MOV #M$AK+1,R0 ; Get the data address of the
; single character
MOV #1,R1 ; Only write single char to terminal
JSR PC,WRITE ; Write to the terminal
DEC R0 ; Get to beginning of data
MOV #L$AK,R1 ; Get the length of the data
JSR PC,SEND ; Send the aknowledgement to the port
JMP DOLIN ; Good so do next line
.SBTTL Finish up
;++
;Finish up
;--
FINISH:
; Close the file(s)
JSR PC,CLTSK ; Close the task file if it isn't yet
TST FILEFL ; See if we read from a file
BEQ 10$ ; If not then branch
MOV #RDFAB,R1 ; Get FAB for input file
$CLOSE R1 ; Close the input file
JSR PC,RMSERR ; Check for file error
BR END ; Go exit
10$: JSR PC,XK.SHT ; Shut down the XK port if we didn't
; read from a file
END: EXIT$S
.SBTTL Close file
;++
; Close the output file if there is one open
;
; If there is an error the program stops with an RMS error
;
; Registers destroyed: R0, R1
; The OPENFL state is changed to file not open (OPENFL=0).
;--
CLTSK: TST OPENFL ; See if the task file is open
BEQ 10$ ; If not then just return
; Write last buffer if needed
TST WTCOUNT ; See if there is any data not written
BEQ 8$ ; If not then branch
MOV #WTRAB,R1 ; Get the RAB address
$STORE WTCOUNT,RSZ,R1 ; Put its size into the RAB.
$WRITE R1 ; Put the buffer of data.
JSR PC,RMSERR ; Check for file error
; Close the file
8$: MOV #WTFAB,R1 ; Get FAB for output file
$CLOSE R1 ; Close output file
JSR PC,RMSERR ; Check for file error
CLR OPENFL ; Set the state to file not open
10$: RTS PC ; Return to sender
.SBTTL Output and input to/from terminal
;++
; Write data to terminal.
; Call with: R0 Address of data to output
; R1 Length of data
; Registers destroyed: NONE
;--
WRITE:
QIOW$S #IO.WVB,#TERLUN,#TTEFN,,#IOSTAT,,<R0,R1>
RTS PC
;++
; Read from the terminal
; Call with: R0 Address of buffer
; R1 Number of characters to read
;
; Returned: R0 Number of characters read
; Registers destroyed: R0
;--
READ: QIOW$S #IO.RVB!TF.ESQ,#TERLUN,#TTEFN,,#IOSTAT,,<R0,R1>
MOV STAT1,R0 ; Get the number of character read
RTS PC
.SBTTL RMS error routine
;++
;Check for RMS error
; Call with: R1 RMS FAB address
;
; Returned: R0 Status
; Registers destroyed: R0
; Program stops after error message is displayed if there is any type of error.
;--
RMSERR: $FETCH R0,STS,R1 ; Get the status and put it in R0
TST R0 ; Test the status code for success.
BMI 60$ ; If negative then branch.
MOV #KNORMAL,R0 ; Set up a successful return code.
RTS PC ; Return to caller
; Here if there is an RMS error we can't recover from
60$: MOV #M$RMS,R0 ; Get the RMS error message
MOV #L$RMS,R1 ; address and length
JSR PC,WRITE ; Output the error message
EXIT$S ; Exit since we can not recover
.SBTTL Open the output file
;++
; Create and open the output file and set the file open flag
;
; Registers destroyed: R0, R1
; Program stops after error message is displayed if there is any type of error.
;--
OPEN: MOV #TRUE,OPENFL ; State that the file is open
MOV #WTFAB,R1 ; Put address of FAB into R1.
$SET #FB$WRT,FAC,R1 ; Set the block write in FAB.
$STORE #FB$CTG,FOP,R1 ; Tell RMS to make the task contiguous
$CREATE #WTFAB ; Create the file
JSR PC,RMSERR ; Check for file error
MOV #WTRAB,R1 ; Put address of RAB into R1.
$STORE #WTBUF,UBF,R1 ; Put address of user buffer in RAB.
$STORE #WTBUF,RBF,R1 ; Put record buffer address in RAB
$STORE #512.,USZ,R1 ; Put size of user buffer into RAB.
$STORE #512.,RSZ,R1 ; Put record buffer size in RAB
$CONNECT #WTRAB ; Connect to record.
JSR PC,RMSERR ; Check for file error
RTS PC ; Return to sender
.SBTTL Put a character to the file
;++
; Put a character to the output file.
; The buffer is only written when 512. characters have been sent to the routine
; If the file does not end on a boundary then the buffer will have to be
; written by some other routine.
;
; Call with: R0 Contains the character to be put into file
; Registers destroyed: R0, R1
;
; Program stops after error message is displayed if there is any type of error.
;--
PUT: MOV R0,-(SP) ; Save the character
MOV WTCOUNT,R0 ; Get the offset into the buffer
MOVB (SP)+,WTBUF(R0) ; Put the character
INC WTCOUNT ; Increment the offset into the buffer
CMP WTCOUNT,#512. ; Check to see if we are past the end
BNE 10$ ; If not then branch
MOV #WTRAB,R1 ; Get the RAB address
$STORE WTCOUNT,RSZ,R1 ; Put its size into the RAB.
$WRITE R1 ; Put the buffer of data.
JSR PC,RMSERR ; Check for file error
CLR WTCOUNT ; Clear the pointer
10$: RTS PC ; Return to sender
.SBTTL Convert to binary
;++
; Convert 2 hexidecimal digits to binary
; Input is from the input buffer pointed to by R4 (it is incremented twice)
;
; Call with: R4 The pointer into the input buffer
; Returned: R0 The binary walue
; Registers destroyed: R0,R1
;--
CVTBIN:
CLR R0 ; Clear R0 for the BISB
BISB (R4)+,R0 ; Get the next digit
JSR PC,BIN ; in place and convert to binary
ASH #4,R0 ; Multiply the result by 16
MOV R0,R1 ; and save it
CLR R0 ; Clear R0
BISB (R4)+,R0 ; Get the next digit
JSR PC,BIN ; Convert to binary
BIS R1,R0 ; Set the correct bits for high order
ADD R0,CHKSUM ; Add the value to the checksum
RTS PC ; Return to sender
BIN: CMP R0,#'9 ; Check to see if above '9
BLE 1$ ; If not then branch
SUB #HEXOFFSET,R0 ; Subtract offset to alphabet
1$: SUB #48.,R0 ; Make binary
RTS PC ; Return to sender
.SBTTL Initialize the port
XKINIT:
;++
; Attach to the port so that no one else can be screwing around
; with it behind our backs.
;
; Registers destroyed: R0
;
; If there is an error the error message will be output and the program
; will stop.
;--
QIO$S #IO.ATT,#XKLUN,#XKREFN,,#IOSTAT ; Grab the device
MOVB IOSTAT,R0 ; Get the status
BLE BAD ; Branch if bad
; Set the characteristics
RTS PC ; Return good try
; Here if we can't get the XK port
BAD: MOV #M$INIT,R0 ; Get the INIT error message
MOV #L$INIT,R1 ; address and length
JSR PC,WRITE ; Output the error message
QIOW$C IO.KIL,XKLUN,XKWEFN,,,,,$CODE$ ; Kill pending I/O queues.
EXIT$S ; Exit since we can not recover
XK.SHT: 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 Receive a line of data
;++
; This will get a line of data from the input device
;
; Returned: R4 Address of start of data buffer
; Registers destroyed: R0, R1, R3, R4
;
; A checksum error will cause a NAK to be sent and input to be read again
; A real error will cause an error message to be output and the program to stop
;--
RECEIVE:
TST FILEFL ; See if we're reading from a file
BEQ 10$ ; If not then don't read from the file
; Here if we're reading from a file
MOV #RDRAB,R1 ; Get the RAB address
$GET R1 ; Get the record
JSR PC,RMSERR ; Check for file error
MOV #MAX.MSG,R3 ; Assume we got a full buffer
BR RECCHK ; Check the data we got
; Here so reading from one of the ports
10$: TST LPFLAG ; See if we're reading from LP:
BNE RECLP ; If so then use that routine
; Here if we're reading from the XK port
MOV #RDBUF,R1 ; Point at first byte of buffer
CLR R3 ; Clear count of chars we have seen
QIOW$S #IO.RAL!TF.RNE,#XKLUN,#XKREFN,,#IOSTAT,,<R1,#1.>
TST IOSTAT ; Test for error
BMI 85$ ; If we got an error, return it
BICB #MSB,(R1) ; Clear most significant bit
CMPB (R1)+,#RCV.SOH ; Check for start of header
BNE 10$ ; If not, check timeout and try again
INC R3 ; Increment the counter
; Here after we have gotten the start of packet character. Now pick up the
;rest
20$: QIOW$S #IO.RAL!TF.RNE,#XKLUN,#XKREFN,,#IOSTAT,,<R1,#1.>
TST IOSTAT ; Test for error
BMI 85$ ; If we got an error, return it
BICB #MSB,(R1) ; Clear most significant bit
CMPB @R1,#RCV.SOH ; Check for start of header
BEQ 10$ ; Restart buffer if so
INC R3 ; Count the character
CMPB (R1)+,#RCV.EOL ; Get end of line character?
BEQ RECCHK ; Yes, go return
CMP R3,#MAX.MSG ; Fill buffer completly yet?
BNE 20$ ; If not, just get next character
DEC R1 ; Otherwise, back up one character
BR 20$ ; And try again
; Here if we got some error that makes it impossible to continue the transfer
85$: MOV #M$REC,R0 ; Get the receive error message
MOV #L$REC,R1 ; address and length
JSR PC,WRITE ; Output the error message
EXIT$S ; Exit since we can not recover
; Here to read from LP port(TT2:)
RECLP:
QIOW$S #IO.RVB!TF.RNE,#XKLUN,#XKREFN,,#IOSTAT,,<#RDBUF,#MAX.MSG>
MOV STAT1,R3 ; Get number of characters read
; Here to check the data we got from any type of receive routine
RECCHK: MOV #RDBUF,R4 ; Get the address of the information
CLR R1 ; Clear the data start address
80$: BICB #MSB,(R4) ; Clear parity bit
CMPB (R4)+,#RCV.SOH ; Check for start of header
BNE 81$ ; If not the just keep going
MOV R4,R1 ; Start of header so save it
81$: SOB R3,80$ ; Repeat until done
TST R1 ; Check to see if we got a SOH
BNE 85$ ; If good then skip the jump
JMP RECEIVE ; If not then re-read
85$: MOV R1,R4 ; Move to R4 for use
MOV R4,-(SP) ; Save SOH pointer on stack
JSR PC,CVTBIN ; Convert all to binary to see if
MOV R0,R3 ; Get the length of data
ADD #4,R3 ; Add the length of address and field
; type and checksum
BMI 94$ ; If we have a negative number then
; must have been a bad length
CMP R3,#MAX.MSG/2-1 ; If we got some length that is out of
BGE 94$ ; range then NAK right away
92$: JSR PC,CVTBIN ; Convert all to binary to see if
SOB R3,92$ ; the checksum is OK
93$: BIC #LEFTBYTE,CHKSUM ; We only want an 8 bit checksum
TST CHKSUM ; Test for a zero checksum
BEQ 95$ ; If OK then exit normally
94$: CLR CHKSUM ; Clear the checksum for the line
MOV #M$NAK+1,R0 ; Get the address of the message
MOV #1,R1 ; Only write the first character to
JSR PC,WRITE ; the terminal
DEC R0 ; Move to beginning of data
MOV #L$NAK,R1 ; Get the whole message length for port
JSR PC,SEND ; Send a NAK to the port
TST (SP)+ ; Pull to pointer off the stack
JMP RECEIVE ; Try to get the line again
; Return to sender
95$: MOV (SP)+,R4 ; Get the pointer back
RTS PC ; Return to sender
.SBTTL Send a line to the host
;++
; Send the buffer to the host if we aren't reading from a file
; If reading from a file just return
;
; Registers destroyed: None
;--
SEND:
TST FILEFL ; See if we're reading from a file
BNE 20$ ; If so then don't send to the port
QIOW$S #IO.WLB,#XKLUN,#XKWEFN,,#IOSTAT,,<R0,R1>
20$: RTS PC ; Return to sender
.SBTTL End of the Dehexify
.END DEHEX