/
/ Flush.
/

	.globl	fflush
	.globl	__flsh
	.globl	__put

blank:	.ascii	" "
soh:	.byte	1
enq:	.byte	5
hbf:	.blkb	2
	.even

/
/ fflush(ioptr);
/ FILE *ioptr;
/

fflush:	jsr	r0,__csav	/Get a stack frame.
	mov	12(r5),r4	/Grab ioptr.

	bit	$VF_OUT,(r4)	/Output IOV.
	beq	0f		/Br if not.
	bit	$VF_UBF,(r4)	/Unbuffered IOV.
	bne	0f		/Br if yes
	call	__flsh		/Do it.

0:	jmp	__cret		/Done.

/
/ This routine flushes the line
/ buffer in the IOV.
/ V_R0(r4) is nbytes.
/ V_R1(r4) is a buffer pointer.
/

__flsh:	mov	r0,-(sp)	/This save may
	mov	r1,-(sp)	/No be necessary.

	mov	V_RBUF(r4),r0	/Buffer address
	mov	V_R0(r4),r1	/Byte count
	beq	0f		/Duck out if zero
	call	__put		/Out it goes.
	mov	r0,V_R1(r4)	/Reset buffer pointer.
	clr	V_R0(r4)	/Clear byte count.

0:	mov	(sp)+,r1	/Return
	mov	(sp)+,r0	/
	return			/

/
/ Put a record.
/ r0 = address
/ r1 = byte count.
/ r4 = iov.
/
/ This routine does newline checking.
/ The "u" option implies the "n" option
/ so binary works as advertised.
/

__put:	mov	r0,-(sp)	/Save the world.
	mov	r1,-(sp)	/
	mov	r2,-(sp)	/
	mov	r3,-(sp)	/

	mov	r0,r2		/Point just past the
	add	r1,r2		/End of the record.

/
/ Record devices.
/

	bit	$VF_REC,(r4)	/Record device?
	beq	2f		/No

	bit	$VF_H72,(r4)	/Am I a 7221
	beq	0f		/No
	call	h7221		/Handshake

0:	bit	$VF_NOS,(r4)	/No newlines?
	beq	0f		/No
	clr	r2		/Set no slew byte.
	mov	$IO.WAL,r3	/IO.WAL used for the write.
	br	1f		/

0:	mov	$IO.WVB,r3	/Set default IO.WVB.
	cmpb	-(r2),$12	/Newline
	bne	0f		/No
	mov	$' ,r2		/Set normal slew
	dec	r1		/Remove from byte count
	bne	1f		/
	mov	$blank,r0	/Bug in RSX.
	inc	r1		/
	br	1f		/

0:	mov	$'$,r2		/Prompt slew.

1:	clr	-(sp)		/Do the I/O.
	clr	-(sp)		/
	clr	-(sp)		/
	mov	r2,-(sp)	/Slew
	mov	r1,-(sp)	/Nbytes.
	mov	r0,-(sp)	/Address.
	mov	r3,r0		/Do
	call	__qiow		/Write.
	bcs	3f		/Error

	bit	$VF_H26,(r4)	/Am I a 2649
	beq	4f		/No
	call	h2649		/Handshake
	br	4f

/
/ Block devices.
/

2:	bit	$VF_NOS,(r4)	/No newlines?
	bne	0f		/Yes
	cmpb	-(r2),$12	/Delete trailing newline.
	bne	0f		/Not a newline
	dec	r1		/

0:	cmpb	V_RTYP(r4), $R.FIX
	bne	1f

/ Fixed length records
/
	cmp	r1, V_RSIZ(r4)
	blos	0f
	mov	V_RSIZ(r4), r1	/Truncate long lines

0:	mov	r1, -(sp)
	mov	r1, r2
	mov	2+6(sp), r3

0:	dec	r2		/Loop to send the record
	bmi	0f
	movb	(r3)+, r0
	call	outb
	br	0b

