home *** CD-ROM | disk | FTP | other *** search
- ;
- ; Receive a record - returns with carry bit set if EOT received
- ;
- rcvrecd:
- xra a; Clear error count
- sta errct
- rcvrpt: call funchk; Check function keys
- mvi b,10; 10-seconds to get 1st byte
- lda frstim
- ora a
- jnz rcvr1; If started, skip next line
- mvi b,3+1; Check every 4 seconds until started
- rcvr1: call recv; Get any char received
- jc rcvstot; Timeout error if no char received
- cpi soh; See if it is SOH
- jz rcvsoh; Got SOH, get record
- cpi stx; See if it is STX for 1k blocks
- jz rcvstx; Got STR, get record
- cpi cancel; Was it a CTL-X to abort?
- jz ckcan; If yes, check for aborting
- ora a; Get another char, if a null
- jz rcvrpt
- cpi '{'; V.22 synch char, ignore
- jz rcvrpt
- cpi '{' + 80h; V.22 synch char with high bit set
- jz rcvrpt
- cpi eot
- stc
- rz; with carry on end of transmission
- cpi crc; Ignore our own char coming back
- jz rcvrpt
- cpi ksnd; Ignore our own char coming back
- jz rcvrpt
- cpi nak; Ignore our own char coming back
- jz rcvrpt
- mvi a,1; Prevents going to modem
- sta remoff
- call crlf
- mov a,b
- call hexo
- call ilprt
- db 'H received not SOH ',0
- ; " "
- ; Didn't get SOH or EOT or did not get valid header so purge the line,
- ; then send NAK.
- ;
- rcvsr: call wait1; Flush incoming
- call ckabort; Want to quit now?
- lda frstim; Get first time switch
- ora a; Has first 'SOH' been received?
- mvi a,nak
- jnz rcvsr1; Yes, then send 'NAK'
- lda crcflg
- ora a
- mvi a,nak
- jz rcvsr1; Not CRC, signal checksum with NAK
- mvi a,crc; Else tell sender we have 'CRC'
- call send
- lda kflg
- ora a
- jz rcvsr1; not requesting 1k transmissions
- mvi a,ksnd; Signal we also have 1k capability
- rcvsr1: call send
- lda errct
- inr a; Increment error count
- sta errct
- mov b,a; Keep error count for now
- lda frstim; Have we gotten under way yet?
- ora a
- mov a,b; get error count back
- jz rcvsr2; Not started yet, exit
- cpi 10; 10 errors the limit, once under way
- jnc rcvsabt; Abort if over the limit
- call rdcount; Display record count before repeating
- jmp rcvrpt; Less than 10, keep going
- ;
- rcvsr2: cpi 10; 10 times for 1k/CRC yet? (40 seconds)
- jc rcvrpt; Keep trying if less
- xra a; Else flip to checksum mode
- sta crcflg
- mov a,b; Get the count back
- cpi 15; Another 5 times for checksum?
- jc rcvrpt; If less, try again, quit at 60 seconds
- ; " "
- ; Error limit exceeded, so abort
- rcvsabt:
- xra a
- sta remoff; Allow console output to remote
- lxi sp,stack; Clear the stack just in case
- call closfil; Keep whatever we got
- call ilprt
- db cr,lf,cr,lf,'++ RECEIVED FILE CANCELLED ++',0
- call delfile; Delete received file
- call erxit; Print 2nd half of message
- db '++ UNFINISHED FILE DELETED ++','$'
- ;
- ; Deletes the received file (used if receive aborts)
- ;
- delfile:
- mvi a,delet
- call fileop; Delete it
- inr a
- rnz; Success, return
- call erxit
- db cr,lf,'++ Can''t delete received file ++','$'
- ;
- ; Aborts with 1 CTL-X if first time flag is not set, two otherwise
- ;
- ckcan: lda frstim; 1st time flag set yet?
- ora a
- jz rcvsabt; If not, Abort and close file
- mvi b,2; Max 2 seconds for extra CTL-X
- call recv
- jc rcvrpt; No additional char, ignore CTL-X
- cpi cancel; If a 2nd CTL-X, abort and close file
- jz rcvsabt
- jmp rcvrpt; Else wait for a STX, SOH or timeout
- ;
- ; Timed out on receive
- ;
- rcvstot:
- lda frstim; 1st time flag set yet?
- ora a
- jz rcvsr; If not, don't show an error
- sta remoff
- call ilprt
- db '++ Timeout waiting for character ++',cr,lf,0
- jmp rcvsr; Bump error count, etc.
- ;
- ; Got a STX - set KFLG for 1k
- ;
- rcvstx: sta kflg; Set 1k flag
- sta crcflg; Ensure in CRC mode for 1k blocks
- jmp rcvs1
- ;
- ; Got SOH - get block number, block number complemented
- ;
- rcvsoh: xra a
- sta kflg; If SOH, clear the 1k flag
- rcvs1: mvi b,5; Timeout = 5 seconds
- mov a,b; Get something to store
- sta remoff; Error messages only shown locally
- sta frstim; Indicate first 'SOH' or 'STX' recvd.
- call recv; Get block number
- jc rcvstot; timeout
- mov d,a; Save block number
- mvi b,5; Timeout = 5 seconds
- call recv; Get complement of rcd no.
- jc rcvstot; Timeout
- cma
- cmp d; Same as original block number?
- jz rcvdata; Yes, get data
- ; " "
- ; Got bad record number in header
- call ilprt
- db '++ Error in header ++',cr,lf,0
- jmp rcvsr; Go check error limit and send NAK
- ;
- rcvdata:
- mov a,d
- sta rcvcnt; get and save record num.
- mvi c,0; Init checksum
- lxi h,0; Init CRC
- shld crcval; Clear CRC counter
- call grcdsz; 128/1024 on kflg
- lhld recptr; Get buffer address
- ; " "
- rcvchr: mvi b,5; 5 sec timeout
- call recv; Get the character
- jc rcvstot; Timeout
- mov m,a; Store char
- inx h; Point to next char
- dcx d; One less to go
- mov a,d
- ora e
- jnz rcvchr; Not done, get next char
- lda crcflg; Using 'CRC'?
- ora a
- jnz rcvcrc; If yes go get 'CRC'
- ; " "
- ; Verify checksum
- mov d,c; Save checksum
- mvi b,5; Timeout length
- call recv; Get checksum
- jc rcvstot; Timeout
- cmp d; Checksum ok?
- jz chksnum; Yes, exit
- call ilprt
- db '++ Checksum error ++',cr,lf,0
- jmp rcvsr; Go check the error limit and send NAK
- ;
- ; Got a record, it's a duplicate if equal to the previous number,
- ; it's OK if previous + 1 record
- chksnum:
- lda rcvcnt; Get received record number
- mov b,a
- lda rcdcnt; previous record number
- cmp b; Previous record repeated?
- jz rcvack; If yes 'ACK' to catch up
- inr a; Increment by 1 for 128 char block
- cmp b; Match this one we just got?
- jnz abort; No match, stop the sender, exit
- ret; Else return with carry not set, was ok
- ;
- ; Receive the Cyclic Redundancy Check characters (2 bytes) and see if
- ; the CRC received matches the one calculated. If they match, get next
- ; record, else send a NAK requesting the record be sent again.
- ;
- rcvcrc: mvi e,2; Number of bytes to receive
- rcvcrc2:
- mvi b,5; 5 second timeout
- call recv; Get CRC byte
- jc rcvstot; Timeout
- dcr e; Decrement the number of bytes
- jnz rcvcrc2; Get both bytes
- call crcchk; Check received CRC against calc'd CRC
- ora a
- jz chksnum; CRC ok, go check record numbers
- call ilprt
- db '++ CRC error ++',cr,lf,0
- jmp rcvsr; Go check error limit and send NAK
- ;
- ; Previous record repeated, due to the last ACK being garbaged.
- ; ACK it so sender will catch up
- rcvack: call sndack
- jmp rcvrecd
- ;
- ; Send an ACK for the record
- ;
- sndack: mvi a,ack
- jmp send
- ;
- ; ---------------------------------
- ;
- ; Send the record header
- ; Send SOH, block number and complemented block number (3 bytes total)
- ;
- sndhdr: lda kflg; Sending 1k blocks?
- ora a
- mvi a,stx; If yes, send a STX rather than SOH
- jnz sndhd1
- mvi a,soh; Send start of header
- sndhd1: call send
- sndhnm: lda rcdcnt; Send the current record number
- call send
- lda rcdcnt; Get the record number again
- cma; Complemented
- jmp send
- ;
- ; Send the data record
- ;
- sndrec: mvi c,0; Init checksum
- lxi h,0; Init CRC
- shld crcval
- call grcdsz; 128/1024 on kflg
- lhld recptr; Get buffer address
- sendc: mov a,m; Get a char
- call send; Send it
- inx h; next char
- dcx d
- mov a,e
- ora d
- jnz sendc; More
- ret
- ;
- ; Send the CRC or checksum value, whichever appropriate
- ;
- sndchk: lda crcflg; See if sending 'CRC' or 'checksum'
- ora a
- mov a,c; checksum value
- jz send; If chksum send it
- ; " "
- ; Send the two Cyclic Redundancy Check characters. Call FINCRC to
- ; calculate the CRC which will be in 'DE' upon return.
- ;
- sndcrc: call fincrc; Calculate the 'CRC' for this record
- mov a,d; Put first 'CRC' byte in accumulator
- call send; Send it
- mov a,e; Put second 'CRC' byte in accumulator
- call send; Send it
- xra a; Set zero return code
- ret
- ;
- ; After a record has been sent, and accepted, move the pointers
- ; forward 128 or 1024 characters for the next record.
- ;
- setptr: call grcdsz; 128/1024 on kflg
- lhld recptr; Get the buffer pointer
- dad d; Increment for the record just sent
- shld recptr; New buffer address for next block
- ret
- ;
- ; Get current protocol record size (128 or 1024, on KFLG)
- ; a,f,d,e
- grcdsz: lxi d,128
- lda kflg
- ora a
- rz
- lxi d,1024
- ret
- ;
- ; After a library transmission has been made, decrement the remaining
- ; records in that library file, then reset the 1k flag if less than 8
- ; remaining.
- ;
- setlbr: lda kflg
- lxi d,-1
- ora a
- jz setl1
- lxi d,-8
- setl1: lhld rcnt; Alter the records-sent count
- dad d
- shld rcnt; One less transmission to go
- ora a; 'K' flag already zero?
- rz; If yes, skip the rest
- ; " "
- ; See if enough records left to use 1k protocol if requested
- ;
- setflg: lhld rcnt
- mov a,h
- ora a
- rnz; 256 or more left
- mov a,l; Get number of records in 'L' register
- cpi 8
- rnc; If 8 or more, keep going
- xra a; Reset the 'K' flag
- sta kflg
- ret
- ;
- ; After a record is sent, a character is returned telling if it was
- ; received properly or not. An ACK allows the next record to be sent.
- ; A NAK causes the current record to be resent. If no character (or
- ; any character other than ACK or NAK) is received after a short wait
- ; (10 to 12 seconds), a timeout error message is shown and the record
- ; will be resent.
- ;
- gtack: call mdinst
- jz gtack1; No char ready now
- call mdinp; Get the char
- cpi ack
- rz; ACK, return
- cpi nak
- jz gtack2; NAK, print error, then resend
- cpi cancel; CTL-X to cancel attempt?
- jz gtcan
- gtack1: mvi b,1; 1 second for an ACK or NAK
- call recv; Go wait for a char
- jc gtack2; timed out
- cpi ack
- rz; ACK, return
- cpi nak
- jz gtack3; NAK, error
- cpi cancel; CTL-X to cancel attempt?
- jz gtcan
- gtack2: mvi b,12; 12-seconds more for an ACK or NAK
- call recv; Go wait for a char
- jc gtatot; timeout
- cpi ack
- rz; ACK, return
- cpi '{'
- jz gtack2; ignore V.22 sync char
- cpi '{' + 080h
- jz gtack2; ignore V.22 sync char w/hi bit
- cpi cancel; CTL-X to cancel attempt?
- jnz gtack3
- ; " "
- ; Two or more CTL-X will cancel the file transfer
- gtcan: mvi b,2; Up to 2 secs. for another CTL-X
- call recv
- mvi a,cancel; Get original char back
- jc gtack3; If no more CTL-X, display the first
- cpi cancel; Was it a second one?
- jz ackmsg; If yes, abort the file transfer
- gtack3: mov b,a; Save the char
- sta remoff; Send to console only
- lda chkeot; Sending EOT?
- ora a
- jnz ackerr; If yes, don't show error (for KMD)
- call ilprt
- db '++ ',0
- mov a,b
- cpi nak
- jz gtack4
- call hexo
- call ilprt
- db 'H',0
- jmp gtack5
- ;
- gtack4: call ilprt
- db 'NAK',0
- ; " "
- gtack5: call ilprt
- db ' received not ACK ++',cr,lf,0
- ; " "
- ; Timeout or error on ACK - bump error count then resend the record
- ; if error limit is not exceeded
- ;
- ackerr: lda accerr; Count accumulated errors on ACK
- inr a
- sta accerr
- lda errct
- inr a; Bump error count
- sta errct
- cpi 10
- jnc ackmsg; At limit, send error msg and abort
- call rdcount; Else show the record count for repeat
- stc; Make sure carry is set for repeat
- ret; And go back
- ;
- ;
- ; Reached error limit
- ;
- ackmsg: call wait1; Flush input
- call send3can; Tell remote we are quitting
- mvi b,1; Wait for remote to perhaps quit too
- call recv
- mvi a,bs
- call send3x; Clear any CTL-X from buffer
- xra a
- sta remoff; Show message on remote and local
- call erxit
- db cr,lf,'++ FILE TRANSFER ABORTED ++','$'
- ;
- ;
- ; Timed out, with no character - set the carry bit and return
- ;
- gtatot: call ilprt
- db '++ Timeout - no character received ++',cr,lf,0
- jmp ackerr
- ;
- ; Check the total error count vs. records sent, switch from 1k to 128
- ; character transmissions if higher than operator selected value.
- ;
- gtratio:
- lda kflg
- ora a
- rz; Not 1k blocks, skip this
- lda errct; See if we got any errors last record
- cpi 4
- jnc gtratio1; If 4 or more, switch to 128 size
- lda accerr; See if up to minimum errors yet
- cpi 3; Had as many as three errors yet?
- rc; If not, don't get excited too quickly
- lhld recdno; Get current record number increment
- lxi d,-8; Have not successfully sent this 1k yet
- dad d; Subtract the current increment
- xchg
- lhld accerr; Number of non-'ACK' errors in HL
- xchg
- call dvhlde; Get ratio in BC of records/hit
- call mspeed; get current speed
- cpi 5; 1200 baud?
- mvi a,71-1; for 1200 bps
- jz gtr1; If 1200, skip next line
- mvi a,43-1; for 2400 bps
- gtr1: cmp c; Compare with actual ratio
- rc; return if less hits than allowed
- ; " "
- gtratio1:
- xra a; Else reset the system to 128
- sta kflg
- call ilprt
- db cr,lf,'Aborting 1k blocks, too many hits',cr,lf,0
- ret
- ;
- ckabort:
- call constat
- ora a
- rz
- call conin
- cpi cancel
- rnz
- ; " "
- ; Aborts send or receive routines and returns to command line
- ;
- abort: lxi sp,stack
- call wait1; 1- sec delay to clear input
- call send3can; Show cancelling, remote may quit also
- call wait1; 1-second delay to clear input
- mvi a,bs
- call send3x
- abortx: xra a; Reset the batch flag
- sta bchflg
- call catch
- call erxit; Exit with abort message
- db cr,lf,'++ RXMD ABORTED ++','$'
- ;
- ; Send 3 cancels
- send3can:
- mvi a,cancel
- ; " "
- ; Send 3 copies of (a)
- send3x: call send
- call send
- jmp send
- ;
- ; Increment record number
- ; a,f
- incrno: push h
- push d
- lhld rcdcnt; Incr transmission count
- inx h
- shld rcdcnt
- lxi d,1
- lda kflg
- ora a
- jz incrn1; not 1k blocks, incr by 1
- mvi e,8; If 1k blocks incr. by 8
- incrn1: lhld recdno; Get current record count
- dad d; Increment that count properly
- shld recdno
- call rdcount
- pop d
- pop h
- ret
- ;
- ; Display the record count on the local CRT
- ; a,f,h,l
- rdcount:
- lhld recdno; Get the record number for display
- mvi a,1
- sta remoff; Set local only
- lda optsav; See if receive or send mode
- cpi 'R'
- jz rmsg
- call ilprt
- db cr,'Sending # ',0
- jmp rest
- rmsg: call ilprt
- db cr,'Received # ',0
- rest: lhld recdno
- call decout
- call ilprt
- db ' (',0
- call t4hex
- call ilprt
- db 'h) ',0
- jmp funchk; Check for function keys
- %