.title k11sen send processing .ident /T2.23/ .if ndf, K11INC .ift .include /IN:K11MAC.MAC/ .include /IN:K11DEF.MAC/ .endc .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. ; ; .save .psect recpkt ,rw,d,lcl,rel,con recpkt: .blkb 130 ; /51/ We will never get a long .restore ; /51/ packet in reply to data. .sbttl send processing .enabl lsb .psect $CODE ,I .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 clr datauk ; /43/ Abort synch status add pcnt.s+2,sencnt+2 ; /43/ save sent packet count adc sencnt+0 ; /43/ 32 bit sums please add pcnt.s+0,sencnt+0 ; /43/ 32 bit high part also 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 clr dpnumber ; /43/ Clear DATA packet count call incsta ; /43/ Get timer stats set up 10$: call sendeb tst remote ; /43/ If remote, don't bne 20$ ; /43/ Ok tst cccnt ; /36/ control C abort beq 20$ ; /36/ no movb #STA.CCABO,state ; /36/ fake abort 20$: 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$: call incsta ; /43/ Get timer stats set up unsave ; pop exit status code please return ; bye .save .psect $PDATA ,D 200$: .byte STA.ABO ,STA.BRK,STA.COM,STA.DAT,STA.FIL,STA.SIN,STA.EOF .byte STA.ATR ,STA.CCA .byte 0 .even 210$: .word send.$ .word send.a ,send.b ,send.c ,send.d ,send.f ,send.s ,send.z .word send.h ,ccabort .restore .dsabl lsb global global ; /43/ global .sbttl STATE routines for SENDSW ccabort:spack #MSG$ERROR,paknum ; /36/ break up a deadlock perhaps 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 .enabl lsb 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 .save .psect $PDATA ,D 200$: .asciz /Sendsw - state is / .even .restore .dsabl lsb global .sbttl sattr send attribute data for the current file .enabl lsb 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") call m$retry ; flag the error type please 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 .save .psect $PDATA ,D 200$: .byte MSG$ERROR,MSG$NAK,MSG$ACK,TIMOUT,BADCHK,0 .even 210$: .word satr.$ .word satr.e ,satr.n ,satr.y ,satr$$ ,satr$$ .restore .dsabl lsb .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 .enabl lsb 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 call m$retry ; flag the error type please 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 .save .psect $PDATA ,D 200$: .byte MSG$ERROR,MSG$NAK,MSG$ACK,TIMOUT,BADCHK,0 .even 210$: .word sbrk.$ .word sbrk.e ,sbrk.n ,sbrk.y ,sbrk$$ ,sbrk$$ .restore .dsabl lsb 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 .enabl lsb 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") call m$retry ; flag the error type please 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 .save .psect $PDATA ,D 200$: .byte MSG$ERROR,MSG$NAK,MSG$ACK,TIMOUT,BADCHK,0 .even 210$: .word sini.$ .word sini.e ,sini.n ,sini.y ,sini$$ ,sini$$ .restore .dsabl lsb 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") call m$retry ; flag the error type please 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$: tstb filnam ; /38/ a REAL file today? bne 21$ ; /38/ no, must be extended server reply jmp 45$ 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 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 tstb asname ; /36/ check for alternate name ? beq 35$ ; /36/ no mov #asname ,r4 ; /36/ yes, point to that name 35$: 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 clrb asname ; /36/ insure one shot only 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 .save .psect $PDATA ,D 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 .restore .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") tst xmode ; /38/ return((xmode) ?STA.DAT:STA.ATR) beq 20$ ; /38/ attributes next calls buffil ,<#packet> ; /38/ get the first buffer of data mov r1 ,size ; /38/ and save it movb #STA.DAT,r1 ; /38/ extended reply, no attributes 20$: return global .sbttl sdata send file data to other system .enabl lsb sdata: inc numtry ; abort if we have been trying too much movb paknum ,datauk ; /43/ cmp numtry ,maxtry ; well ? blos 10$ ; no, keep it up movb #STA.ABO,r1 ; yes, return("ABORT") call m$retry ; flag the error type please 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 .save .psect $PDATA ,D 200$: .byte MSG$ERROR,MSG$NAK,MSG$ACK,TIMOUT,BADCHK,0 .even 210$: .word sdat.$ .word sdat.e ,sdat.n ,sdat.y ,sdat$$ ,sdat$$ .restore .dsabl lsb global ; /43/ .sbttl handle the response to the packet sent by SDATA .enabl lsb ; Unknown or packet type not valid in current state sdat.$: cmpb datauk+1,#2 ; /43/ Been here too often ? blo 100$ ; /43/ No, simply NAK it cmpb datauk ,paknum ; /43/ But for the SAME packet bne 100$ ; /43/ No, just NAK it incb datauk+1 ; /43/ Bump the counter please strlen #200$ ; /43/ Yes, send error packet spack #MSG$ERROR,paknum,r0,#200$ ; /43/ ... movb #STA.ABO,r1 ; /43/ Exit please return 100$: spack #MSG$NAK,paknum ; /43/ No, just simple NAK movb state ,r1 ; /43/ Continue... return ; /43/ Exit .save .psect $PDATA ,D 200$: .asciz /Expecting ACK, packet type not valid in current SDATA state/ .even .restore .dsabl lsb sdat$$: ; /43/ Timeout sizfix: tst dpnumber ; /43/ First DATA packet? bne 100$ ; /43/ No cmp senlng ,#maxpak ; /43/ Long packet got TOO small ? blos 100$ ; /43/ No asr senlng ; /43/ Yes, reduce packet size tst infomsg ; /43/ Really inform the user? beq 100$ ; /43/ No calls printm ,<#1,#adpmsg> ; /43/ Inform the user 100$: movb state ,r1 ; /43/ Keep current state return ; and exit global ; /43/ .save .psect $pdata adpmsg: .ascii /LONG Packet size reduced, first data packet failed/ .byte cr,lf,0 .even .restore sdat.e: calls prerrp ,<#recpkt> ; print out received error packet return sdat.n: clr datauk ; /43/ 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 ? bne sizfix ; /43/ No, must be for current packet call sdat.y ; same packet, goto ACK code return sdat.y: clr datauk ; /43/ cmp r3 ,paknum ; insure ACK is for correct packet beq 10$ ; yes movb state ,r1 ; no, continue in current state return 10$: 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 ; 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 ,#'A&37 ; /56/ Control A stats? bne 16$ ; /56/ No call cs$out ; /56/ Yes, dump char counts br 40$ ; /56/ And finish up 16$: cmpb r0 ,#ABT$ERROR&37 ; /56/ 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 clr cccnt ; /36/ clear control C flag 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$: 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 ; EOF, set state to EOF state return ; return("EOF") 100$: movb #STA.DAT,r1 ; not eof, stay in DATA state return ; return("DATA") global .sbttl SEOF Send file eof packet .enabl lsb 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") call m$retry ; flag the error type please 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 .save .psect $PDATA ,D 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 .even .restore .dsabl lsb .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 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 .end