.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	<r0>			; 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	<r0>			; 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	<chksiz	,chktyp	,inopn	,lun.in	,state	,sencnt>
	global	<image	,$image>

	global	<senhdr,senlog,rechdr,reclog>


	.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	,<r0,r1,#lun.lo>; 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	<image	,state	,trace>

	.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	<atrctx,numtry	,paknum	,packet	,sendat	,size	,state>







	.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	<maxtry	,state>



	.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	<numtry	,paknum	,packet	,recpkt	,state>


	.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	<lun.ti	,packet	,paknum	,recpkt	,sparsz	,ttname>
	global	<maxtry	,numtry>






	.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	<conpar	,numtry	,paknum	,recpkt>
	

	.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	,<r0,#errtxt>	; 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	<doauto	,errtxt	,filnam	,index	,inopn	,paknum	,recpkt>
	global	<skipfl	,clratr>



	.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	<size>


	.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	<chkabo	,numtry	,paknum	,packet	,size	,state>

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