.title K11REC recieve processing .ident /T2.23/ .if ndf, K11INC .ift .include /IN:K11MAC.MAC/ .include /IN:K11DEF.MAC/ .endc .psect .enabl gbl ; 13-Oct-84 14:06:43 Brian Nelson ; ; Creation: Moved from K11PAK ; ; ; 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 recsw state table controller for receiving files .enabl lsb recsw:: clr paknum ; packet_number := 0 rec.sw::movb @r5 ,state ; assume RECEIVE-INIT for starters clr cccnt ; control_c_count := 0 mov $image ,image ; insure correct default for mode movb #defchk ,chktyp ; reset checksum type to default mov #1 ,chksiz ; the size of the checksum clr numtry ; number_trys := 0 clr oldtry ; add pcnt.r+2,reccnt+2 ; /43/ Save rec packet count adc reccnt+0 ; /43/ 32 bits today add pcnt.r+0,reccnt+0 ; /43/ 32 bits in the total call clrsta ; clear the stats out now clr outopn ; say nothing is open now tst remote ; local or remote bne 5$ ; remote call ttrini ; perhaps special init for local tt: 5$: call rechdr call incsta ; /43/ Timer stats init 10$: call recdeb ; perhaps debugging should be done cmp incpar ,#1 ; /56/ Is it possible that parity bne 15$ ; /56/ is messed up? CALLS printm ,<#1,#300$> ; /56/ Warn, but only once 15$: tst remote ; /43/ Control C and a server? bne 20$ ; /43/ Yep, ignore random noise. tst cccnt ; /36/ control C abort ? beq 20$ ; /36/ no movb #STA.CCABO,state ; /36/ yes, enter ABORT state 20$: scan state ,#200$ ; case state of asl r0 ; dispatch to correct routine jsr pc ,@210$(r0) bcc 10$ 100$: movb #defchk ,chktyp ; reset type of checksum to 1 mov #1 ,chksiz ; the size of the checksum save ; insure files are closed tst remote ; remote or local bne 105$ ; remote call ttrfin ; local, perhaps clean up console 105$: tst outopn ; file open from a failure ? bpl 110$ ; no calls close ,<#lun.ou> ; insure that it's closed 110$: clr outopn call incsta ; /43/ Timer stats init unsave ; pop exit status code please return .save .psect $PDATA ,D 200$: .byte STA.RIN ,STA.FIL,STA.DAT,STA.COM,STA.ABO,STA.CCABO,0 .even 210$: .word recs.$ .word recs.r ,recs.f ,recs.d ,recs.c ,recs.a, ccabort 300$: .asciz / Warning: Parity possibly being used by sender./ .even .restore .dsabl lsb recs.$: clc ; Unknown state return ; back to caller recs.r: call rinit ; receive-init movb r1 ,state ; set state and exit clc ; saying there is more to come return ; bye recs.f: call rfile ; receive-file movb r1 ,state clc return recs.d: call rdata ; receive-data movb r1 ,state clc return recs.c: clr r0 ; complete sec return ccabort:strlen #ccmsg0 ; /43/ Send msg text over spack #MSG$ERROR,paknum,r0,#ccmsg0 ; /36/ break out the sender please recs.a: mov sp ,r0 ; abort sec return .save .psect $PDATA ,D ccmsg0: .asciz /Control C abort on file receive/ .even .restore global global .sbttl debugging and logging for receive .enabl lsb recdeb: save sub #50 ,sp 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 bit #log$st ,trace ; debugging for RECSW beq 30$ ; if trace is on then dump the calls putrec ,; dump it 30$: tst debug ; terminal debugging on ? beq 40$ ; no print r0 ,r1 .newli ; and a crlf 40$: tst remote ; running locally ? bne 100$ ; no tst xmode ; simply printing text to ti: ? bne 100$ ; yes, skip the packet stats then call reclog 100$: add #50 ,sp unsave return .save .psect $PDATA 200$: .asciz /Recsw - state is / .even .restore .dsabl lsb global .sbttl rinit receive initialization ; R I N I T ; ; input: nothing .enabl lsb rinit: save ; get registers we use saved inc numtry ; check for retry count cmp numtry ,maxtry ; been here too often ? blos 10$ ; no call m$retry ; log/send the reason for the abort movb #STA.ABO,r1 ; yes, return ABORT state br 100$ 10$: rpack r2,r3,#packet ; get the next packet please scan r1,#200$ ; look for the packet type asl r0 ; and dispatch to it jsr pc ,@210$(r0) ; simple 100$: unsave return .save .psect $PDATA 200$: .byte MSG$SND ,MSG$ERROR,TIMOUT,BADCHK,0 .even 210$: .word rini.$ .word rini.S ,rini.E ,rini$$ ,rini$$ .restore .dsabl lsb rini.$: ; unknown packet type rini$$: spack #MSG$NAK,paknum ; error, send a NAK movb state ,r1 ; and exit return rini.e: calls prerrp ,<#packet> movb #STA.ABO,r1 return rini.s: calls rpar ,<#packet,r2> ; SEND-INIT calls spar ,<#packet> ; get other sides init and fill with spack #MSG$ACK,paknum,sparsz,#packet; ours mov numtry ,oldtry clr numtry incm64 paknum ; paknum := (paknum+1) mod 64 call inirepeat ; initialize repeat processing movb #STA.FIL,r1 ; state := FILE-RECEIVE return .sbttl rfile receive file header .enabl lsb rfile: save ; get registers we use saved call clratr ; insure attribute stuff is cleared movb conpar+p.chkt,chktyp ; time to use new checksum ? movb chktyp ,chksiz ; compute the checksum size also sub #'0 ,chksiz ; simple mov $image ,image ; insure correct default for mode inc numtry ; check for retry count cmp numtry ,maxtry ; been here too often ? blos 5$ ; no call m$retry ; log why we aborted please movb #STA.ABO,r1 ; yes, return ABORT state br 100$ 5$: tst xgottn ; already get the x packet ? beq 10$ ; no movb #STA.TYP,r1 ; yes, fake that we already got it br 20$ 10$: rpack r2,r3,#packet ; get the next packet please 20$: scan r1,#200$ ; look for the packet type asl r0 ; and dispatch to it jsr pc ,@210$(r0) ; simple 100$: unsave return .save .psect $PDATA 200$: .byte MSG$SND ,MSG$EOF,MSG$FILE,MSG$BREAK,MSG$ERROR,MSG$TEXT .byte timout ,badchk ,0 .even 210$: .word rfil.$ .word rfil.s ,rfil.z ,rfil.f ,rfil.b ,rfil.e ,rfil.x .word rfil$$ ,rfil$$ .restore .dsabl lsb .sbttl more rfile rfil.$: ; unknow packet type rfil$$: spack #MSG$NAK,paknum ; timeout or checksum error, send movb state ,r1 ; NAK and continue in current state return rfil.b: cmp r3 ,paknum ; Break XMIT (EOT) beq 10$ ; insure BREAK is for current packet call m$synch ; for abort, say we are out of synch movb #STA.ABO,r1 ; no, return 'ABORT" return ; exit 10$: spack #MSG$ACK,paknum ; ACK the BREAK movb #STA.COM,r1 ; and return state as 'COMPLETE' return rfil.e: calls prerrp ,<#packet> ; error packet, print it out movb #STA.ABO,r1 ; return 'ABORT' return rfil.s: inc oldtry ; SEND-INIT, must have lost ours cmp oldtry ,maxtry ; tried this too many times ? blos 10$ ; no call m$retry ; log the reason for the abort movb #STA.ABO,r1 ; yes, return 'ABORT' return 10$: mov paknum ,r1 ; see if thispacket=(paknum+63) mod 64 add #77 ,r1 ; ie, check if this data packet was the clr r0 ; one sent the last time. if so, we div #100 ,r0 ; must reack that packet and remain clr r0 ; in the current state. cmp r3 ,r1 ; bne 20$ ; no calls spar ,<#packet> ; resend our SEND-INIT stuff spack #MSG$ACK,r3,sparsz,#packet ; reack this then clr numtry ; clear out retry counter movb state ,r1 ; and return current state return 20$: call m$synch ; log the reason for this event please movb #STA.ABO,r1 ; otherwise return ABORT since we must return ; be way out of synch then. rfil.z: inc oldtry ; END-OF-FILE ? cmp oldtry ,maxtry ; tried this too many times ? blos 10$ ; no call m$retry ; log the reason for this event movb #STA.ABO,r1 ; yes, return 'ABORT' return 10$: mov paknum ,r1 ; see if thispacket=(paknum+63) mod 64 add #77 ,r1 ; ie, check if this data packet was the clr r0 ; one sent the last time. if so, we div #100 ,r0 ; must reack that packet and remain clr r0 ; in the current state. cmp r3 ,r1 ; bne 20$ ; not the last one after all spack #MSG$ACK,r3 ; reack this then clr numtry ; clear out retry counter movb state ,r1 ; and return current state return 20$: call m$retry ; log the reason for this please movb #STA.ABO,r1 ; otherwise return ABORT since we must return ; be way out of synch then. .sbttl more rfile subroutines .enabl lsb ; Move the actual file create to RDATA so we can create ; the output file after all attribute packets have come. ; Thus, when we get the first DATA packet is when we go ; and create the file. ; ; 18-Apr-84 10:24:45 Brian Nelson rfil.f: cmp r3 ,paknum ; FILE name beq 10$ ; insure correct packet numer call m$synch ; log the reason for this ABORT movb #STA.ABO,r1 ; no, return 'ABORT' return ; bye 10$: STRCPY #srcnam ,#packet ; /53/ Temp copy calls bufunp ,<#srcnam,#packet>; /53/ clrb packet(r1) ; /53/ Insure .asciz calls fixfil ,<#packet,#srcnam>; check for invalid chars tst r0 ; was the filname ok ? beq 15$ ; yes calls printm ,<#3,#packet,#200$,#srcnam> 15$: calls fparse ,<#srcnam,#filnam>; parse and fill in defaults tst r0 ; /42/ Successful $PARSE? bne 100$ ; /42/ No tst outopn ; output already open as if from bpl 20$ ; a NAK or something calls close ,<#lun.ou> ; yes, close it please 20$: clr outopn ; it's closed spack #MSG$ACK,paknum ; please ack the fileheader packet mov numtry ,oldtry ; update number of retrys clr numtry ; and init the current retry count incm64 paknum ; paknum := (paknum+1) mod 64 movb #STA.DAT,r1 ; return 'DATA' return 100$: calls syserr , ; /42/ no, get the system error text calls error ,<#3,#230$,#errtxt,r4> /42/ movb #STA.ABO,r1 ; /42/ return 'ABORT' return .save .psect $PDATA 200$: .asciz / was renamed to / 230$: .asciz /RMS $PARSE failed / ; /42/ .even .restore .dsabl lsb rfil.x: cmp r3 ,paknum ; X header name beq 10$ ; insure correct packet numer movb #STA.ABO,r1 ; no, return 'ABORT' return ; bye 10$: spack #MSG$ACK,paknum ; ACK the filename clr outlun ; not a real file to output to clr outopn ; nothing is open for output mov sp ,xmode ; flag this also please MESSAGE ; /54/ Dump a CRLF mov numtry ,oldtry ; update number of retrys clr numtry ; and init the current retry count incm64 paknum ; paknum := (paknum+1) mod 64 movb #STA.DAT,r1 ; return 'DATA' return global global .sbttl rdata receive data from pc .enabl lsb ; R D A T A ; ; input: nothing ; output: global paknum packet number ; oldtry retry count ; packet packet just received ; numtry ; r1 returned state rdata: save clr datauk ; /43/ Unknown/out synch NAK count clr r0 ; error := 0 inc numtry ; abort of retry count is too large cmp numtry ,maxtry ; been here too many times ? blos 10$ ; no call m$retry ; log/send error message about it movb #STA.ABO,r1 ; yes, return state(abort) br 100$ ; bye 10$: rpack r2,r3,#packet ; get the next imcoming packet scan r1 ,#200$ ; look for the packet type and dispatch asl r0 ; to the correct routine. ie, a crude jsr pc ,@210$(r0) ; case statement 100$: unsave return .save .psect $PDATA 200$: .byte MSG$ATR ,MSG$DATA,MSG$ERROR,MSG$FILE,MSG$EOF,MSG$TEXT .byte timout ,badchk ,0 .even 210$: .word rdat.$ .word rdat.a ,rdat.d ,rdat.e ,rdat.f ,rdat.z ,rdat.x .word rdat$$ ,rdat$$ .restore .dsabl lsb global .sbttl rdata packet handlers .enabl lsb rdat.d: tst xmode ; do we need to create the file bne 1$ ; no tst outopn ; did we already open the file up? bne 1$ ; yes, please don't try again then. tst filprot ; no supercede on file creates ? beq 2$ ; no clr -(sp) ; yes, check for the file already mov sp ,r0 ; there please calls lookup ,<#3,#filnam,r0,#srcnam> tst (sp)+ ; pop context for lookup tst r0 ; did we find the file today? bne 2$ ; no calls printm ,<#2,#250$,#filnam> spack #MSG$ACK,paknum,#1,#220$; yes, send ack with X in data incm64 paknum ; increment packet number mod 64 clr numtry ; /48/ mov #1 ,outopn ; never really opened it up movb #STA.DAT,r1 ; switch to data state return ; bye 1$: br 10$ 2$: mov #filnam ,r4 ; /36/ setup address of file tstb asname ; /36/ use alternate name for file? beq 3$ ; /36/ nothing there calls fparse ,<#asname,r4> ; /37/ insure defaults are inserted tst r0 ; /37/ is parse successful bne 4$ ; /37/ no, exit 3$: calls create ,; /36/ now create it clrb asname ; /36/ one shot for alternate name mov #lun.ou ,outlun ; set a real LUN for output tst r0 ; did the file create work ? beq 5$ ; yes 4$: calls syserr , ; no, get the system error text tst remote ; /51/ Are we LOCAL or Remote bne 444$ ; /51/ We must be the server strlen #errtxt ; /51/ We are local, get the spack #MSG$ERR,paknum,r0,#errtxt ; /51/ Other side to STOP. 444$: calls error ,<#3,#230$,#errtxt,r4> /36/ movb #STA.ABO,r1 ; return 'ABORT' return 5$: calls fillog ,<#0,r4> ; /36/ log to disk perhaps ? calls printm ,<#2,#240$,r4> ; /36/ log to terminal perhaps? mov #-1 ,outopn ; flag output as being open 10$: cmp r3 ,paknum ; case "D" beq 40$ ; Correct packet number ? inc oldtry ; no, see if retry limit expired cmp oldtry ,maxtry ; if so, return ABORT blos 20$ ; no call m$retry ; log/send notice of what happened movb #STA.ABO,r1 ; yes, return 'ABORT' return ; bye 20$: mov paknum ,r1 ; see if thispacket=(paknum+63) mod 64 add #77 ,r1 ; ie, check if this data packet was the clr r0 ; one sent the last time. if so, we div #100 ,r0 ; must reack that packet and remain clr r0 ; in the current state. cmp r3 ,r1 ; insure r0 is not affected bne 30$ ; not the last packet spack #MSG$ACK,r3 ; reack this then clr numtry ; clear out retry counter movb state ,r1 ; and return current state return 30$: call m$synch ; log/send the reason for the abort movb #STA.ABO,r1 ; otherwise return ABORT since we must return ; be way out of synch then. 40$: add r2 ,charin+2 ; /43/ Stats adc charin+0 ; /43/ In 32 bits please calls bufemp ,<#packet,r2> ; correct packet, get the data out tst r0 ; did BUFEMP return any errors? beq 41$ ; no calls syserr , ; it failed, send error packet calls error ,<#2,#200$,#errtxt> br 100$ ; take the abort exit please 41$: tst remote ; are we a local kermit today ? bne 70$ ; no, just ack normally tst cccnt ; we are local. check for control bne 60$ ; c abort for this file please call chkabo ; check for abort via ^X and ^Z cmpb r0 ,#ABT$ERROR&37 ; control E aborts NOW beq 60$ ; yes, abort please cmpb r0 ,#ABT$ALL&37 ; did the user type a control Z? beq 50$ ; yes cmpb r0 ,#ABT$CUR&37 ; no, what about a control X then? beq 45$ ; /56/ Yes cmpb r0 ,#'A&37 ; /56/ Control A ? bne 70$ ; /56/ No call cs$in ; /56/ Yes, print stats br 70$ ; /56/ And exit 45$: spack #MSG$ACK,paknum,#1,#220$; ^X typed, send an X in the data br 80$ 50$: spack #MSG$ACK,paknum,#1,#210$; yes, send an ACK with "Z" data br 80$ ; 60$: spack #MSG$ERROR,paknum ; break the sender out please clr cccnt ; /36/ clear control C flag br 100$ ; bye 70$: spack #MSG$ACK,paknum ; ack it 80$: mov numtry ,oldtry ; oldtry_count:= numtry clr numtry ; numtry := 0 incm64 paknum ; increment packet number mod 64 movb #STA.DAT,r1 ; switch to data state return ; bye 100$: mov #STA.ABO,r1 ; abort for some reason return global global .save .psect $PDATA 200$: .asciz /Local KERMIT error: / 210$: .byte ABT$ALL ,0 220$: .byte ABT$CUR ,0 230$: .asciz /Create failed - / 240$: .asciz /Created file - / 250$: .asciz /File exists, not superceded - / .even .restore .dsabl lsb .sbttl rdata subroutines, continued ; 'F', got a FILE HEADER rdat.x: ; 'X', also handle EXTENED REPLY rdat.f: inc oldtry ; no, see if retry limit expired cmp oldtry ,maxtry ; if so, return ABORT blos 10$ ; no call m$retry ; log/send the reason for the abort movb #STA.ABO,r1 ; yes, return 'ABORT' return ; bye 10$: mov paknum ,r1 ; see if thispacket=(paknum+63) mod 64 add #77 ,r1 ; ie, check if this data packet was the clr r0 ; one sent the last time. if so, we div #100 ,r0 ; must reack that packet and remain clr r0 ; in the current state. cmp r3 ,r1 ; bne 20$ ; not the last packet spack #MSG$ACK,r3 ; reack this then clr numtry ; clear out retry counter movb state ,r1 ; and return current state return 20$: call m$synch ; log/send the reason for the abort movb #STA.ABO,r1 ; else return ABORT return rdat.e: calls prerrp ,<#packet> ; flag error, print it movb #STA.ABO,r1 ; return ABORT return rdat.z: cmp paknum ,r3 ; END OF FILE. If not correct packet beq 10$ ; the return 'ABORT' call m$synch ; log/send the reason for the abort movb #STA.ABO,r1 ; switch to abort state return ; and exit 10$: mov #lun.ou ,r2 ; assume that we close a disk file tst outopn ; real output or to the terminal bmi 20$ ; it's a for real disk file today bgt 30$ ; open was aborted via fileprotection clr r2 ; no, it's the console terminal 20$: calls close , ; do the close now call clratr ; attributes no longer valid 30$: clr outopn ; flag it spack #MSG$ACK,r3 ; acknowledge the eof packet mov numtry ,oldtry ; /48/ clr numtry ; /48/ incm64 paknum ; paknum := (paknum+1) mod 64 movb #STA.FIL,r1 ; back to receive file state clr xgottn ; don't have an X packet anymore return .enabl lsb rdat.$: inc datauk ; /43/ Unknown packet type cmp datauk ,#2 ; /43/ Been here too often ? blo rdat$$ ; /43/ No, simply NAK it strlen #200$ ; /43/ Yes, send error packet spack #MSG$ERROR,paknum,r0,#200$ ; /43/ ... movb #STA.ABO,r1 ; /43/ Exit please return .save .psect $PDATA 200$: .asciz /Expecting ACK, packet type not valid in current RDATA state/ .even .restore .dsabl lsb rdat$$: spack #MSG$NAK,paknum ; timed out or checksum error movb state ,r1 ; NAK it and return current state return global global .sbttl receive data attribute packets .enabl lsb rdat.a: cmp r3 ,paknum ; case "A" beq 40$ ; Correct packet number ? inc oldtry ; no, see if retry limit expired cmp oldtry ,maxtry ; if so, return ABORT blos 20$ ; no call m$retry ; log/send the reason for the abort movb #STA.ABO,r1 ; yes, return 'ABORT' return ; bye 20$: mov paknum ,r1 ; see if thispacket=(paknum+63) mod 64 add #77 ,r1 ; ie, check if this data packet was the clr r0 ; one sent the last time. if so, we div #100 ,r0 ; must reack that packet and remain clr r0 ; in the current state. cmp r3 ,r1 ; insure r0 is not affected bne 30$ ; not the last packet spack #MSG$ACK,r3 ; reack this then clr numtry ; clear out retry counter movb state ,r1 ; and return current state return 30$: movb #STA.ABO,r1 ; otherwise return ABORT since we must return ; be way out of synch then. 40$: calls r$attr ,<#packet> ; simple tst r0 ; was this successful ? bne 50$ ; no spack #MSG$ACK,paknum mov numtry ,oldtry ; oldtry_count:= numtry clr numtry ; numtry := 0 incm64 paknum ; increment packet number mod 64 movb state ,r1 ; retain current state br 100$ ; all done 50$: movb #STA.ABO,r1 ; new state br 100$ ; bye 100$: return ; exti .save .psect $PDATA 200$: .asciz /Attribute packet error - / .even .restore .dsabl lsb .end