.title k11sen send processing .ident /T2.23/ .include /IN:K11MAC.MAC/ .include /IN:K11DEF.MAC/ .psect .enabl gbl ; 13-Oct-84 14:04:37 Brian Nelson ; ; Creation: moved from K11PAK.MAC ; ; ; Copyright (C) 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. ; ; .sbttl send processing .enabl lsb sen.sw:: sendsw::movb @r5 ,state ; do a SINIT first thing please movb #defchk ,chktyp ; setup the default checksum type mov #1 ,chksiz ; the dize of the checksum mov $image ,image ; insure correct default for mode clr paknum ; packetnumber := 0 clr numtry ; retry_count := 0 clr oldtry ; oldretry_count := 0 add pcnt.s+0,sencnt ; save sent packet count call clrsta ; clear the stats out now cmpb conpar+p.chkt,#'1 ; did the 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$: tst remote ; local kermit today? bne 6$ ; no call ttrini ; yes, init for console aborts then 6$: call senhdr ; packet count header initialization 10$: call sendeb scan state,#200$ ; now dispatch based on current asl r0 ; state jsr pc ,@210$(r0) ; and do it again movb r1 ,state ; set a new state bcc 10$ ; ok 100$: movb #defchk ,chktyp ; reset the checksum type mov #1 ,chksiz ; the size of the checksum save ; insure files are closed tst remote ; do we need to drop console aborts? bne 105$ ; no call ttrfin ; yes, drop them 105$: tst inopn ; file open from a failure ? beq 110$ ; no calls close ,<#lun.in> ; insure that it's closed 110$: unsave ; pop exit status code please return ; bye 200$: .byte STA.ABO ,STA.BRK,STA.COM,STA.DAT,STA.FIL,STA.SIN,STA.EOF .byte STA.ATR .byte 0 .even 210$: .word send.$ .word send.a ,send.b ,send.c ,send.d ,send.f ,send.s ,send.z .word send.h .dsabl lsb global global global .sbttl STATE routines for SENDSW send.a: send.$: mov #-1 ,r0 movb #STA.ABO,r1 ; return ("ABORT") sec ; unknown state, abort return send.b: call sbreak ; send a break to the other system clc ; and continue return send.c: clr r0 ; Complete sec ; exit return send.d: call sdata ; send data now clc ; assume all is well return ; bye send.f: call sfile ; send a file header clc ; assume it went well return send.h: call sattr clc return send.s: call sinit ; initialize clc return send.z: call seof ; end of file clc return sendeb: bit #log$st ,trace ; debugging for SENDSW beq 30$ ; if trace is on then dump the sub #50 ,sp ; current state to the disk file mov sp ,r1 ; allocate a small buffer mov #200$ ,r2 ; point to a header 10$: movb (r2)+ ,(r1)+ ; copy a header please bne 10$ ; until we find a null dec r1 ; all done movb state ,(r1)+ ; copy the current state over movb #40 ,(r1)+ ; sub sp ,r1 ; get the record length mov sp ,r0 ; and point back to the record calls putrec ,; dump it add #50 ,sp ; and deallocate the buffer 30$: tst debug ; terminal debugging on ? beq 40$ ; no .print #200$ ; yes, dump current state to ti: .print #state ,#1 ; .newli ; and a crlf 40$: call senlog ; packet stats 100$: return 200$: .asciz /Sendsw - state is / .even global .sbttl sattr send attribute data for the current file sattr: inc numtry ; abort if we have been trying too much cmp numtry ,maxtry ; well ? blos 10$ ; no, keep it up movb #STA.ABO,r1 ; yes, return("ABORT") br 100$ ; exit 10$: tst sendat ; really do this ? beq 90$ ; no mov atrctx ,r5 ; save ctx in case of timeout or nak calls w$attr ,<#filnam,#lun.in,#packet> ; get the next attr 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 the next record out please rpack r2,r3,#recpkt ; 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 br 100$ ; bye 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 if no more attr 100$: return ; bye 200$: .byte MSG$ERROR,MSG$NAK,MSG$ACK,TIMOUT,BADCHK,0 .even 210$: .word satr.$ .word satr.e ,satr.n ,satr.y ,satr$$ ,satr$$ .sbttl handle the response to the packet sent by SATTR satr.$: movb #STA.ABO,r1 ; unrecognized packet type return satr$$: movb state ,r1 ; timeout, stay in current state mov r5 ,atrctx ; we want the same packet next time return ; and exit satr.e: calls prerrp ,<#recpkt> ; print out received error packet movb #STA.ABO,r1 ; abort return ; and exit satr.n: dec r3 ; a NAK, see if it's for the last bge 10$ ; packet mov #63. ,r3 ; --paknum<0 ? 63:paknum 10$: cmp r3 ,paknum ; same one ? beq 20$ ; yes movb state ,r1 ; no, continue on as before then mov r5 ,atrctx ; also restore context please return ; bye 20$: call satr.y ; same packet, goto ACK code return satr.y: cmp r3 ,paknum ; insure ACK is for correct packet beq 10$ ; yes movb state ,r1 ; no, continue in current state return 10$: clr numtry ; retrycount := 0 incm64 paknum ; paknum := (paknum+1) mod 64 movb #STA.ATR,r1 ; not eof, stay in ATTRIBUTE state return ; return("ATTRIBUTE") global .sbttl sbreak send a break sbreak: inc numtry ; ABORT if retry count is too high cmp numtry ,maxtry ; well ? blos 10$ ; ok movb #STA.ABO,r1 ; no, abort the sending of this br 100$ 10$: spack #MSG$BREAK,paknum,#0,#packet ; send a break packet rpack r2,r3,#recpkt ; read the response scan r1,#200$ ; and dispatch based on it asl r0 ; offset times two jsr pc ,@210$(r0) ; simple 100$: clc return 200$: .byte MSG$ERROR,MSG$NAK,MSG$ACK,TIMOUT,BADCHK,0 .even 210$: .word sbrk.$ .word sbrk.e ,sbrk.n ,sbrk.y ,sbrk$$ ,sbrk$$ global .sbttl sbreak routines sbrk.$: movb #STA.ABO,r1 ; default or timeout error return ; bye sbrk$$: movb state ,r1 ; receive failure (timeout) return ; remain in current state sbrk.e: calls prerrp ,<#recpkt> movb #STA.ABO,r1 return sbrk.n: dec r3 ; for a NAK see if it was for bge 10$ ; the last one mod 64 mov #63. ,r3 ; underflowed, reset to 63 10$: cmpb r3 ,paknum ; is it the last one ? beq 20$ ; yes movb state ,r1 ; no, simply stay in current mode return 20$: call sbrk.y return sbrk.y: cmp r3 ,paknum ; ACK, insure ack is for the beq 10$ ; current packet movb state ,r1 ; wrong packet, ignore it return 10$: clr numtry ; ack for this packet. incm64 paknum ; paknum := (paknum+1) mod 64 movb #STA.COM,r1 ; return ("COMPLETE") return global .sbttl sendinit sinfo:: save ; save ALL registers please clr numtry ; send info packets before any clr paknum ; extended server response please movb #MSG$SER,-(sp) ; packet type 'i' call .sinit ; do it unsave ; restore ALL registers now return ; bye sinit:: movb #MSG$SND,-(sp) ; normal sinit operation for sending call .sinit ; files return ; bye .sinit: mov chktyp ,-(sp) ; save checksum type (not needed) mov chksiz ,-(sp) ; save checksum type (not needed) movb #defchk ,chktyp ; force type one please mov #1 ,chksiz ; length of it inc numtry ; abort if we have been trying too much cmp numtry ,maxtry ; well ? blos 10$ ; no, keep it up movb #STA.ABO,r1 ; yes, return("ABORT") br 100$ 10$: calls spar ,<#packet> ; get our send parameters calls cantyp ,<#ttname,#lun.ti>; flush pending input please movb 6(sp) ,r5 ; packet type to do today spack r5,paknum,sparsz,#packet ; sent our init info now rpack r2,r3,#recpkt ; and get the other's response scan r1,#200$ ; and dispatch to the correct asl r0 ; routine now jsr pc ,@210$(r0) ; simple 100$: mov (sp)+ ,chksiz ; restore cehcksum stuff mov (sp)+ ,chktyp ; restore cehcksum stuff mov (sp)+ ,@sp ; pop passed packet type now return 200$: .byte MSG$ERROR,MSG$NAK,MSG$ACK,TIMOUT,BADCHK,0 .even 210$: .word sini.$ .word sini.e ,sini.n ,sini.y ,sini$$ ,sini$$ global global .sbttl routines for SINIT sini.$: movb #STA.ABO,r1 ; default case, unrecognized TYPE return sini$$: movb state ,r1 ; error on the packet, try again return sini.e: cmpb r5 ,#MSG$SER ; if called from sinfo, ignore errors beq 100$ ; calls prerrp ,<#recpkt> ; error state, print it and abort movb #STA.ABO,r1 ; return ("ABORT") 100$: return sini.n: cmpb r5 ,#MSG$SER ; server NAK for I (sinfo) packet? bne 10$ ; no cmp numtry ,#2 ; gotten at least one NAK for 'I'? blo 10$ ; no, try again please incm64 paknum ; yes, simply ignore it and move clr numtry ; to file state movb #STA.FIL,r1 ; not all servers may know about it return 10$: movb state ,r1 ; NAK, continue as before return sini.y: cmp r3 ,paknum ; got an ACK for SINIT beq 10$ ; and the ack is for correct packet movb state ,r1 ; wrong ACK, ignore it please return 10$: calls rpar ,<#recpkt,r2> ; load the other's parameters now tstb conpar+p.eol ; insure legitimate EOL character bne 20$ ; yes movb #cr ,conpar+p.eol ; no, stuff a carriage return in 20$: tstb conpar+p.qctl ; vaild quoting character present? bne 30$ ; yes movb #myquot ,conpar+p.qctl ; no, stuff the default in please 30$: clr numtry ; number_of_trys := 0 incm64 paknum ; packetnumber := packetnumber+1 mod 64 call inirepeat ; initialize repeat processing movb #STA.FIL,r1 ; return("FILE") return global .sbttl sfile .enabl lsb sfile: 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 ; insure correct default for mode mov #filnam ,r3 ; and point to it please clr skipfl ; the user skip the rest of a file call clratr ; insure attribute stuff is cleared call inirepeat ; must reset pointers for repeat counts sub #100 ,sp ; and a converted filename buffer mov sp ,r4 ; and point to it please inc numtry ; abort if we have been trying too much cmp numtry ,maxtry ; well ? blos 10$ ; no, keep it up movb #STA.ABO,r1 ; yes, return("ABORT") jmp 100$ ; exit 10$: tst inopn ; open files hanging around ? beq 20$ ; no calls close ,<#lun.in> ; yes, clean up please clr inopn ; it's closed now 20$: tst doauto ; see if we should check for binary beq 25$ ; no, don't do it please calls binfil ,<#filnam,#lun.in>; 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 ,<#2,#errtxt,#filnam>; say so please movb #STA.ABO,r1 ; return("ABORT") br 100$ ; 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 fillog ,<#1,#filnam> ; log this to disk calls namcvt ,<#filnam,r4> ; convert name to simple name tst remote ; are we local here ? bne 40$ ; no, don't print this out calls printm ,<#4,#300$,#filnam,#310$,r4> 40$: strlen r4 ; and get the filename length spack #MSG$FILE,paknum,r0,r4 ; set the filename packet over br 50$ ; ok 45$: spack #MSG$TEXT,paknum ; server extended reply here, send X 50$: rpack r2,r3,#recpkt ; get the response to the filename scan r1,#200$ ; and dispatch on the response asl r0 ; times 2 jsr pc ,@210$(r0) ; and call the appropiate response 100$: add #100 ,sp return 200$: .byte MSG$ERROR,MSG$NAK,MSG$ACK,TIMOUT,BADCHK,0 .even 210$: .word sfil.$ .word sfil.e ,sfil.n ,sfil.y ,sfil$$ ,sfil$$ 300$: .asciz /Sending file / 310$: .asciz / as file / .even .dsabl lsb global global .sbttl routines for SFILE sfil.$: movb #STA.ABO,r1 ; unknown response, return("ABORT") return sfil$$: movb state ,r1 ; timeout or checksum error return ; remain in current F state sfil.e: calls prerrp ,<#recpkt> ; error, abort aftering getting movb #STA.ABO,r1 ; the error packet printed. return sfil.n: dec r3 ; a NAK, see if it's for the last bge 10$ ; packet mov #63. ,r3 ; --paknum<0 ? 63:paknum 10$: cmp r3 ,paknum ; same one ? beq 20$ ; yes movb state ,r1 ; no, continue on as before then return ; bye 20$: call sfil.y ; same packet, goto ACK code return sfil.y: cmp r3 ,paknum ; same packet number being ACKED? beq 10$ ; yes movb state ,r1 ; no, continue in current state return 10$: clr numtry ; number_of_tries := 0 incm64 paknum ; packnumber := packnumber+1 mod 64 movb #STA.ATR,r1 ; return("ATTRIBUTE") return global .sbttl sdata send file data to other system sdata: inc numtry ; abort if we have been trying too much cmp numtry ,maxtry ; well ? blos 10$ ; no, keep it up movb #STA.ABO,r1 ; yes, return("ABORT") br 100$ ; exit 10$: spack #MSG$DATA,paknum,size,#packet ; send the next record out please rpack r2,r3,#recpkt ; 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 100$: return ; bye 200$: .byte MSG$ERROR,MSG$NAK,MSG$ACK,TIMOUT,BADCHK,0 .even 210$: .word sdat.$ .word sdat.e ,sdat.n ,sdat.y ,sdat$$ ,sdat$$ .sbttl handle the response to the packet sent by SDATA sdat.$: movb #STA.ABO,r1 ; unrecognized packet type return sdat$$: movb state ,r1 ; timeout, stay in current state return ; and exit sdat.e: calls prerrp ,<#recpkt> ; print out received error packet return sdat.n: dec r3 ; a NAK, see if it's for the last bge 10$ ; packet mov #63. ,r3 ; --paknum<0 ? 63:paknum 10$: cmp r3 ,paknum ; same one ? beq 20$ ; yes movb state ,r1 ; no, continue on as before then return ; bye 20$: call sdat.y ; same packet, goto ACK code return sdat.y: cmp r3 ,paknum ; insure ACK is for correct packet beq 10$ ; yes movb state ,r1 ; no, continue in current state return 10$: 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 ; any control C's pending? bne 30$ ; yes, always send an error packet call chkabo ; now check for control X,Z or E cmpb r0 ,#ABT$ERROR&37 ; control E then send error packet beq 30$ ; yes cmpb r0 ,#ABT$CUR&37 ; control X then abort current file beq 20$ ; yes cmpb r0 ,#ABT$ALL&37 ; control Z then abort file group? bne 40$ ; nothing 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 in EOF return ; and exit 30$: spack #MSG$ERROR,paknum ; send an error packet mov #STA.ABO,r1 ; force state to ABORT return ; and exit 40$: cmpb recpkt ,#ABT$CUR ; did the ack contain a X for skipfile beq 80$ ; yes, fake EOF then cmpb recpkt ,#ABT$ALL ; did the ack contain a Z for skip all bne 90$ ; files ? no mov #-1 ,index ; flag a fake no more files 80$: movb #STA.EOF,r1 ; and fake EOF for either X or Z ack return 90$: 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 ; EOF, set state to EOF state return ; return("EOF") 100$: movb #STA.DAT,r1 ; not eof, stay in DATA state return ; return("DATA") global seof: inc numtry ; abort if we have been trying too much cmp numtry ,maxtry ; well ? blos 10$ ; no, keep it up movb #STA.ABO,r1 ; yes, return("ABORT") br 100$ ; exit 10$: tst skipfl ; skipping the rest of a file ? beq 20$ ; no spack #MSG$EOF,paknum,#1,#220$; yes, send D in data field br 30$ 20$: spack #MSG$EOF,paknum ; send an EOF packet out now 30$: rpack r2,r3,#recpkt ; 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 100$: clr skipfl ; clear skip the file flag return ; bye 200$: .byte MSG$ERROR,MSG$NAK,MSG$ACK,TIMOUT,BADCHK,0 .even 210$: .word seof.$ .word seof.e ,seof.n ,seof.y ,seof$$ ,seof$$ 220$: .byte 'D&137 ,0 .sbttl handle the response to the packet sent by seof seof.$: movb #STA.ABO,r1 ; unrecognized packet type return seof$$: movb state ,r1 ; timeout, stay in current state return ; and exit seof.e: calls prerrp ,<#recpkt> ; print out received error packet return seof.n: dec r3 ; a NAK, see if it's for the last bge 10$ ; packet mov #63. ,r3 ; --paknum<0 ? 63:paknum 10$: cmp r3 ,paknum ; same one ? beq 20$ ; yes movb state ,r1 ; no, continue on as before then return ; bye 20$: call seof.y ; last packet, handle the kac return seof.y: cmp r3 ,paknum ; correct packet number beq 10$ ; yes movb state ,r1 ; no, return the last state return 10$: 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 call getnxt ; get the next input file ? tst r0 ; did it work ? bne 20$ ; no tst xmode bne 20$ movb #STA.FIL,r1 ; yes, set new state to "FILE" return 20$: movb #STA.BRK,r1 ; return("BREAK") return .end