	.TITLE	MBTST2
	.ENABL	GBL
	.NLIST	BEX
	.ENABL	LC
;
;+
;*****
;
;	MBTST2 - Performance test of MB: driver...talks to
;	 itself via default queue named for task name.  Uses
;	 outstanding read mechanism for I/O.
;
;*****
;-
TI$EFN==1
TI$LUN==1
MB$EFN==2
MB$LUN==2
;
	.MCALL	EXST$S,QIOW$S,ALUN$S,ASTX$S,QIO$S,DIR$,QIOW$,QIO$
	.mcall	MBIO$
	MBIO$
;
	.PSECT	$IDATA,RW,D,LCL,CON,REL
;
IDAT:			; INPUT DATA ARRAY
	.BLKW	8194.		; MAKE SURE IT WRAPS OVER 4KW BOUND TO CHECK
				;  $BLXIO FUNCTIONING
	L.IDAT=.-IDAT
ODAT:			; OUTPUT DATA ARRAY
	.BLKW	8192.
	L.ODAT=.-ODAT
INQIO:
	QIO$	IO.RLB,MB$LUN,,,ISB,,<IDAT,L.IDAT>
ISB:			; INPUT I/O STATUS BLOCK
	.BLKW	2
OUTQIO:
	QIOW$	IO.WLB,MB$LUN,MB$EFN,,OSB,,<ODAT,L.ODAT>
OSB:			; OUTPUT I/O STATUS BLOCK
	.BLKW	2
;
M0:
.ASCII	&MBTST2 -- Outstanding read I/O performance test for MB: driver&
	L.M0=.-M0
	.EVEN
;
	.PSECT	$PCODE,RO,I,LCL,CON,REL
;
MBTST2::
	ALUN$S	#TI$LUN,#"TI,#0	; ASSIGN LUN TO TI:
	ALUN$S	#MB$LUN,#"MB,#0	; ASSIGN LUN TO MB:
	BCC	5$
	CALL	DSWSTA		; show directive status
	JMP	EXIT		; and quit
;
5$:
	QIOW$S	#IO.WLB,#TI$LUN,#TI$EFN,,,,<#M0,#L.M0,#40>
	MOV	#OSB,R0		; use output status block
	QIOW$S	#IO.ARD,#MB$LUN,#MB$EFN,,R0,,<>
	CALL	IOSTA		; display status
	TSTB	(R0)		; check status
	BMI	EXIT		; quit if it fails
	QIOW$S	#IO.AWR,#MB$LUN,#MB$EFN,,R0,,<,>
	CALL	IOSTA		; display status
	TSTB	(R0)		; check status
	BMI	EXIT		; quit if it fails
;
; *** Ask for QIO block count; then use "TIMER" routines to
;	determine elapsed time for QIO's
;
LOOP:
	CALL	GETCMD
	BCS	EXIT		; quit on exit request
	MOV	#2,R0		; setup 100 Khz time base
	CALL	.TMINI		; init timer
	BCS	EXIT
	MOV	#1000.,R5	; setup loop counter
10$:
	CALL	.TMSTR		; start timer rolling
	DIR$	#INQIO		; issue read
	DIR$	#OUTQIO		; issue write
	CALL	.TMSTP		; stop time...
	MOV	#OSB,R0		; get status
	TSTB	(R0)		; check completion
	BPL	18$		; branch if worked
	CALL	IOSTA		; display problem
	BR	EXIT		;  and quit	
	MOV	#ISB,R0
	TSTB	(R0)		; check completion
	BPL	18$		; branch if worked
	CALL	IOSTA		; display problem
	BR	EXIT		;  and quit	
18$:
;	CALL	.TMDSP		; display result
	SOB	R5,10$
20$:
	CALL	.TMDSP		; queue last display
	BCS	20$		; loop til taken
	CALL	.TMEXI		; wait for last display
	BR	LOOP
EXIT:
	CALL	.TMSTP		; make sure timer's stopped
	QIOW$S	#IO.DEA!SF.ALL,#MB$LUN,#MB$EFN	; deaccess all MBX's
	EXST$S	#EX$SUC		;  and exit

;
	.page
	.sbttl	Local Subroutines
;
; *** GETCMD - Prompt user for message string.  Input handled at AST level;
;	 any valid input string received with FLAG = 0 defines the
;	 transfer block count
;	 forces program into 'master' mode and immediately starts transmitting
;	 data to partner DR11.  Once started in either master or slave
;	 mode, read-qio is kept outstanding as a way for user abort via
;	 "esc" or "CTRL-Z".  Abort is indicated by not re-queueing the
;	 read-qio so EX$EFN will remain set when exit AST.
;
	.psect	$IDATA,RW,D,LCL,CON,REL
;
TIIOSB:			; I/O status block
	.blkw	2
TIBUF:
	.BLKB	80.
	L.TIBF=.-TIBUF
