.title KRTSEN Send file processing .ident "V03.62" ; /62/ 27-Jul-93 Billy Youdelman ; ; dump FILLOG, as PRINTM now does this ; use log$packets for state logging ; provide for logfile errors ; add time to SEN.SW state logging ; modified to wait thru bad ack packets, noise, etc.. ; recpkt buffer back to normal size, now passes same to rpack ; /BBS/ 1-Dec-91 Billy Youdelman V03.61 ; ; increased size of recpkt buffer to $allsiz to avoid writing past ; eob (causing trap to 4 in rpack$ which crashes the program) when ; packets are out of sync and a long packet arrives where an ack ; is expected, or line noise "extends" otherwise ok data.. ; ; kill debug to TT if not running as a local Kermit ; modified to (w/KRTATR) send all attributes in a single packet ; ensure directory search channel is closed on errors/aborts ; ; display abort message when file skipped due to SET FILE PROTECT ; (by an "X" or "Z" in the ACK packet) on the other Kermit ; 13-Oct-84 14:04:37 Brian Nelson ; ; Copyright 1983,1984 Change Software, Inc. ; ; This software is furnished under a license and may ; be used and copied only in accordance with the ; terms of such license and with the inclusion of ; the above copyright notice. This software or any ; other copies thereof may not be provided or other- ; wise made available to any other person. No title ; to and ownership of the software is hereby trans- ; ferred. ; ; The information in this software is subject to ; change without notice and should not be construed ; as a commitment by the author. .include "IN:KRTMAC.MAC" .iif ndf KRTINC .error <; .include for IN:KRTMAC.MAC failed> .include "IN:KRTDEF.MAC" .iif ndf MSG$DA .error <; .include for IN:KRTDEF.MAC failed> .mcall .PURGE ; /62/ to hose dir search ch on err .sbttl Local data .psect $pdata ; /62/ consolidated this stuff here.. adpmsg: .asciz "First data packet failed, PACKET_LENGTH reduced to " adptag: .asciz ". bytes" badpre: .asciz "Ignoring invalid " badack: .asciz "ACK/NAK serial number" badpak: .asciz "response or noise" badtag: .asciz ", paknum: " S2$: .asciz "SEN.SW" S3$: .asciz "Warning: Parity found in SOH byte" SD25$: .asciz "ABORT$CURRENT_FILE" SD26$: .asciz "ABORT$ALL_FILES" SD27$: .asciz " received in other Kermit's ACK packet" SE22$: .byte eof$dis ,0 SF1$: .asciz "Sending file " SF2$: .asciz " as file " .even .psect recpkt ,rw,d,lcl,rel,con recpkt: .blkb maxpak+2 ; /62/ added passed length to rpack .psect $code .sbttl State controller for send file processing .enabl lsb sen.sw:: sendsw::movb @r5 ,state ; state at which caller wants to begin clr cccnt ; /62/ no ^Cs typed yet movb #defchk ,chktyp ; setup the default checksum type mov #1 ,chksiz ; size of default checksum mov $image ,image ; ensure correct default for mode clr paknum ; packet_number := 0 clr numtry ; retry_count := 0 cmpb conpar+p.chkt,#'1 ; did other system want CRC checks? bne 1$ ; yep cmpb senpar+p.chkt,#'1 ; simple block checks today? beq 5$ ; yes, assume caller's state is ok 1$: movb #sta.sin,state ; no, must force a sinit exchange 5$: clr logini ; /62/ force display stats header call senhdr ; packet count stats and display init clr dpnumber ; /43/ clear data packet count movb sentim ,senpar+p.time ; /62/ load send time_out value 10$: call sendeb ; do send debugging if enabled call senlog ; /62/ update transfer stats display cmp incpar ,#1 ; /62/ is it possible that parity bne 15$ ; /62/ is messed up? calls printm ,<#1,#S3$> ; /62/ warn, but only once inc incpar ; /62/ be sure it is only once! 15$: tst remote ; /43/ if remote, bne 20$ ; /43/ ignore random noise tst cccnt ; /36/ ^C abort? beq 20$ ; /36/ no movb #sta.cca,state ; /36/ ya, fake abort 20$: scan state ,#200$ ; now dispatch asl r0 ; based on current jsr pc ,@210$(r0) ; state movb r1 ,state ; set a new state bcc 10$ ; ok movb #defchk ,chktyp ; reset the checksum type mov #1 ,chksiz ; size of the above checksum save ; save the exit status code tst inopn ; file open from a failure? beq 110$ ; no calls close ,<#lun.in> ; ya, ensure that it's closed clr inopn ; /BBS/ say so.. 110$: .purge #lun.sr ; /62/ close dir search channel call incsta ; /43/ increment timer stats unsave ; pop exit status code please return .save .psect $pdata 200$: .byte sta.abo ,sta.brk,sta.com,sta.dat,sta.fil,sta.atr,sta.sin .byte sta.eof ,sta.cca .byte 0 .even 210$: .word send.$ .word send$$ ,sbreak ,send.c ,sdata ,sfile ,sattr ,sinit ; /62/ .word seof ,ccabort .restore .dsabl lsb .sbttl State routines for SENDSW .enabl lsb ; /62/ send.$: call bad$pak ; /62/ report ignoring bad packet type movb state ,r1 ; /62/ stay in same state clc ; keep sen.sw running return ccabort:spack #msg$err,paknum ; /36/ break up a deadlock perhaps send$$: mov sp ,r0 ; flag there was an error movb #sta.abo,r1 ; return(abort) br 90$ send.c: clr r0 ; complete 90$: sec ; exit sen.sw return .dsabl lsb ; /62/ .sbttl Received bad ACK/NAK and error handling .enabl lsb ; /62/ all new.. sndx$$: movb state ,r1 ; time_out, stay in current state br 10$ ; kill re-read loop and retry packet sndx.$: cmp numtry ,maxtry ; bad data, been here too often? blo bad$pak ; compare as if already bumped.. s$retry:call m$retry ; too many retries error br sabort sndx.e: calls prerrp ,<#recpkt> ; print out received error packet br sabort s$sync: call m$sync ; can't resync packets error sabort: movb #sta.abo,r1 ; exit please 10$: clr datauk ; stop read_only loop return bad$pak:mov #1 ,datauk ; listen again, no matter what mov #badpak ,r3 ; point to appropriate text br 20$ ; common code.. bad$ack:mov #-1 ,datauk ; listen again, but just once mov #badack ,r3 ; point to appropriate text 20$: inc numtry ; this is another retry mov #pcnt.s ,r1 ; packet number mov #spare1 ,r0 ; where to write ascii output clr r2 ; kill leading zero and spaces call $cddmg ; convert 32-bit # to ascii clrb @r0 ; make it .asciz calls printm ,<#4,#badpre,r3,#badtag,#spare1> ; say what's up return .dsabl lsb .sbttl Send debugging and logging ; /62/ major revision.. sendeb: mov trace ,r0 ; copy of debug status word bic #^c,r0 ; need to do this? beq 50$ ; nope save sub #100. ,sp ; allocate a small buffer mov sp ,r1 ; point to it mov #S2$ ,r2 ; /62/ pointer to "SEN.SW" call paksta ; get elapsed time of last packet sub sp ,r1 ; get the record length mov sp ,r2 ; and point back to the record bit #log$pa ,trace ; debugging for SEND.SW beq 30$ ; if trace is on then calls putrec , ; dump it tst r0 ; did it work? beq 30$ ; ya call logerr ; no, handle the error 30$: tst remote ; is there a TT to do this? bne 40$ ; not right now.. bit #log$de ,trace ; terminal debugging on? beq 40$ ; no wrtall r2 ; ya, print it .newline 40$: add #100. ,sp ; deallocate the buffer unsave 50$: return .sbttl Send attribute data for the current file .enabl lsb ; /BBS/ Modified to (w/KRTATR.MAC) send all attributes in a single packet sattr: clr datauk ; /62/ init re-read only flag inc numtry ; abort if it's been trying too much cmp numtry ,maxtry ; well? blos 10$ ; no, keep it up jmp s$retry ; /62/ handle the error please 10$: tst doattr ; really do this? beq 90$ ; no calls w$attr ,<#lun.in,#packet> ; build the attributes packet tst r0 ; any errors along the way? bne 90$ ; yes tst r1 ; anything to send over? beq 90$ ; no spack #msg$atr,paknum,r1,#packet ; send file attributes to receiver 20$: rpack r2 ,r3 ,#recpkt,#maxpak ; /62/ get the reply please scan r1 ,#200$ ; and take action on the reply asl r0 ; dispatch based on the packet type jsr pc ,@210$(r0) ; simple tst datauk ; /62/ need to re-read w/o re-sending? bne 20$ ; /62/ ya br 99$ ; /62/ no 90$: calls buffil ,<#packet> ; get the first buffer of data please mov r1 ,size ; and save it movb #sta.dat,r1 ; switch to data state 99$: clc ; /62/ keep sen.sw running return .save .psect $pdata 200$: .byte msg$err ,msg$nak,msg$ack,timout ,badchk .byte 0 .even 210$: .word sndx.$ ; /62/ .word sndx.e ,satr.n ,satr.y ,sndx$$ ,sndx.$ ; /62/ badchk = noise .restore .dsabl lsb .sbttl Process response to SATTR .enabl lsb ; /62/ satr$$: jmp sndx$$ ; /62/ common code satr.n: cmp r3 ,paknum ; /62/ is NAK for this packet? beq satr$$ ; /62/ ya, resend the data dec r3 ; NAK for next packet bge 1$ ; is ACK for current packet mov #63. ,r3 ; if --paknum<0, 63:paknum 1$: cmp r3 ,paknum ; well? beq 10$ ; /62/ it's an implicit ACK br 2$ ; /62/ out of sync, try to fix things satr.y: cmp r3 ,paknum ; ensure ACK is for correct packet beq 10$ ; it is 2$: cmp numtry ,maxtry ; /62/ it isn't, been here too often? blos 3$ ; /62/ not yet jmp s$sync ; /62/ ya, say so, send error packet 3$: tst datauk ; /62/ already tossed one bad ACK/NAK? blt satr$$ ; /62/ ya, re-send packet jmp bad$ack ; /62/ listen again, but just once 10$: clr datauk ; /62/ stop read_only loop clr numtry ; retrycount := 0 incm64 paknum ; paknum := (paknum+1) mod 64 calls buffil ,<#packet> ; /BBS/ get the first buffer of data mov r1 ,size ; /BBS/ and save it movb #sta.dat,r1 ; /BBS/ switch to data state return .dsabl lsb ; /62/ .sbttl Send a break packet .enabl lsb sbreak: clr datauk ; /62/ init re-read only flag inc numtry ; abort if retry count is too high cmp numtry ,maxtry ; well? blos 10$ ; ok jmp s$retry ; /62/ handle the error please 10$: spack #msg$bre,paknum,#0,#packet ; send a break packet 20$: rpack r2 ,r3 ,#recpkt,#maxpak ; /62/ read the response scan r1 ,#200$ ; and dispatch based on it asl r0 ; word indexing jsr pc ,@210$(r0) tst datauk ; /62/ need to re-read w/o re-sending? bne 20$ ; /62/ ya return ; /62/ no, carry cleared by above tst .save .psect $pdata 200$: .byte msg$err ,msg$nak,msg$ack,timout ,badchk .byte 0 .even 210$: .word sndx.$ ; /62/ .word sndx.e ,sbrk.n ,sbrk.y ,sndx$$ ,sndx.$ ; /62/ badchk = noise .restore .dsabl lsb .sbttl Process response to SBREAK .enabl lsb ; /62/ sbrk$$: jmp sndx$$ ; /62/ common code sbrk.n: cmp r3 ,paknum ; /62/ is NAK for this packet? beq sbrk$$ ; /62/ ya, resend the data dec r3 ; NAK for next packet bge 1$ ; is ACK for current packet mov #63. ,r3 ; if --paknum<0, 63:paknum 1$: cmp r3 ,paknum ; well? beq 10$ ; /62/ it's an implicit ACK br 2$ ; /62/ out of sync, try to fix things sbrk.y: cmp r3 ,paknum ; ensure ACK is for correct packet beq 10$ ; it is 2$: cmp numtry ,maxtry ; /62/ it isn't, been here too often? blos 3$ ; /62/ not yet jmp s$sync ; /62/ ya, say so, send error packet 3$: tst datauk ; /62/ already tossed one bad ACK/NAK? blt sbrk$$ ; /62/ ya, re-send packet jmp bad$ack ; /62/ listen again, but just once 10$: clr datauk ; /62/ stop read_only loop clr numtry ; ACK for this packet incm64 paknum ; paknum := (paknum+1) mod 64 movb #sta.com,r1 ; return(complete) return .dsabl lsb ; /62/ .sbttl Send file init .enabl lsb sinit: movb #msg$snd,-(sp) ; normal sinit operation call .sinit ; for sending files return .sinit::clr datauk ; /62/ init re-read only flag inc numtry ; /62/ moved this test here.. cmp numtry ,initry ; abort if we've been trying too much blos 10$ ; no, keep it up call s$retry ; /62/ yes, return(abort) br 101$ ; /62/ go pop init type off the stack 10$: mov chktyp ,-(sp) ; save checksum type (not needed) mov chksiz ,-(sp) ; and size (also not needed) movb #defchk ,chktyp ; force type one please mov #1 ,chksiz ; length of it calls spar ,<#packet> ; get our send parameters call cantyp ; flush pending input please movb 6(sp) ,r5 ; packet type to do today spack r5,paknum,sparsz,#packet ; send our init info now 20$: rpack r2 ,r3 ,#recpkt,#maxpak ; /62/ and get the other's response scan r1 ,#200$ ; and dispatch to the correct asl r0 ; routine now jsr pc ,@210$(r0) tst datauk ; /62/ need to re-read w/o re-sending? bne 20$ ; /62/ ya note above tst clears carry mov (sp)+ ,chksiz ; restore checksum size mov (sp)+ ,chktyp ; restore checksum type 101$: mov (sp)+ ,@sp ; dump passed packet type now return .save .psect $pdata 200$: .byte msg$err ,msg$nak,msg$ack,timout ,badchk .byte 0 .even 210$: .word sndx.$ ; /62/ .word sini.e ,sini.n ,sini.y ,sndx$$ ,sndx.$ ; /62/ badchk = noise .restore .dsabl lsb .sbttl Process response to SINIT .enabl lsb ; /62/ sini.$: jmp sndx.$ ; /62/ common sini$$: jmp sndx$$ ; /62/ code sini.e: calls prerrp ,<#recpkt> ; /62/ print error message cmpb r5 ,#msg$ser ; if called from sinfo.. beq 33$ ; /62/ ..ignore errors jmp sabort ; /62/ return(abort) sini.n: cmp r3 ,paknum ; /62/ is NAK for this packet? bne sini.$ ; /62/ no, try just listening again cmpb r5 ,#msg$ser ; server NAK for "I" (sinfo) packet? bne 101$ ; /62/ no cmp numtry ,#2 ; gotten at least one NAK for "I" ? bhis 33$ ; /62/ ya, move to file state 101$: br sini$$ ; /62/ no, loop another time sini.y: cmp r3 ,paknum ; got an ACK for sinit beq 10$ ; and the ACK is for correct packet cmp numtry ,initry ; /62/ it isn't, been here too often? blos 3$ ; /62/ not yet jmp s$sync ; /62/ ya, say so, send error packet 3$: tst datauk ; /62/ already tossed one bad ACK/NAK? blt sini$$ ; /62/ ya, re-send packet jmp bad$ack ; /62/ listen again, but just once 10$: calls rpar ,<#recpkt,r2> ; load the other's parameters now 33$: clr datauk ; /62/ stop read_only loop clr numtry ; number_of_tries := 0 incm64 paknum ; pack_number := pack_number+1 mod 64 movb #sta.fil,r1 ; return(file) jmp inirepeat ; /62/ initialize repeat processing .dsabl lsb ; /62/ .sbttl Send a file .enabl lsb sfile: clr datauk ; /62/ init re-read only flag inc numtry ; /62/ moved this test here.. cmp numtry ,maxtry ; abort if we've been trying too much blos 10$ ; no, keep it up jmp s$retry ; /62/ handle the error please 10$: movb conpar+p.chkt,chktyp ; switch to new checksum type movb chktyp ,chksiz ; compute the checksum size also sub #'0 ,chksiz ; simple mov $image ,image ; ensure correct default for mode mov #filnam ,r3 ; and point to it please clr skipfl ; the user skipped the rest of a file call clratr ; ensure attribute stuff is cleared call inirepeat ; must reset ptrs for repeat counts sub #100 ,sp ; and a converted file name buffer mov sp ,r4 ; and point to it please tst inopn ; open files hanging around? beq 20$ ; no calls close ,<#lun.in> ; yes, clean up please clr inopn ; it's closed now 20$: tstb filnam ; /38/ a REAL file today? bne 21$ ; /38/ ya.. jmp 45$ ; /38/ no, must be an extended reply 21$: tst doauto ; see if we should check for binary beq 25$ ; no, don't do it please tst image ; /56/ bne 25$ ; /56/ calls chkext ,<#filnam> ; should we force binary mode? tst r0 ; if gt, then yes ble 25$ ; no mov #binary ,image ; yes, force binary file operations 25$: calls open ,<#filnam,#lun.in,image> ; open the file for input tst r0 ; did it work? beq 30$ ; yes calls syserr , ; no calls error ,<#3,#errtxt,#aspace,#filnam> ; /BBS/ add space here movb #sta.abo,r1 ; return(abort) br 100$ ; go dump local buffer and exit 30$: mov sp ,inopn ; file is open tst xmode ; is this a server X-tended reply? bne 45$ ; yes, send a simple "X" packet calls namcvt ,<#filnam,r4> ; convert name to simple name tstb asname ; /36/ check for alternate name? beq 35$ ; /36/ no mov #asname ,r4 ; /36/ yes, point to that name 35$: calls printm ,<#4,#SF1$,#filnam,#SF2$,r4> ; /62/ say what's up.. strlen r4 ; and get the file name length spack #msg$fil,paknum,r0,r4 ; set the file name packet over clrb asname ; /36/ ensure one shot only br 50$ 45$: spack #msg$tex,paknum ; server extended reply here, send "X" 50$: rpack r2 ,r3 ,#recpkt,#maxpak ; /62/ get response to the file name scan r1 ,#200$ ; and dispatch on the response asl r0 ; word indexing jsr pc ,@210$(r0) ; and call the appropriate response tst datauk ; /62/ need to re-read w/o re-sending? bne 50$ ; /62/ ya 100$: add #100 ,sp ; dump local buffer, also clears carry return .save .psect $pdata 200$: .byte msg$err ,msg$nak,msg$ack,timout ,badchk .byte 0 .even 210$: .word sndx.$ ; /62/ .word sndx.e ,sfil.n ,sfil.y ,sndx$$ ,sndx.$ ; /62/ badchk = noise .restore .dsabl lsb .sbttl Process response to SFILE .enabl lsb ; /62/ sfil$$: jmp sndx$$ ; /62/ common code sfil.n: cmp r3 ,paknum ; /62/ is NAK for this packet? beq sfil$$ ; /62/ ya, resend the data dec r3 ; NAK for next packet bge 1$ ; is ACK for current packet mov #63. ,r3 ; if --paknum<0, 63:paknum 1$: cmp r3 ,paknum ; well? beq 10$ ; /62/ it's an implicit ACK br 2$ ; /62/ out of sync, try to fix things sfil.y: cmp r3 ,paknum ; ensure ACK is for correct packet beq 10$ ; it is 2$: cmp numtry ,maxtry ; /62/ it isn't, been here too often? blos 3$ ; /62/ not yet jmp s$sync ; /62/ ya, say so, send error packet 3$: tst datauk ; /62/ already tossed one bad ACK/NAK? blt sfil$$ ; /62/ ya, re-send packet jmp bad$ack ; /62/ listen again, but just once 10$: clr datauk ; /62/ stop read_only loop clr numtry ; number_of_tries := 0 incm64 paknum ; packnumber := packnumber+1 mod 64 movb #sta.atr,r1 ; assume return(attribute) tst xmode ; /38/ is this an extended reply? beq 20$ ; /38/ no, attributes are next calls buffil ,<#packet> ; /38/ ya, get first buffer of data mov r1 ,size ; /38/ and save it movb #sta.dat,r1 ; /38/ skip attributes, return(data) 20$: return .dsabl lsb .sbttl Send file data .enabl lsb sdata: clr datauk ; /62/ init re-read only flag inc numtry ; abort if we've been trying too much cmp numtry ,maxtry ; well? blos 10$ ; no, keep it up jmp s$retry ; /62/ flag the error type please 10$: spack #msg$dat,paknum,size,#packet ; send the next record please 20$: rpack r2 ,r3 ,#recpkt,#maxpak ; /62/ get the reply scan r1 ,#200$ ; look for type in list of responses asl r0 ; word indexing jsr pc ,@210$(r0) ; dispatch based on the packet type tst datauk ; /62/ need to re-read w/o re-sending? bne 20$ ; /62/ ya return ; /62/ no, carry cleared by above tst .save .psect $pdata 200$: .byte msg$err ,msg$nak,msg$ack,timout ,badchk .byte 0 .even 210$: .word sndx.$ ; /62/ .word sndx.e ,sdat.n ,sdat.y ,sdat$$ ,sndx.$ ; /62/ badchk = noise .restore .dsabl lsb .sbttl Process response to SDATA sdat$$: tst dpnumber ; /43/ first data packet? bne 100$ ; /43/ no cmp senlng ,#maxpak ; /43/ long packet gotten TOO small? blos 100$ ; /43/ ya asr senlng ; /43/ no, reduce packet size mov senlng ,r0 ; /BBS/ pass new length to L10012 mov #spare1 ,r1 ; /BBS/ where to write ascii digits call L10012 ; /BBS/ convert r0 to decimal number clrb @r1 ; /BBS/ null terminate the string calls printm ,<#3,#adpmsg,#spare1,#adptag> ; /BBS/ inform the user 100$: jmp sndx$$ ; /62/ keep current state, try again .enabl lsb sdat.n: cmp r3 ,paknum ; /62/ is NAK for this packet? beq sdat$$ ; /62/ ya, resend the data dec r3 ; NAK for next packet bge 1$ ; is ACK for current packet mov #63. ,r3 ; if --paknum<0, 63:paknum 1$: cmp r3 ,paknum ; well? beq 10$ ; /62/ it's an implicit ACK br 2$ ; /62/ out of sync, try to fix things sdat.y: cmp r3 ,paknum ; ensure ACK is for correct packet beq 10$ ; it is 2$: cmp numtry ,maxtry ; /62/ it isn't, been here too often? blos 3$ ; /62/ not yet jmp s$sync ; /62/ ya, say so, send error packet 3$: tst datauk ; /62/ already tossed one bad ACK/NAK? blt sdat$$ ; /62/ ya, re-send packet jmp bad$ack ; /62/ listen again, but just once 10$: clr datauk ; /62/ stop read_only loop add #1 ,dpnumber ; /43/ datapacket_number++ bcc 15$ ; /43/ mov #1 ,dpnumber ; /43/ avoid overflow 15$: clr numtry ; retry_counter = 0 incm64 paknum ; paknum = paknum++ mod 64 tst remote ; is this a remote system? bne 40$ ; yes, forget about checking tst cccnt ; ^C pending? bne 30$ ; yes, always send an error packet call chkabo ; now check for ^A, ^E, ^X or ^Z cmpb r0 ,#'A&37 ; /56/ ^A stats? bne 16$ ; /56/ no call cs$out ; /56/ yes, dump char counts br 40$ ; /56/ and finish up 16$: cmpb r0 ,#abt$err&37 ; /56/ if ^E beq 30$ ; /56/ then send error packet cmpb r0 ,#abt$cur&37 ; if ^X beq 20$ ; then abort current file cmpb r0 ,#abt$all&37 ; if ^Z bne 40$ ; then abort file group mov #-1 ,index ; flag that we are all done 20$: mov #sta.eof,r1 ; force new state to EOF mov sp ,skipfl ; get seof to set discard return 30$: spack #msg$err,paknum ; send an error packet clr cccnt ; /36/ clear ^C flag jmp sabort ; /62/ force state to abort 40$: cmpb recpkt ,#abt$cur ; ACK contain a "X" for skipfile? bne 41$ ; /BBS/ no calls printm ,<#2,#SD25$,#SD27$> ; /62/ ya, say so if not remote br 80$ ; /BBS/ then fake EOF 41$: cmpb recpkt ,#abt$all ; ACK contain a "Z" for skip all? bne 90$ ; no calls printm ,<#2,#SD26$,#SD27$> ; /62/ ya, say so if not remote mov #-1 ,index ; flag a fake no more files and 80$: movb #sta.eof,r1 ; fake EOF for either "X" or "Z" ACK return 90$: add size ,charout+2 ; /43/ keep track of counts adc charout+0 ; /43/ 32. bits please calls buffil ,<#packet> ; get the next buffer of data to send mov r1 ,size ; and save the size please bne 100$ ; something was there movb #sta.eof,r1 ; set state to EOF return 100$: movb #sta.dat,r1 ; not EOF, stay in data state return .dsabl lsb .sbttl Send end of file packet .enabl lsb seof: clr datauk ; /62/ init re-read only flag inc numtry ; abort if we've been trying too much cmp numtry ,maxtry ; well? blos 10$ ; no, keep it up jmp s$retry ; /62/ handle the error please 10$: tst skipfl ; skipping the rest of a file? beq 20$ ; no spack #msg$eof,paknum,#1,#SE22$ ; /62/ yes, send "D" in data field br 30$ 20$: spack #msg$eof,paknum ; send an EOF packet out now 30$: rpack r2 ,r3 ,#recpkt,#maxpak ; /62/ get the reply please scan r1 ,#200$ ; and take action on the reply asl r0 ; word indexing jsr pc ,@210$(r0) ; dispatch based on the packet type tst datauk ; /62/ need to re-read w/o re-sending? bne 30$ ; /62/ ya clr skipfl ; clear skipfile flg, also clear carry return .save .psect $pdata 200$: .byte msg$err ,msg$nak,msg$ack,timout ,badchk .byte 0 .even 210$: .word sndx.$ ; /62/ .word sndx.e ,seof.n ,seof.y ,sndx$$ ,sndx.$ ; /62/ badchk = noise .restore .dsabl lsb .sbttl Process response to SEOF .enabl lsb ; /62/ seof$$: jmp sndx$$ ; /62/ common code seof.n: cmp r3 ,paknum ; /62/ is NAK for this packet? beq seof$$ ; /62/ ya, resend the data dec r3 ; NAK for next packet bge 1$ ; is ACK for current packet mov #63. ,r3 ; if --paknum<0, 63:paknum 1$: cmp r3 ,paknum ; well? beq 10$ ; /62/ it's an implicit ACK br 2$ ; /62/ out of sync, try to fix things seof.y: cmp r3 ,paknum ; ensure ACK is for correct packet beq 10$ ; it is 2$: cmp numtry ,maxtry ; /62/ it isn't, been here too often? blos 3$ ; /62/ not yet jmp s$sync ; /62/ ya, say so, send error packet 3$: tst datauk ; /62/ already tossed one bad ACK/NAK? blt seof$$ ; /62/ ya, re-send packet jmp bad$ack ; /62/ listen again, but just once 10$: clr datauk ; /62/ stop read_only loop clr numtry ; clear the retry count incm64 paknum ; paknum := (paknum+1) mod 64 calls close ,<#lun.in> ; close the input file clr inopn ; input file is now closed cmp index ,#-1 ; force a break here from user beq 20$ ; yes clr r0 ; /38/ no errors tst xmode ; /38/ extended response? bne 20$ ; /38/ finish up the transaction call getnxt ; get the next input file? tst r0 ; did it work? bne 20$ ; no movb #sta.fil,r1 ; yes, set new state to file return 20$: movb #sta.brk,r1 ; return(break) return .dsabl lsb ; /62/ .end