0:	mov	(sp), r2
	neg	r2
	add	V_RSIZ(r4), r2

0:	dec	r2		/Pad short records
	bmi	odd
	clr	r0
	call	outb
	br	0b

/ Variable length records
/
1:	cmp	r1,V_RSIZ(r4)	/If this record is longer than
	blos	0f		/The longest record already out
	mov	r1,V_RSIZ(r4)	/Reset the size

0:	mov	r1,-(sp)	/Save updated byte count.
	mov	r1,r0		/Put out RCW.
	call	outb		/
	mov	(sp),r0		/
	swab	r0		/
	call	outb		/

	mov	(sp),r2		/Byte count
	mov	10(sp),r3	/Address

0:	dec	r2		/Put out the record
	bmi	odd		/
	movb	(r3)+,r0	/
	call	outb		/
	br	0b		/

odd:	asr	(sp)+		/Is this odd length record?
	bcc	1f		/No
	clr	r0		/Put out NUL.
	call	outb		/

/
/ Update EOF location.
/

1:	cmp	V_RBLK(r4),V_EFBK(r4) /EOF high lbn.
	bhi	0f		/Must fix
	blo	4f		/Ok
	cmp	V_RBLK+2(r4),V_EFBK+2(r4) /EOF low lbn.
	bhi	0f		/Must fix
	blo	4f		/Ok
	cmp	V_RBYT(r4),V_FFBY(r4) /EOF byte number.
	blos	4f		/Ok

0:	mov	V_RBLK(r4),V_EFBK(r4) /Update
	mov	V_RBLK+2(r4),V_EFBK+2(r4) /EOF
	mov	V_RBYT(r4),V_FFBY(r4) /Location.
	br	4f		/

3:	bis	$VF_ERR,(r4)	/Set error flag.

4:	mov	(sp)+,r3	/Return
	mov	(sp)+,r2	/
	mov	(sp)+,r1	/
	mov	(sp)+,r0	/
	return			/

/
/ Put out a byte to a block buffered
/ device.
/ r0 = byte.
/ Uses r0, r1
/

outb:	mov	V_RBYT(r4),r1	/Get byte location
	add	V_BBUF(r4),r1	/
	movb	r0,(r1)		/Save byte

	inc	V_RBYT(r4)	/Fix byte number.
	cmp	V_RBYT(r4),$512./Is the block full?
	blo	0f		/No
	call	__wvb		/Yes, write it out
	add	$1,V_RBLK+2(r4)	/Fix
	adc	V_RBLK(r4)	/Blocknumber
	clr	V_RBYT(r4)	/And start at byte 0.

0:	return			/Return

/
/ Handshaking.
/ On the 7221, the call to `fhandshake' has set
/ handshake mode 2 with a trigger character of
/ 1. Blast it down the line and wait for the
/ single character response.
/ On the 2649, send an ENQ and wait for the ACK.
/ In reality, we don't check for the ACK at
/ all. 
/ No, you cannot use an ENQ on the 7221 and have
/ 1 routine. The 7221 always ACK's an ENQ regardless
/ of what state it is in.
/

h7221:	mov	r0,-(sp)	/7221 entry
	mov	$soh,r0
	br	0f

h2649:	mov	r0,-(sp)	/2649 entry
	mov	$enq,r0

0:	mov	r1,-(sp)

	clr	-(sp)		/Send out SOH
	clr	-(sp)
	clr	-(sp)
	clr	-(sp)
	mov	$1,-(sp)
	mov	r0,-(sp)
	mov	$IO.WAL,r0
	call	__qiow
	bcs	0f

	clr	-(sp)
	clr	-(sp)
	clr	-(sp)
	clr	-(sp)
	mov	$1,-(sp)
	mov	$hbf,-(sp)
	mov	$IO.RAL,r0
	call	__qiow

0:	mov	(sp)+,r1
	mov	(sp)+,r0
	return