;
PROMPT:
	.ASCII	<15>/Enter block size in bytes to initiate data echo test : /
	.ASCII	<15><12>/*/
	L.PRMT=.-PROMPT
;
SYNERR:
	.ASCII	/?? Invalid block buffer size ??/
	L.SYNE = .-synerr
	.even

	.PSECT	$PCODE,RO,I,LCL,CON,REL
GETCMD:
1$:
	QIO$S	#IO.WLB,#TI$LUN,,,,,<#PROMPT,#L.PRMT,#'$>	; prompt user
	QIOW$S	#IO.RLB,#TI$LUN,#TI$EFN,,#TIIOSB,,<#TIBUF,#L.TIBF>
	TSTB	TIIOSB			; check completion status
	BMI	18$			; branch if bad
	MOV	TIIOSB+2,R1		; anything read ??
	BLE	1$			; branch if no, re-prompt
	MOV	#TIBUF,R0		; get input string address
	CLRB	TIBUF(R1)		; set terminator
	CALL	$CDTB			; convert to binary
	CMP	R1,#L.IDAT-4		; check against max buffer size
	BHI	18$			; branch if invalid
	MOV	R1,OUTQIO+Q.IOPL+2	; setup output size
	CLC				; show success
	BR	19$			;  and exit
18$:
	SEC				; show problems
19$:
	RETURN

;
	.page
	.sbttl	MBDRV Unsolicited input handler
;
; *** MBATA - Unsolicited input AST from Mailbox;  echo sender's name and
;	 message byte count
;
	.PSECT	$IDATA,RW,D,LCL,CON,REL
ATATMP:
	.BLKW	3			; AST temporary storage
ATAM1:
	.ASCII	<15>/Unsolicited input from /
ATNAM:	.BLKB	6			; place for sender's task name
	.ASCII	/; byte count = /
ATCNT:	.BLKB	7			; place for unsigned input data
	L.ATM1=.-ATAM1
	.EVEN
;
	.PSECT	$PCODE,RO,I,LCL,CON,REL
MBATA::			; ATTENTION AST
	MOV	(SP)+,ATATMP	; copy byte count
	MOV	(SP)+,ATATMP+2	; pop 1st half of name
	MOV	(SP),ATATMP+4	; pop 2nd half of name
	MOV	R0,(SP)		; free R0-R2
	MOV	R1,-(SP)
	MOV	R2,-(SP)
	MOV	#ATNAM,R0	; get place for ASCII task name
	MOV	ATATMP+2,R1	; get name
	CALL	$C5TA		; convert it to ascii
	MOV	ATATMP+4,R1	; get 2nd half of name
	CALL	$C5TA		; convert it to ascii
	MOV	#ATCNT,R0	; get place for byte count
	MOV	ATATMP,R1	; get byte count
	CLR	R2		; enable 0 suppression
	CALL	$CBDMG		; convert to decimal
	MOVB	#'.,(r0)	; show decimal radix
	MOV	#ATAM1,R1	; get start address of message
	SUB	R1,R0		; compute byte count
	QIOW$S	#IO.WLB,#TI$LUN,#TI$EFN,,,,<R1,R0,#40>
	MOV	(SP)+,R2	; recover registers
	MOV	(SP)+,R1
	MOV	(SP)+,R0
	ASTX$S
;
	.page
	.sbttl	Information Message Format Routines
;
; *** DSWSTA - Prints contents of directive status word to TI:
;
;	R0-R2 destroyed !!
;
	.PSECT	$IDATA,RW,D,LCL,CON,REL
DSWMSG:
	.ASCII	/Directive status = /
ADSW:	.BLKB	8.
	.EVEN
;
	.PSECT	$PCODE,RO,I,LCL,CON,REL
;
DSWSTA::
	MOV	#ADSW,R0		; get place for dsw string
	MOV	@#$DSW,R1		; get directive status word
	CLR	R2			; enable 0 suppression
	CALL	$CBDSG			; convert it decimal
	MOVB	#'.,(R0)+		; insert radix indicator
	MOV	#DSWMSG,R1		; get message start address
	SUB	R1,R0			; compute string length
	QIOW$S	#IO.WLB,#TI$LUN,#TI$EFN,,,,<R1,R0,#40>
	RETURN
;
; *** IOSTA - Reports state of I/O status block pointed to by R0.
;
;	R0-R2 destroyed !!
;
	.PSECT	$IDATA,RW,D,LCL,CON,REL
;
IOSMSG:
	.ASCII	&I/O Status Block = &
AIOSB:	.BLKB	20.
	.EVEN
;
	.PSECT	$PCODE,RO,I,LCL,CON,REL
;
IOSTA::
	MOV	R0,-(SP)		; save I/O status block address
	MOVB	(R0),R1			; pickup status byte
	MOV	#AIOSB,R0		; get place to build string
	CLR	R2			; enable 0 suppression
	CALL	$CBDSG			; convert it decimal
	MOVB	#'.,(R0)+		; insert radix indicator
	MOVB	#40,(R0)+		; insert delimiter
	MOVB	#40,(R0)+
	MOV	(SP),R1			; pickup status block address
	MOVB	1(R1),R1		; get top byte of 1st word
	MOV	PC,R2			; disable 0 suppression
	CALL	$CBTMG			; convert to unsigned octal
	MOVB	#40,(R0)+		; insert delimiter
	MOVB	#40,(R0)+
	MOV	(SP),R1			; pickup status block again
	MOV	2(R1),R1		; get 2nd word	
	MOV	PC,R2			; disable 0 suppression
	CALL	$CBOMG			; convert to unsigned octal
	MOV	#IOSMSG,R1		; get message start address
	SUB	R1,R0			; compute string length
	QIOW$S	#IO.WLB,#TI$LUN,#TI$EFN,,,,<R1,R0,#40>
	MOV	(SP)+,R0		; recover status block addr
	RETURN

;
	.END	MBTST2
