.title KRTSEN Send file processing .ident "V04.64" ; /E64/ 28-Apr-96 John Santos ; ; Conditionalize for RSTS/E ; Note: doesn't handle large files!! ; If we resize the buffer and re-open the input file in sdat$$, close ; it first. Check for errors and abort if re-open fails. ; /63/ 8-Feb-96 Billy Youdelman ; ; display file size and type in "sending file" messages ; display contents of SEND FILE ACK packet, if any.. ; redo data packet at sdat$$ when resizing due to first one failing ; so the next retry is actually done with the smaller sized packet ; /62/ 27-Jul-93 Billy Youdelman V03.62 ; ; 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> .if df RT11 ; /E64/ .mcall .PURGE ; /62/ to hose dir search ch on err .endc ;RT11 ; /E64/ .sbttl Local data .psect $pdata ; /62/ consolidated this stuff here.. fillst: .word 10$ ,20$ ,30$ ; /63/ 10$: .asciz "ASCII (7-bit)" ; /63/ 20$: .asciz "BINARY (8-bit)" ; /63/ 30$: .asciz "DEC-Multinational" ; /63/ 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" ; /63/ badtag: .asciz ", paknum: " sen.01: .asciz "SEN.SW" sen.02: .asciz "Warning: Parity found in SOH byte" sen.03: .asciz "Remote ACK: " ; /63/ sen.04: .asciz "ABORT$CURRENT-FILE" sen.05: .asciz "ABORT$ALL-FILES" sen.06: .byte eof$dis ,0 sen.07: .asciz "Sending file " sen.08: .asciz " as " ; /63/ sen.09: .asciz " 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 sensw:: 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 10$ ; yep cmpb senpar+p.chkt,#'1 ; simple block checks today? beq 20$ ; yes, assume caller's state is ok 10$: movb #sta.sin,state ; no, must force a sinit exchange 20$: clr logini ; /62/ force display stats header call inista ; /63/ init packet count stats clr dpnumber ; /43/ clear data packet count movb sentim ,senpar+p.time ; /62/ load send time-out value 30$: call sendeb ; do send debugging if enabled call senlog ; /62/ update transfer stats display cmp incpar ,#1 ; /62/ is it possible that parity bne 40$ ; /62/ is messed up? calls printm ,<#1,#sen.02> ; /62/ warn, but only once inc incpar ; /62/ be sure it is only once! 40$: tst remote ; /43/ if remote, bne 50$ ; /43/ ignore random noise tst cccnt ; /36/ ^C abort? beq 50$ ; /36/ no movb #sta.cca,state ; /36/ ya, fake abort 50$: scan state ,#70$ ; now dispatch asl r0 ; based on current jsr pc ,@80$(r0) ; state movb r1 ,state ; set a new state bcc 30$ ; 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 60$ ; no calls close ,<#lun.in> ; ya, ensure that it's closed clr inopn ; /BBS/ say so.. 60$: .if df RT11 ; /E64/ .purge #lun.sr ; /62/ close dir search channel .endc ;RT11 ; /E64/ call incsta ; /43/ increment timer stats unsave ; pop exit status code please return .save .psect $pdata 70$: .byte sta.abo ,sta.brk,sta.com,sta.dat,sta.fil,sta.atr,sta.sin .byte sta.eof ,sta.cca .byte 0 .even 80$: .word send.$ .word send$$ ,sbreak ,send.c ,sdata ,sfile ,sattr ,sinit ; /62/ .word seof ,ccabort .restore .dsabl lsb .sbttl State routines for SENSW .enabl lsb ; /62/ send.$: call bad$pak ; /62/ report ignoring bad packet type movb state ,r1 ; /62/ stay in same state clc ; keep sensw 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 10$ send.c: clr r0 ; complete 10$: sec ; exit sensw 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 30$ ; nope save sub #100. ,sp ; allocate a small buffer mov sp ,r1 ; point to it mov #sen.01 ,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 10$ ; if trace is on then calls putrec , ; dump it tst r0 ; did it work? beq 10$ ; ya call logerr ; no, handle the error 10$: tst remote ; is there a TT to do this? bne 20$ ; not right now.. bit #log$de ,trace ; terminal debugging on? beq 20$ ; no wrtall r2 ; ya, print it .newline 20$: add #100. ,sp ; deallocate the buffer unsave 30$: return .sbttl Send attribute data for the current file .enabl lsb ; /BBS/ Modified to (w/KRTATR.MAC) send all attributes in a single packet ; /E64/ Change this back to send multiple attributes packets if ; /E64/ more than 94 bytes of attributes. 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 30$ ; no calls w$attr ,<#lun.in,#packet> ; build the attributes packet tst r0 ; any errors along the way? bne 30$ ; yes tst r1 ; anything to send over? beq 30$ ; 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 ,#50$ ; and take action on the reply asl r0 ; dispatch based on the packet type jsr pc ,@60$(r0) ; simple tst datauk ; /62/ need to re-read w/o re-sending? bne 20$ ; /62/ ya br 40$ ; /62/ no 30$: calls buffil ,<#0,#packet> ; /63/ get the first buffer of data mov r1 ,size ; and save it movb #sta.dat,r1 ; switch to data state 40$: clc ; /62/ keep sensw running return .save .psect $pdata 50$: .byte msg$err ,msg$nak,msg$ack,timout ,badchk .byte 0 .even 60$: .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 10$ ; is ACK for current packet mov #63. ,r3 ; if --paknum<0, 63:paknum 10$: cmp r3 ,paknum ; well? beq 40$ ; /62/ it's an implicit ACK br 20$ ; /62/ out of sync, try to fix things satr.y: cmp r3 ,paknum ; ensure ACK is for correct packet beq 40$ ; it is 20$: cmp numtry ,maxtry ; /62/ it isn't, been here too often? blos 30$ ; /62/ not yet jmp s$sync ; /62/ ya, say so, send error packet 30$: 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 40$: clr datauk ; /62/ stop read_only loop clr numtry ; retrycount := 0 incm64 paknum ; paknum := (paknum+1) mod 64 .if df RSTS ; /E64/ mov atrctx ,atrsnt ; /E64/ count attributes sent calls w$attr ,<#lun.in,#packet> ; build the attributes packet tst r0 ; any errors along the way? bne 50$ ; yes tst r1 ; anything to send over? beq 50$ ; no movb #sta.atr,r1 ; stay in attribute state return ; send next attr packet .endc ;RSTS ; /E64/ 50$: calls buffil ,<#0,#packet> ; /63/ 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 ,#30$ ; and dispatch based on it asl r0 ; word indexing jsr pc ,@40$(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 30$: .byte msg$err ,msg$nak,msg$ack,timout ,badchk .byte 0 .even 40$: .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 10$ ; is ACK for current packet mov #63. ,r3 ; if --paknum<0, 63:paknum 10$: cmp r3 ,paknum ; well? beq 40$ ; /62/ it's an implicit ACK br 20$ ; /62/ out of sync, try to fix things sbrk.y: cmp r3 ,paknum ; ensure ACK is for correct packet beq 40$ ; it is 20$: cmp numtry ,maxtry ; /62/ it isn't, been here too often? blos 30$ ; /62/ not yet jmp s$sync ; /62/ ya, say so, send error packet 30$: 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 40$: 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 30$ ; /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 ,#40$ ; and dispatch to the correct asl r0 ; routine now jsr pc ,@50$(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 30$: mov (sp)+ ,@sp ; dump passed packet type now return .save .psect $pdata 40$: .byte msg$err ,msg$nak,msg$ack,timout ,badchk .byte 0 .even 50$: .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 40$ ; /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 10$ ; /62/ no cmp numtry ,#2 ; gotten at least one NAK for "I" ? bhis 40$ ; /62/ ya, move to file state 10$: br sini$$ ; /62/ no, loop another time sini.y: cmp r3 ,paknum ; got an ACK for sinit beq 30$ ; and the ACK is for correct packet cmp numtry ,initry ; /62/ it isn't, been here too often? blos 20$ ; /62/ not yet jmp s$sync ; /62/ ya, say so, send error packet 20$: 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 30$: calls rpar ,<#recpkt,r2> ; load the other's parameters now 40$: 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 #ln$max+2,sp ; /63/ 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 30$ ; /38/ ya.. jmp 70$ ; /38/ no, must be an extended reply 30$: tst doauto ; see if we should check for binary beq 40$ ; no, don't do it please tst image ; /56/ bne 40$ ; /56/ calls chkext ,<#filnam> ; should we force binary mode? tst r0 ; if gt, then yes ble 40$ ; no mov #binary ,image ; yes, force binary file operations 40$: calls open ,<#filnam,#lun.in,image> ; open the file for input tst r0 ; did it work? beq 50$ ; yes calls syserr , ; no calls error ,<#3,#errtxt,#aspace,#filnam> ; /BBS/ add space here movb #sta.abo,r1 ; return(abort) br 90$ ; go dump local buffer and exit 50$: mov sp ,inopn ; file is open tst xmode ; is this a server X-tended reply? bne 70$ ; yes, send a simple "X" packet calls namcvt ,<#filnam,r4> ; convert to simple name (strip dev:) tstb asname ; /36/ check for alternate name? beq 60$ ; /36/ no mov #asname ,r4 ; /36/ yes, point to that name 60$: movb #'[ ,errtxt ; /63/ a leading bracket mov #lun.in ,r0 ; /63/ the LUN in use here asl r0 ; /63/ word indexing ; /E64/ NOTE: this doesn't handle large files!! mov sizof(r0),r0 ; /63/ recover the file size mov #errtxt+1,r1 ; /63/ start writing size here call L10012 ; /63/ convert size to ascii movb #'] ,(r1)+ ; /63/ a terminating bracket clrb (r1) ; /63/ terminate the size string mov image ,r1 ; /63/ recover current file-type asl r1 ; /63/ word indexing mov fillst(r1),r1 ; /63/ point to its description calls printm ,<#7,#sen.07,#filnam,#errtxt,#sen.08,r1,#sen.09,r4> 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 80$ 70$: spack #msg$tex,paknum ; server extended reply here, send "X" 80$: rpack r2 ,r3 ,#recpkt,#maxpak ; /62/ get response to the file name scan r1 ,#100$ ; and dispatch on the response asl r0 ; word indexing jsr pc ,@110$(r0) ; and call the appropriate response tst datauk ; /62/ need to re-read w/o re-sending? bne 80$ ; /62/ ya 90$: add #ln$max+2,sp ; /63/ dump local buff, clears carry return .save .psect $pdata 100$: .byte msg$err ,msg$nak,msg$ack,timout ,badchk .byte 0 .even 110$: .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 10$ ; is ACK for current packet mov #63. ,r3 ; if --paknum<0, 63:paknum 10$: cmp r3 ,paknum ; well? beq 40$ ; /62/ it's an implicit ACK br 20$ ; /62/ out of sync, try to fix things sfil.y: cmp r3 ,paknum ; ensure ACK is for correct packet beq 40$ ; it is 20$: cmp numtry ,maxtry ; /62/ it isn't, been here too often? blos 30$ ; /62/ not yet jmp s$sync ; /62/ ya, say so, send error packet 30$: 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 40$: tstb recpkt ; /63/ anything in received packet? beq 50$ ; /63/ no calls printm ,<#2,#sen.03,#recpkt> ; /63/ ya, print the packet 50$: clr datauk ; /62/ stop read_only loop clr numtry ; number_of_tries := 0 incm64 paknum ; packnumber := packnumber+1 mod 64 .if df RSTS ; /E64/ clr atrsnt ; /E64/ we haven't sent any attrs yet .endc ;RSTS ; /E64/ movb #sta.atr,r1 ; assume return(attribute) tst xmode ; /38/ is this an extended reply? beq 60$ ; /38/ no, attributes are next calls buffil ,<#0,#packet> ; /63/ ya, get first buffer of data mov r1 ,size ; /38/ and save it movb #sta.dat,r1 ; /38/ skip attributes, return(data) 60$: 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 ,#30$ ; look for type in list of responses asl r0 ; word indexing jsr pc ,@40$(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 30$: .byte msg$err ,msg$nak,msg$ack,timout ,badchk .byte 0 .even 40$: .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 10$ ; /43/ no cmp senlng ,#maxpak ; /43/ long packet gotten TOO small? blos 10$ ; /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 ;/E64/ This next, commented-out section closes and re-opens the ; input file to reset our send pointer. We are going to try ; rewinding it, instead. ; calls close ,<#lun.in> ; /E64/ clean up please ; clr inopn ; /E64/ it's closed now ; calls open ,<#filnam,#lun.in,image> ; /63/ back to top of file ; tst r0 ; /E64/ did it work? ; beq 50$ ; /E64/ yes ; calls syserr , ; /E64/ no ; calls error ,<#3,#errtxt,#aspace,#filnam> ; /E64/ add space here ; jmp sabort ; /E64/ whoops!! ; ;50$: mov sp ,inopn ; file is open calls rewind ,<#lun.in> ; /E64/ rewind please clr fileout+0 ; /63/ no chars sent yet clr fileout+2 ; /63/ this too just to be sure.. call inirepeat ; /E64/ must reset repeat count ptrs calls buffil ,<#0,#packet> ; /63/ redo the re-sized packet mov r1 ,size ; /63/ and save it's new length here 10$: 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 10$ ; is ACK for current packet mov #63. ,r3 ; if --paknum<0, 63:paknum 10$: cmp r3 ,paknum ; well? beq 40$ ; /62/ it's an implicit ACK br 20$ ; /62/ out of sync, try to fix things sdat.y: cmp r3 ,paknum ; ensure ACK is for correct packet beq 40$ ; it is 20$: cmp numtry ,maxtry ; /62/ it isn't, been here too often? blos 30$ ; /62/ not yet jmp s$sync ; /62/ ya, say so, send error packet 30$: 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 40$: clr datauk ; /62/ stop read_only loop add #1 ,dpnumber ; /43/ datapacket_number++ bcc 50$ ; /43/ mov #1 ,dpnumber ; /43/ avoid overflow 50$: clr numtry ; retry_counter = 0 incm64 paknum ; paknum = paknum++ mod 64 tst remote ; is this a remote system? bne 90$ ; yes, forget about checking tst cccnt ; ^C pending? bne 80$ ; yes, always send an error packet call chkabo ; now check for ^A, ^E, ^X or ^Z cmpb r0 ,#'A&37 ; /56/ ^A stats? bne 60$ ; /56/ no call cs$out ; /56/ yes, dump char counts br 90$ ; /56/ and finish up 60$: cmpb r0 ,#abt$err&37 ; /56/ if ^E beq 80$ ; /56/ then send error packet cmpb r0 ,#abt$cur&37 ; if ^X beq 70$ ; then abort current file cmpb r0 ,#abt$all&37 ; if ^Z bne 90$ ; then abort file group mov #-1 ,index ; flag that we are all done 70$: mov #sta.eof,r1 ; force new state to EOF mov sp ,skipfl ; get seof to set discard return 80$: spack #msg$err,paknum ; send an error packet clr cccnt ; /36/ clear ^C flag jmp sabort ; /62/ force state to abort 90$: cmpb recpkt ,#abt$cur ; ACK contain a "X" for skipfile? bne 100$ ; /BBS/ no calls printm ,<#2,#sen.03,#sen.04> ; /63/ ya, say so if not remote br 110$ ; /BBS/ then fake EOF 100$: cmpb recpkt ,#abt$all ; ACK contain a "Z" for skip all? bne 120$ ; no calls printm ,<#2,#sen.03,#sen.05> ; /63/ ya, say so if not remote mov #-1 ,index ; flag a fake no more files and 110$: movb #sta.eof,r1 ; fake EOF for either "X" or "Z" ACK return 120$: add size ,charout+2 ; /43/ keep track of counts adc charout+0 ; /43/ 32. bits please calls buffil ,<#0,#packet> ; /63/ get next buffer of data to send mov r1 ,size ; and save the size please bne 130$ ; something was there movb #sta.eof,r1 ; set state to EOF return 130$: 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,#sen.06 ; /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 ,#40$ ; and take action on the reply asl r0 ; word indexing jsr pc ,@50$(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 40$: .byte msg$err ,msg$nak,msg$ack,timout ,badchk .byte 0 .even 50$: .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 10$ ; is ACK for current packet mov #63. ,r3 ; if --paknum<0, 63:paknum 10$: cmp r3 ,paknum ; well? beq 40$ ; /62/ it's an implicit ACK br 20$ ; /62/ out of sync, try to fix things seof.y: cmp r3 ,paknum ; ensure ACK is for correct packet beq 40$ ; it is 20$: cmp numtry ,maxtry ; /62/ it isn't, been here too often? blos 30$ ; /62/ not yet jmp s$sync ; /62/ ya, say so, send error packet 30$: 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 40$: 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 50$ ; yes clr r0 ; /38/ no errors tst xmode ; /38/ extended response? bne 50$ ; /38/ finish up the transaction call getnxt ; get the next input file? tst r0 ; did it work? bne 50$ ; no movb #sta.fil,r1 ; yes, set new state to file return 50$: movb #sta.brk,r1 ; return(break) return .dsabl lsb ; /62/ .end