;++
;
; Installation notes:
;
;	This program performs the general functions of a device symbiont
; under VAX/VMS. It is designed to perform multiple forms of output to the
; device, in keeping with the Varian plotter for which it was written, on 
; which both plots can be made, and alphanumeric text generated for the
; printing of files.
;
; Files entered on the queues have a specific format, based on the 
; implementation of the plot-queueing command at the JCF. The symbiont
; recognizes such files, and processes them in a special way; ie each record
; is assumed to contain a specification of a file to plot; that file is then
; plotted by calling the routine PLOT_VARIAN. Plot_varian is not supplied;
; and can be locally implemented in specific for the devices desired.
;
; If there are any problems, please feel free to contact us at:
; 	Joint Computer Facility
;	Room 1-106
;	Massachusettes Institue of Technology
;	Cambridge, Mass, 02139
;	Phone:  (617) 253-2041
;

	.title VSMB   VAX/VMS VARIAN SYMBIONT
	.ident /01.1/


;++
; FACILITY:     VAX/VMS VARIAN SYMBIONT
;
; ABSTRACT:     This program serves as the sybmiont to control
;		the Varian electrostatic plotter.
;
; ENVIRONMENT:  NATIVE/USER MODE NON-PRIVILEGED CODE
;
; AUTHOR:       Neal Lippman, MIT-JCF,  CREATION DATE: 22-JUN-80
;
; MODIFIED BY:
;
; 7/16/80       [NL001] -- Do form feed on resume/top_of_file
;
;--

	.page
	.sbttl Data segment declaration

.library \sys$library:lib\

;
;macros:
;

;
;program section declaration macros:
;
; arguments are:
;
;       1) NAME = psect section name             
;       2) ALIGN = alignment keyword (d=LONG)
;
; generate a pure section -- code and read only data
;


	.macro pure_section     name=vsmb_pure,align=long
	.psect  name,rd,nowrt,exe,align
	.endm  pure_section

;generate an inpure section -- read/write data

	.macro impure_section   name=vsmb_impure,align=long
	.psect  name,rd,wrt,noexe,align
	.endm  impure_section

;
;macros for error signalling:
;

	.macro signal   condition,p1,p2,p3,p4,p5,p6,p7,p8

	$$$args=1
	.irp    arg,<p8,p7,p6,p5,p4,p3,p2,p1>
	.if     nb arg
	pushl   arg
	$$$args=$$$args+1
	.endc
	.endr

	pushl   #condition
	calls   #$$$args,lib$signal

	.endm   signal

;
; system wide symbolic name definitions:
;

	$shrdef         ;shared message definitions
	$opcdef         ;opcom definitions
	$jbcmsgdef      ;job controller message definitions
	$iodef          ;I/O function code definitions
	$pcbdef         ;process control block definitions
	$msgdef         ;message definitions
	$fabdef         ;file access block definitions
	$rabdef         ;record access block definitions
	$namdef         ;name block definitions
	$dibdef         ;device information block offsets
	$chfdef         ;condition handling facility definitions
	$rmsdef         ;define RMS status codes
	$accdef         ;accounting values

;
; definition of message modifiers   
;

	$gblini
	$defini mod

	$equlst mod__,,1,8,<-
		<success>-              ;success
		>

	$equlst mod__,,4,8,<-
		<abort>-                ;printing aborted
		<rmserr>-               ;error from RMS
		<varerr>-               ;varian device error
		>

	$defend mod 

;
; a few constants:
;

vsmb_k_usernamesz=12                    ;size of username string
vsmb_c_bufsz=256                        ;size of cruft buffer
 

;
; define symbiont states:
;

	$defini state

	$equlst state__,,0,1,<-
		<idle>-                 ;symbiont idle
		<asndev>-               ;assigning device
		<suspend>-              ;suspended
		<active>-               ;plotting file
		<done>-                 ;doing rundown
		<open>-                 ;opening file
		>

	$defend state


;
; define offset to delete flag in flag byte of symbiont message
;

	$vield  pqr,0,<-
		<delete,,m>,-   ;delete flag
		>               ;ignore rest of flags


;   
; define message from job controller format
;

	$defini sim


$def sim$w_msgtyp       .blkw   1       ;symbiont manager message type code

$def sim$w_rest         .blkw   1       ;rest of short messages

$def sim$l_uic          .blkl   1       ;UIC of requesting process

$def sim$t_usernam      .blkb   vsmb_k_usernamesz
					;username, not counted, blank filled

$def sim$q_qtime        .blkq   1       ;time job was queued

$def sim$t_volnam       .blkb   16      ;device ID field - counted string

$def sim$g_fileid       .blkb   6       ;file ID field

$def sim$g_dirid        .blkb   6       ;directory ID field

$def sim$b_flags        .blkb   1       ;file print flags
	 
$def sim$b_filcopy      .blkb   1       ;number of copies to print

$def sim$w_pagcnt       .blkw   1       ;max pages to print

$def sim$t_prtnam       .blkb   16      ;device name for printing - counted
					;string

$def sim$t_filnam       .blkb   20      ;filename to print - counted string

$def sim$t_acntname     .blkb   16      ;user's account name

$def sim$k_size                         ;size of this structure


	$defend sim


vsmb_mbefn = 0                          ;event flag for send to JBC mailbox


;
; define symbiont global data base
;


	$defini vsd


$def    vsd_w_mbchan    .blkw 1         ;mailbox input channel

$def    vsd_b_state     .blkb 1         ;current state

$def    vsd_w_unit      .blkw 1         ;mailbox unit

$def    vsd_q_userdesc  .blkq 1         ;username descriptor

$def    vsd_t_simmsg    .blkb   sim$k_size ;simbiont message buffer

$def    vsd_w_jbcchan   .blkw 1         ;JBC mailbox channel

$def    vsd_g_msgtomgr                  ;message to job controller
$def    vsd_t_tbuf      .blkb vsmb_c_bufsz      ;temp buffer
	
$def    vsd_q_iosb      .blkq 1         ;an I/O status block

$def    vsd_w_vchan     .blkw 1         ;channel to plot to

$def    vsd_b_dcode     .blkb 1         ;dispatch code for processing routine

$def    vsd_b_err_flags .blkb 1         ;error flags

	_vield  vsd,0,<-
			<abort,,m>,-    ;aborting   
			<geterr,,m>,-   ;error getting a record
			<openerr,,m>,-  ;error opening file
			<varerr,,m>,-   ;error on output device
			<vplot,,m>-     ;file is a varian plot specification
			>               ;file (from plot command)
			 
;adjacency of the next two assumed

$def    vsd_q_plotdata                  ;accounting info

$def    vsd_l_numvecs   .blkl 1         ;number of vectors plotted

$def    vsd_l_numplots  .blkl 1         ;number of plots made

.=<.+3>&-4              ;long word align
$def    vsd_g_fab       .blkb fab$c_bln ;fab for file

$def    vsd_g_rab       .blkb rab$c_bln ;rab for file

$def    vsd_g_nam       .blkb nam$c_bln ;name block to open file by file ID

$def    vsd_w_mbreadlen .blkw 1         ;length of read from mailbox

$def    vsd_k_size                      ;size of this data structure


	$defend vsd


	.page
	.sbttl Condition Handler
;++
; FUNCTIONAL DESCRIPTION:
;
;       Condition Handler for the VAX/VMS Varian symbiont.
;       It sends the appropriate messages to 
;       the operator(s), and exits on a system error or returns to the
;       symbiont on a signalled condition.
;
; CALLING SEQUENCE:
;
;       Entered when and exception occurs, or when an error is signalled.
;       Called by CALLS/G by condition handling facility
;
; INPUT PARAMETERS:
;
;       As per condition handling standard
;
; IMPLICIT INPUTS:
;
;       None 
;
; OUTPUT PARAMETERS:
;
;       None
;
; IMPLICIT OUTPUTS:
;
;       None
;
; COMPLETION CODES:
;
;       None
;
; SIDE EFFECTS:
;
;       On system error, symbiont is exited
;
;--

;own storage

	impure_section

sig_name:       .blkl 1
       

	pure_section  

facility_desc:
	     
	.long 20$-10$
	.long 10$
10$:
	.ascii /VARSMB/
20$:

;storage for signal name



	.page

vsmb_handler:
	.word   ^m<r2,r11>                      ;entry mask
	movl    chf$l_sigarglst(ap),r2          ;get addr of signal argument
						;list
	subw2   #2,chf$l_sig_args(r2)           ;don't pass PC,PSL
	movl    chf$l_sig_name(r2),sig_name     ;save signal name
	pushaq  facility_desc                   ;push facility name
	pushaw  putmsg_action                   ;push putmsg action routine
	pushl   r2                              ;push addr of signal arg list
	calls   #3,g^sys$putmsg                 ;call putmgs facility
	tstw    sig_name+2                      ;system exception (=0)
	bneq    10$                             ;branch if not
	$exit_s                                 ;else exit
10$:
	ret

;
; putmsg action routine
;
putmsg_action:
	.word   ^m<r2,r3,r6>                    ;entry mask
	movl    4(ap),r2                        ;get addr of message
						;descriptor
	movzbl  #120,r6                         ;assume max message length
	cmpw    (r2),r6                         ;compare with actual len
	bgeq    5$                              ;branch if greater -- truncate
	movzwl  (r2),r6                         ;else use actual length
5$:
	subl2   r6,sp                           ;make room on stack for
	movc3   r6,@4(r2),(sp)                  ;move string onto stack
	pushl   #0                              ;no reply ID
	movzwl  #opc$_rq_rqst!-                 ;request type
			<<opc$m_nm_centrl!-     ;send to central
			  opc$m_nm_device!-     ;send to device
			  opc$m_nm_print>-      ;send to print
			@8>,-(sp)
	pushl   sp                              ;create descriptor
	addl3   r6,#8,-(sp)                     ;...
	movl    sp,r0                           ;get descriptor addr
	$sndopr_s       (r0)                    ;send message to opers 
	clrl    r0                              ;inhibit sending to sys$output
						;and sys$error
	ret


	.page
	.sbttl  Initialization Routine

;++
; FUNCTIONAL DESCRIPTION:
;
;       Once only init routine          
;
; CALLING SEQUENCE:
;
;       Entered as main symbiont entry point
;
; INPUT PARAMETERS:
;
;       None
;
; IMPLICIT INPUTS:
;
;       None
;
; OUTPUT PARAMETERS:
;
;       r11 = address of symbiont data base
;
; IMPLICIT OUTPUTS:
;
;       Init done message send to Job Controller
;       Channel assigned to Job Controller's mbox
;       Mailbox created to recieve messages
;
; COMPLETION CODES:
;
;       None
;
; SIDE EFFECTS:
;
;       None
;
;--

;own data  

jbcmailbox:     ;name of job controller's mailbox

	.long 20$-10$
	.long 10$

10$:    .ascii /_/
	.long sys$c_jobctlmb
	.ascii /:/
20$:


vsmb_start::
	.word 0                         ;entry mask
	moval   vsmb_handler,(fp)       ;set condition handler in stack frame
	$setast_s       #0              ;disable AST delivery during init
	moval   vsd_g_data,r11          ;set address of data base
	movb    #state__idle,vsd_b_state(r11) ;set state initially to idle

;
; assign channel to job controller's mailbox
;
	$assign_s       jbcmailbox,-    ;device to assign to
			vsd_w_jbcchan(r11)      ;addr for channel
	blbs    r0,20$                  ;successful?
	signal  jbc$_mbasgn,#0,r0       ;signal the error
10$:
	$exit_s                         ;exit

;
; create symbiont's mailbox
;
20$:
	$crembx_s       -               ;create the mbox
		promsk=#0,-             ;protection
		maxmsg=#sim$k_size,-    ;max size of message
		bufquo=#2*sim$k_size,-  ;two messages, max
		chan=vsd_w_mbchan(r11)  ;addr for channel
	blbs    r0,30$                  ;success?
	signal  jbc$_symbcre,#0,r0      ;signal the error
	brb     10$                     ;and exit

30$:

;
; init some values in the data segment
;

	clrb    vsd_b_err_flags(r11)    ;clear all flags
	moval   vsd_g_fab(r11),r6       ;get fab addr
	moval   vsd_g_rab(r11),r7       ;get rab addr
	moval   vsd_g_nam(r11),r8       ;get nam block addr
	movb    #fab$c_bid,fab$b_bid(r6);create fab
	movb    #fab$c_bln,fab$b_bln(r6);...
	movb    #rab$c_bid,rab$b_bid(r7);create rab
	movb    #rab$c_bln,rab$b_bln(r7);...
	movb    #nam$c_bid,nam$b_bid(r8);create nam block
	movb    #nam$c_bln,nam$b_bln(r8);...
	movl    r8,fab$l_nam(r6)        ;set nam block addr in fab
	movl    r6,rab$l_fab(r7)        ;set fab addr in rab
	movl    #fab$m_nam,fab$l_fop(r6);set nam block open in fab
	movw    #sim$k_size,vsd_w_mbreadlen(r11) ;set initial mbox read length

;
; get mailbox channel info
;
	movw    vsd_w_mbchan(r11),r0    ;get channel number
	subl2   #dib$k_length,sp        ;make buffer on stack
	movl    sp,r2                   ;r2 is buffer pointer
	pushl   r2                      ;push addr on stack
	movzwl  #dib$k_length,-(sp)     ;and put length on
	movl    sp,r1                   ;get descriptor address
	$getchn_s       chan=r0,-       ;channel
			scdbuf=(r1)     ;buffer
	movw    dib$w_unit(r2),vsd_w_unit(r11) ;save unit number

;  
; set unsolicited AST to jbc mailbox
;

	bsbw    vsmb_setmbast
	movw    vsd_w_unit(r11),r0      ;get unit number of our mailbox
	bsbw    vsmb_init_done          ;send init done message

	$setast_s       #1              ;enable ASTs

	brw     vsmb_main               ;enter main loop


	.page
	.sbttl Subroutines -- Uic routines
;++
; FUNCTIONAL DESCRIPTION:
;
;       These routines are used to set/restore the symbiont's UIC
;
; CALLING SEQUENCE:
;
;       BSB/JSB            
;               Registers:
;                               r0,r1 -- scratch
;
; INPUT PARAMETERS:
;
;       r11 = address of data segment
;
; IMPLICIT INPUTS:
;
;       Requestor's UIC in the symbiont start print message buffer
;
; OUTPUT PARAMETERS:
;
;       None
;
; IMPLICIT OUTPUTS:
;
;       None
;
; COMPLETION CODES:
;
;       None
;
; SIDE EFFECTS:
;
;       The symbiont's UIC is set/reset
;
;--

.enabl lsb

vsmb_setuic:
	movl    sim$l_uic+vsd_t_simmsg(r11),r5  ;get uic of requestor
	brb     10$

vsmb_restoreuic:
	movl    #<<1@16>+4>,r5                  ;get our uic [1,4]
10$:    $cmkrnl_s       routin=20$              ;set the uic
	rsb

20$:                            ;kernel mode routine to set uic
	.word 0                         ;save no regs
	movl    @#sch$gl_curpcb,r1      ;get PCB addr
	movl    r5,pcb$l_uic(r1)        ;set the uic
	movl    #1,r0                   ;must return success
	ret

.dsabl lsb


	.page
	.sbttl  Subroutine -- Accounting Routine
;++
; FUNCTIONAL DESCRIPTION:
;
;       This routine sets up an accounting information buffer
;       for the accounting system and used the sndacc system service
;       to submit it.
;
; CALLING SEQUENCE:
;
;       BSB/JSB              
;               Registers:
;                               r2 = movc5 destroyed
;                               r3 = descriptor address,scratch
;                               r4,r5 - movc5 destroyed
;                               r6 = buffer pointer
;       ***These registers are restored on exit
;
; INPUT PARAMETERS:
;
;       r11 = address of data segment
;
; IMPLICIT INPUTS:
;
;       Data in data segment
;
; OUTPUT PARAMETERS:
;
;       None
;
; IMPLICIT OUTPUTS:
;
;       None
;
; COMPLETION CODES:
;
;       None
;
; SIDE EFFECTS:
;
;       None
;
;--


;      
; some symbols defns
;

space=^a/ /
vectors=31              ;bucket # for vectors
plots=30                ;bucket # for plots
acc$k_genlchg=^x1111    ;general charge code (JCF defined)

acc_varcharge:  .long   ^x200           ;code for varian charges
pure_section
vsmb_account:
	pushr   #^m<r2,r3,r4,r5,r6>     ;save registers
	subl2   #132,sp                 ;make buffer on stack
	movl    sp,r6                   ;r2 is buffer pointer 
	movw    #acc$k_insmesg,0(r6)    ;insert message code
	movw    #130,2(r6)              ;used by JCF accounting system
	movw    #acc$k_genlchg,4(r6)    ;general charge
	clrw    6(r6)                   ;zero fill
	movl    acc_varcharge,8(r6)     ;varian charge
	movc3   #12,vsd_t_simmsg+sim$t_usernam(r11),12(r6)
	movl    #plots,24(r6)           ;code for plots
	movl    vsd_l_numplots(r11),28(r6) ;number of plots
	movl    #vectors,32(r6)         ;code for vectors
	movl    vsd_l_numvecs(r11),36(r6) ;number of vectors
	movc5   #0,0,#0,#92,40(r6)      ;zero fill the rest
	pushl   r6                      ;create descriptor on stack
	movzbl  #132,-(sp)              ;...
	movl    sp,r3                   ;get descriptor address
	$sndacc_s      (r3)             ;send the accounting buffer     
	blbs    r0,30$                  ;br if okay
	signal  jbc$_acntwrt,#0,r0      ;signal the error
30$:    addl3   #132,r6,sp              ;pop buffer off stack
	popr    #^m<r2,r3,r4,r5,r6>     ;pop regies
	rsb

     
	.page
	.sbttl Subroutines -- Send messages to Job Controller
;++
; FUNCTIONAL DESCRIPTION:
;
;       This routines sends the init done message to the Job Controller
;
; CALLING SEQUENCE:
;
;       BSB/JSB            
;
;               Registers:
;                       r0,r1 -- scratch
;
; INPUT PARAMETERS:
;
;       r0 = unit number of symbiont's mailbox
;       r11 = address of data base
;
; IMPLICIT INPUTS:
;
;       None
;
; OUTPUT PARAMETERS:
;
;       None
;
; IMPLICIT OUTPUTS:
;
;       Init done message sent
;
; COMPLETION CODES:
;
;       None
;
; SIDE EFFECTS:
;
;       None
;
;--

vsmb_init_done:
	movw    r0,vsd_g_msgtomgr+2(r11)  ;set mb unit in buffer
	movw    #msg$_smbini,vsd_g_msgtomgr(r11) ;set init_done message type
	$qiow_s -                       ;send the message
		efn=#vsmb_mbefn,-       ;event flag
		chan=vsd_w_jbcchan(r11),-;channel
		func=#io$_writevblk!io$m_now,- ;write with no wait
		iosb=vsd_q_iosb(r11),-  ;iosb
		p1=vsd_g_msgtomgr(r11),-        ;message
		p2=#4                   ;length
	blbc    r0,20$                  ;error?
	movzwl  vsd_q_iosb(r11),r0      ;get I/O status
	blbs    r0,30$                  ;br if okay 
20$:    signal  jbc$_mbwrite,#0,r0      ;signal the error
30$:
	rsb
;++
; FUNCTIONAL DESCRIPTION:
;
;       This routine is called to send a file_done message to the
;       Job Controller
;
; CALLING SEQUENCE:
;
;       BSB/JSB            
;
;               Registers:
;                       r0-r5   are destroyed 
;
; INPUT PARAMETERS:
;
;       r3 = reason for termination
;       r11 = address of data segment
;
; IMPLICIT INPUTS:
;
;       None
;
; OUTPUT PARAMETERS:
;
;       None
;
; IMPLICIT OUTPUTS:
;
;       None
;
; COMPLETION CODES:
;
;       None
;
; SIDE EFFECTS:
;
;       Mailbox read length is reset to init message length
;
;--


vsmb_file_done:
	movw    #msg$_smbdon,vsd_g_msgtomgr(r11) ;set message done code
	movw    r3,vsd_g_msgtomgr+2(r11)        ;set reason code
	movc5   #0,0,#0,#14,vsd_g_msgtomgr+4(r11) ;zero fill rest
	$qiow_s -                               ;send the message
		efn=#vsmb_mbefn,-               ;event flag number
		chan=vsd_w_jbcchan(r11),-       ;channel
		func=#io$_writevblk!io$m_now,-  ;write with no wait
		iosb=vsd_q_iosb(r11),-          ;iosb
		p1=vsd_g_msgtomgr(r11),-        ;buffer
		p2=#16                          ;len
	blbc    r0,20$                          ;error?
	movzwl  vsd_q_iosb(r11),r0              ;get iosb
	blbs    r0,30$                          ;okay?
20$:    signal  jbc$_mbwrite,#0,r0              ;signal the error
30$:
	movw    #sim$k_size,vsd_w_mbreadlen(r11) ;reset mb read length to max
	rsb


	.page
	.sbttl  Subroutine -- Set mailbox AST
;++
; FUNCTIONAL DESCRIPTION:
;
;       This routine sets an unsolicited AST on the Job Controller's
;       mailbox
;
; CALLING SEQUENCE:
;
;       BSB/JSB             
;
;               Registers:
;                       r0 destroyed
; INPUT PARAMETERS:
;
;       None
;
; IMPLICIT INPUTS:
;
;       r11 = address of data segment
;
; OUTPUT PARAMETERS:
;
;       None
;
; IMPLICIT OUTPUTS:
;
;       None
;
; COMPLETION CODES:
;
;       None
;
; SIDE EFFECTS:
;
;       None
;
;--


vsmb_setmbast:
	$qiow_s -                       ;set unsolicited AST
		efn=#vsmb_mbefn,-       ;event flag
		chan=vsd_w_mbchan(r11),-;channel
		func=#io$_setmode,-     ;set mode function
		iosb=vsd_q_iosb(r11),-  ;iosb
		p1=vsmb_mbast           ;AST routine
	blbc    r0,10$                  ;error?
	movzwl  vsd_q_iosb(r11),r0      ;get iosb
	blbs    r0,20$                  ;okay?
10$:    signal  jbc$_mbsetast,#0,r0     ;signal the error
20$:    rsb


	.page
	.sbttl  Subroutines -- FORTRAN support routines
;++
; FUNCTIONAL DESCRIPTION:
;
;       This routine is for use by FORTRAN routines. It sets the device
;       error flag, and signals the input error.
;
; CALLING SEQUENCE:
;
;       CALLS/G             
;
; INPUT PARAMETERS:
;
;       @4(ap) = condition code to signal
;
; IMPLICIT INPUTS:
;
;       None  
;
; OUTPUT PARAMETERS:
;
;       None
;
; IMPLICIT OUTPUTS:
;
;       None
;
; COMPLETION CODES:
;
;       None
;
; SIDE EFFECTS:
;
;       The VARERR bit in the error flags is set
;
;--

;
; Note that the address of the data segment is reset, as the status of
; the registers is unpredictable on entry.
;

vsmb_prterr::
	.word   ^m<r11>        ;entry mask 
	moval   vsd_g_data,r11  ;set address of data segment
	bisb    #vsd_m_varerr,vsd_b_err_flags(r11)
				;set the device error bit
	signal  jbc$_printout,#0,@4(ap) ;signal the error
	ret
;++
; FUNCTIONAL DESCRIPTION:
;
;       This routine is called by FORTRAN routines to check the abort
;       bit in the error flags.
;
; CALLING SEQUENCE:
;
;       CALLS/G             
;
; INPUT PARAMETERS:
;
;       None
;
; IMPLICIT INPUTS:
;
;       None 
;
; OUTPUT PARAMETERS:
;
;       None
;
; IMPLICIT OUTPUTS:
;
;       None
;
; COMPLETION CODES:
;
;       The value of the abort bit is returned (0/1)
;
; SIDE EFFECTS:
;
;       None
;
;--

;
; Note that the address of the data segment is reset, as the status of
; the registers is unpredictable on entry.
;

vsmb_chkabort::
	.word   ^m<r11>         ;entry mask
	clrl    r0              ;assume not set
	moval   vsd_g_data,r11  ;get address of data segment
	bbc     #vsd_v_abort,vsd_b_err_flags(r11),10$ ;branch if not set
	incl    r0              ;return set
10$:    ret


	.page
	.sbttl Symbiont Mainline 
;++
; FUNCTIONAL DESCRIPTION:
;
;       This is the symbiont mainline. It is entered directly from
;       the init routine, and loops around, processing files.
;
; CALLING SEQUENCE:
;
;       BR                  
;
; INPUT PARAMETERS:
;
;       None
;
; IMPLICIT INPUTS:
;
;       r11 = address of data segment
;       At wake, the file is open, and the dispatch code is in the data 
;       segment; a channel has been assigned to the requested device.
;
; OUTPUT PARAMETERS:
;
;       None
;
; IMPLICIT OUTPUTS:
;
;       None
;
; COMPLETION CODES:
;
;       None
;
; SIDE EFFECTS:
;
;       The file is plotted/printed as requested.
; 
;--


;     
; this is the data segment
;

	impure_section

vsd_g_data::
	.blkb   vsd_k_size   


	pure_section


;
; declaration of processing routine dispatch table.
; 
; the first byte of each record of a file placed on the queue
; contains a dispatch code which specifies the routine
; to be used to process the file.
;


dispatch_table:                 ;used to dispatch to processing routine
	.long   vsmb_vplot      ;plot specification file
max_d=1


vsmb_main:
	moval   dispatch_table,r2       ;get addr of dispatch table
10$:
	$hiber_s                        ;wait for something todo
	   
	movzbl  vsd_b_dcode(r11),r4     ;get dispatch code
	cmpb    #max_d,r4               ;is it valid?
	bgtr    15$                     ;br onward if okay
	signal  vmg_invdcod             ;signal the error
	brb     10$                     ;and branch back
15$:
	movb    #state__active,vsd_b_state(r11)  ;set us active
	bbc     #vsd_v_openerr,vsd_b_err_flags(r11),35$                
					;br if opened successfully
	moval   vsd_t_simmsg+sim$t_filnam+1(r11),-(sp) ;push file name addr
	movzbl  vsd_t_simmsg+sim$t_filnam(r11),-(sp) ;push length of file name
	movl    sp,r3                   ;save descriptor address
	pushl   vsd_g_fab+fab$l_stv(r11) ;push RMS status value
	pushl   vsd_g_fab+fab$l_sts(r11) ;push RMS status code
	pushl   r3                      ;push filename descriptor
	pushl   #1                      ;one FAO arg
	pushl   #<4@16>!shr$_openin!4   ;condition code
	calls   #5,lib$signal           ;signal the error
	addl2   #8,sp                   ;pop the descriptor off the stack
	brw     90$                     ;and exit

;
; now dispatch to the appropriate processing routine
;
35$:
	movl    (r2)[r4],r3             ;get addr of routine to use  
	jsb     (r3)                    ;and subroutine to it


;
; perform rundown on file:
;
90$:
	$setast_s       #0              ;disable AST delivery
	tstw    vsd_g_fab+fab$w_ifi(r11) ;has open been done?
	beql    120$                    ;br if not
	bicl    #fab$m_dlt,vsd_g_fab+fab$l_fop(r11) ;clear delete bit
	tstw    vsd_g_nam+nam$w_did(r11);does file have a directory?
	beql    113$                    ;if no, delete, no matter what
	bbs     #vsd_v_abort,vsd_b_err_flags(r11),115$ ;br if aborting
112$:
	bbs     #vsd_v_vplot,vsd_b_err_flags(r11),113$  ;branch if plot file
	bbc     #pqr$v_delete,vsd_t_simmsg+sim$b_flags(r11),115$
					;branch if not delete
113$:   bisl    #fab$m_dlt,vsd_g_fab+fab$l_fop(r11) ;set delete bit 

115$:
	bsbw    vsmb_setuic             ;set UIC to requestor's
	$close  vsd_g_fab(r11)          ;close the file
	clrw    vsd_g_rab+rab$w_isi(r11) ;quick disconnect
	bsbw    vsmb_restoreuic         ;set uic back to [1,4]

;
; set ending status
;
120$:
	movzbl  #mod__rmserr,r3         ;assume input error
	bitb    #vsd_m_openerr!-        ;check open error,
		 vsd_m_geterr,-         ;get error
		 vsd_b_err_flags(r11)   ;was either set?
	bneq    130$                    ;br if no
	movzbl  #mod__varerr,r3         ;assume device error
	bbs     #vsd_v_varerr,vsd_b_err_flags(r11),130$
					;br if print error
	movzbl  #mod__abort,r3          ;set abort
	bbs     #vsd_v_abort,vsd_b_err_flags(r11),130$
					;br if aborting
	movzbl  #mod__success,r3        ;okay, successful

;
; final cleanup
;

130$:
	clrb    vsd_b_err_flags(r11)    ;reset all flags
	$dassgn_s       vsd_w_vchan(r11);deassign the varian
	movb    #state__idle,vsd_b_state(r11) ;set state to idle
	bsbw    vsmb_file_done          ;send file done message
	$setast_s       #1              ;enable ASTs
	brw     vsmb_main               ;and loop back for another go


	.page
	.sbttl  Plot Routine
;++
; FUNCTIONAL DESCRIPTION:
;
;       This routine is called to process a plot specification file
;       (input from the PLOT command).
;
; CALLING SEQUENCE:
;
;       BSB/JSB            
;
;               Registers:
;                       r0,r1 - scratch
;                       r2 - rab addr
;                       r8 - scratch
;                       r7 - scratch
;                       r9 - saved stack pointer
;                       r10 - buffer pointer
; INPUT PARAMETERS:
;
;       None
;
; IMPLICIT INPUTS:
;
;       r11 = addr of data segment
;       File is open on rab/fab
;
; OUTPUT PARAMETERS:
;
;       None
;
; IMPLICIT OUTPUTS:
;
;       None
;
; COMPLETION CODES:
;
;       None
;
; SIDE EFFECTS:
;
;       The file is processed.
;
;--


;
; define offsets into data record
;

delete=0
expan=1
copies=2

	.extrn  plot_varian

vsmb_vplot:
	movl    sp,r9           ;save SP for return
	subl2   #100,sp         ;make a buffer on stack
	movl    sp,r10          ;make R10 buffer pointer
	clrq    vsd_q_plotdata(r11) ;init vecs,plots
	moval   vsd_g_rab(r11),r2   ;get rab addr
	movl    r10,rab$l_ubf(r2)   ;set buffer addr in rab
	movw    #100,rab$w_usz(r2)  ;set buffer size in rab
	pushaw  vsd_w_vchan(r11);push channel address
	calls   #1,var$setchan  ;set channel addr in varutil common block

read:
	bitb    #vsd_m_varerr!vsd_m_abort,vsd_b_err_flags(r11)
				;are we aborting or device error?
	bneq    9$              ;branch if so
	$get    rab=(r2)        ;get a record
	blbs    r0,20$          ;success?
	cmpl    #rms$_eof,r0    ;end of file?
	beql    10$             ;br if so
	bisb    #vsd_m_geterr,vsd_b_err_flags(r11) ;set error bit
	brb     10$
9$: 
	bsbw     vsmb_form_feed  ;advance paper on varian

10$:
	movzbl  #state__done,vsd_b_state(r11) ;set done state
	bsbw    vsmb_account    ;do accounting
	movl    r9,sp           ;reset stack pointer
	rsb

20$:
	pushab  4(r10)          ;save address of file name string
	movzbl  3(r10),-(sp)    ;put length of filename on stack
	movl    sp,r8           ;save descriptor addr
	pushab  vsd_t_simmsg+sim$t_usernam(r11) ;push username addr
	movzwl  #12,-(sp)       ;push length of username
	pushl   sp              ;and save username address
	pushab  expan(r10)      ;push expansion count
	pushab  copies(r10)     ;push copy count
	pushab  delete(r10)     ;push delete flag  
	pushl   r8              ;push filename descriptor
	calls   #6,plot_varian  ;plot the file

	cmpl    #<-1>,r0        ;unsuccessful plot returns -1
	bneq    24$             ;br if successful
	pushab  vsd_t_simmsg+sim$t_usernam(r11) ;push username addr
	movzwl  #12,-(sp)       ;push length
	movl    sp,r7           ;save username addr
	pushl   r8              ;push filename descr
	pushl   r7              ;push username descr
	pushl   #2              ;fao count
	pushl   #vmg_filerr     ;push message code
	pushl   #4              ;argument count
	movl    sp,r7           ;get message vector addr
	pushaq  facility_desc   ;push facility name
	pushaw  vsmb_tell_varian ;push action routine
	pushl   r7              ;push message vector addr
	calls   #3,g^sys$putmsg ;call putmsg
	brw     25$             ;and loop
24$:
	addl2   r0,vsd_l_numvecs(r11) ;add in plotted vectors
	movzbl  copies(r10),r0  ;get copy count
	addl2   r0,vsd_l_numplots(r11)  ;add in number of plots
25$:    movl    r10,sp          ;reset stack pointer
	brw     read            ;and read the next record


	.page
	.sbttl  Subroutine -- assign channel to dev
;++
; FUNCTIONAL DESCRIPTION:
;
;       This routine assigns a channel to the device specified in the 
;       start print message
;
; CALLING SEQUENCE:
;
;       BSB/JSB            
;
;               Registers:
;                       r7 - buffer pointer
;                       r8 - device name string length    
;                       r9 - pointer to device name string
;               ***NOTE: r7-r9 are restored on exit
; INPUT PARAMETERS:
;
;       None
;
; IMPLICIT INPUTS:
;
;       r11 = addr of data segment
;       Device name string in symbiont start print message 
;
; OUTPUT PARAMETERS:
;
;       None
;
; IMPLICIT OUTPUTS:
;
;       None
;
; COMPLETION CODES:
;
;       The return code from the assign system service is returned in R0 
;
; SIDE EFFECTS:
;
;       A channel is assigned to the device
;
;--


vsmb_assigndev:
	pushr   #^m<r7,r8,r9>           ;save registers
	subl2   #20,sp                  ;make buffer on stack
	movl    sp,r7                   ;make r7 buffer pointer
	pushl   r7                      ;put addr on stack for descriptor
	movzbl  vsd_t_simmsg+sim$t_prtnam(r11),r8 ;get device name length
	movab   vsd_t_simmsg+sim$t_prtnam+1(r11),r9 ;device name addr
	movb    #^a/_/,(r7)+            ;put on leading underscore
10$:    movb    (r9)+,(r7)+             ;move a character into buffer
	sobgtr  r8,10$                  ;done?
	movb    #^a/:/,(r7)+            ;end with a colon
	subl3   (sp),r7,-(sp)           ;compute length of string onto
					;stack for descriptor
	movl    sp,r7                   ;get descriptor addr
	movab   vsd_w_vchan(r11),r8     ;get channel addr
	$assign_s (r7),(r8)             ;assign the channel
	addl2   #28,sp                  ;clear buffer+descriptor from stack
	popr    #^m<r7,r8,r9>           ;pop registers
	rsb


	.page
	.sbttl AST level routines
;++
; FUNCTIONAL DESCRIPTION:
;
;       These routines are called at AST level when something is put
;       in the mailbox. They process the message and adjust the appropriate
;       parts of the data segment.
;
; CALLING SEQUENCE:
;
;       CALLS/G from AST dispatcher
;
; INPUT PARAMETERS:
;
;       None
;
; IMPLICIT INPUTS:
;
;       None
;
; OUTPUT PARAMETERS:
;
;       See each routine for a description of return codes, if any.
;
; IMPLICIT OUTPUTS:
;
;       None 
;
; COMPLETION CODES:
;
;       None
;
; SIDE EFFECTS:
;
;       The file is opened/connected on init print. Various actions
;       are taken by the subroutines.
;
;--


vsmb_mbast: 
	.word   ^m<r2,r3,r9,r10,r11>    ;entry mask
	moval   vsd_g_data,r11          ;get addr of data segment
	movzbl  vsd_b_state(r11),r10    ;get current state

read_mb_again:
	cmpb    #state__asndev,r10      ;assigning device?
	bneq    10$                     ;br if no
	bsbw    asndev                  ;try again
10$:    bsbw    read_mb_now             ;read the mbox
	blbs    r0,chk_mbrd             ;check read if successful

	bsbw    vsmb_setmbast           ;reque the AST
	movb    r10,vsd_b_state(r11)    ;reset state in data segment
	ret

;  
; This routine is used to case to the appropriate handler
; for each message type. We really want this to look like a subroutine call,
; so a return addr is pushed for the rsb instruction.
;
chk_mbrd:
	pushab  read_mb_again           ;push return addr
	case    vsd_t_simmsg+sim$w_msgtyp(r11),- ;dispatch code
			<<init>,-       ;start print
			 <abort>,-      ;abort printing
			 <suspend>,-    ;suspend printing
			 <resume>,-     ;resume printing
			 <exit>,-       ;exit symbiont
			>,limit=#msg$_iniopr ;start at first message
	signal  jbc$_invmsg             ;signal invalid message
	brb     read_mb_again           ;try again

.enabl lsb

5$:     .long   <-1*50000000>,-1        ;five minutes, delta time

;
; this routine processes an init print message
;
init:
	cmpb    #state__idle,r10        ;are we idle?
	beql    1$                      ;okay if so
	brw     unexpect                ;else unexpected  
1$:     movzbl  #state__asndev,r10      ;set assigning device state

asndev: movw    #4,vsd_w_mbreadlen(r11) ;set read length to minimum
12$:    bsbw    vsmb_assigndev          ;try to assign device
	blbs    r0,17$                  ;br if okay
	bsbw    read_mb_now             ;read again
	blbc    r0,2$                   ;br if failed
	brw     chkmb1                  ;else check the read   
2$:     $setimr_s       #10,5$          ;wait for five minutes
	$waitfr_s       #10             ;...
	brw     12$                     ;try again
17$:
	movzbl  #state__open,r10        ;set opening file state
	movc3   #16+6+6,vsd_t_simmsg+sim$t_volnam(r11),-
		vsd_g_nam+nam$t_dvi(r11) ;set device, file, and dir
					;fields in nam block
	bsbw    vsmb_setuic             ;set uic to requestor's
	$open   fab=vsd_g_fab(r11)      ;open the file
	blbs    r0,20$                  ;br if okay
9$:     bsbw    vsmb_restoreuic         ;reset uic to [1,4]
	bisb    #vsd_m_openerr,vsd_b_err_flags(r11) ;set open error bit
10$:    movzbl  #state__done,r10        ;set done state
	brw     40$                     ;and exit

20$:
	$connect        rab=vsd_g_rab(r11) ;connect to file
	blbc    r0,9$                   ;take care of connect error
	bsbw    vsmb_restoreuic         ;set UIC to [1,4]
	movab   vsd_g_rab(r11),r2       ;get rab addr
	movab   vsd_t_tbuf(r11),r3      ;get buffer addr       
	movl    r3,rab$l_ubf(r2)        ;set buffer addr in rab
	movw    #256,rab$w_usz(r2)      ;set buffer size in rab
	$get    rab=(r2)                ;get first record
	blbc    r0,10$                  ;error?
	clrb    vsd_b_dcode(r11)        ;assume plot
	bisb    #vsd_m_vplot,vsd_b_err_flags(r11) ;set plot bit
	cmpb    #0,(r3)                 ;is first byte plot code?
    					;The files entered on the que by the
    					;plot command contain a header record
    					;with a type code of 0 in the first 
    					;byte.
    					;Subsequent records contain 
    					;specifications of files to plot, and
    					;information to control the plotting.
    					;If the type code is not zero, it is
    					;currently assumed that there is an 
    					;error; no additional type codes are
    					;currently defined.
	beql    40$                     ;br if so
	$rewind (r2)                    ;else, rewind file
	incb    vsd_b_dcode(r11)        ;set to print code
	bicb    #vsd_m_vplot,vsd_b_err_flags(r11) ;and clear plot bit

40$:
	$wake_s                         ;wake up
	rsb


.dsabl lsb

;
; Local subroutines to read the mailbox
;
 
;
; Read with no wait:
;
read_mb_now:
	movzwl  #io$_readvblk!io$m_now,r0 ;set I/O function code

;read the mb 
read_mb:
	movaq   -(sp),r1                ;make iosb on stack
	$qiow_s -                       ;do the read
		chan=vsd_w_mbchan(r11),-;channel
		func=r0,-               ;function
		iosb=(r1),-             ;iosb
		p1=vsd_t_simmsg(r11),-  ;buffer
		p2=vsd_w_mbreadlen(r11) ;size to read
	movq    (sp)+,r0                ;get iosb
	rsb


;
; This routine processes the abort file message.
; The abort bit is set, and outstanding I/O canceled.
;
abort:
	cmpb    #state__done,r10        ;are we done?
	beql    30$                     ;then ignore it
	cmpb    #state__idle,r10        ;were we idle?    
	bneq    10$                     ;br if not
	brw     unexpect                ;else unexpected
10$:
	bisb    #vsd_m_abort,vsd_b_err_flags(r11) ;set abort bit
	$cancel_s       vsd_w_vchan(r11)        ;cancel I/O on channel
	cmpb    #state__suspend,r10     ;were we suspended?
	bneq    20$                     ;br if not
	movzbl  r9,r10                  ;restore previous state
20$:
	cmpb    #state__asndev,r10      ;are we assigning device?
	bneq    30$                     ;br if no
	movzbl  #state__idle,r10        ;else make us idle
30$:
	rsb

;
; This routine is the symbiont exit point
;
exit:
	cmpb    #state__idle,r10        ;are we idle
	beql    10$                     ;br if so
	brw     unexpect                ;else unexpected
10$:
	$dassgn_s vsd_w_jbcchan(r11)    ;deassign channel to JBC's mbox
	blbc    r0,20$                  ;br on error
	$dassgn_s vsd_w_mbchan(r11)     ;deassign my mb
	blbs    r0,30$                  ;br if okay
20$:    signal  jbc$_mbdeas,#0,r0       ;signal the error   
30$:
	$delmbx_s       vsd_w_unit(r11) ;kill my mb (just in case)
	$exit_s

;
; signal unexpected message
;
unexpect:
	signal  jbc$_unesymmsg          ;signal
	brw     read_mb_again           ;read again

;
; Handle suspend message
;

.enabl lsb

suspend:
	cmpb    #state__done,r10        ;done?
	beql    20$                     ;ignore it
	cmpb    #state__idle,r10        ;were we idle?   
	bneq    10$                     ;okay if not
	brw     unexpect                ;else unexpected
10$:
	movzbl  r10,r9                  ;save old state
	movzbl  #state__suspend,r10     ;set suspend state
	movzwl  #io$_readvblk,r0        ;set function code
	bsbw    read_mb                 ;wait for something in mbox
chkmb1: movab   chk_mbrd,(sp)           ;set new ret addr
20$:    rsb

.dsabl lsb 

;
; This routine performs a resume print
;
resume:
	cmpb    #state__done,r10        ;are we done?
	beql    30$                     ;then ignore it
	cmpb    #state__suspend,r10     ;are we suspended
	beql    1$                      ;okay if so
	brw     unexpect                ;else unexpected  
1$:     movzbl  r9,r10                  ;restore old state
	movw    vsd_t_simmsg+sim$w_rest(r11),r0 ;get rest of message
	beql    30$                     ;no flags, just resume
	cmpw    #^x8000,r0              ;top of file requested?
	bneq    30$                     ;br if no
	bsbw    vsmb_form_feed          ;generate a form feed
	$rewind vsd_g_rab(r11)          ;rewind the file
	blbs    r0,20$                  ;br if okay
	signal  shr$_rmserror!<4@16>,#0,r0 ;signal the error
	bisb    #vsd_m_geterr,vsd_b_err_flags(r11) ;set error bit
30$:    rsb

20$:    bbc     #vsd_v_vplot,vsd_b_err_flags(r11),30$ ;br if not vplot file
	$get    rab=vsd_g_rab(r11)      ;punt first record of plot file
	brb     30$                     ;and exit


	.page
	.sbttl  Subroutine -- output form_feed to the varian
;++
; FUNCTIONAL DESCRIPTION:
;
;       This routine outputs a form feed to the varian
;
; CALLING SEQUENCE:
;
;       BSB/JSB             
;
; INPUT PARAMETERS:
;
;       None
;
; IMPLICIT INPUTS:
;
;       None
;
; OUTPUT PARAMETERS:
;
;       None
;
; IMPLICIT OUTPUTS:
;
;       None
;
; COMPLETION CODES:
;
;       None
;
; SIDE EFFECTS:
;
;       None
;
;--

slew:   .long ^o263             ;form feed char for varian

vsmb_form_feed:                 ;send form feed to varian
	pushal  slew            ;push code
	calls   #1,var$command  ;do the form feed
	rsb                     ;and return

	.page
	.sbttl  Error to varian action routine


;++
; FUNCTIONAL DESCRIPTION:
;
;       This is a putmsg action routine which outputs the message to
;       the varian. Output to sys$error and sys$output is supressed.
;
; CALLING SEQUENCE:
;
;       CALLS/G           
;
; INPUT PARAMETERS:
;
;       4(ap) = address of descriptor of the error message to output
;
; IMPLICIT INPUTS:
;
;       None
;
; OUTPUT PARAMETERS:
;
;       None
;
; IMPLICIT OUTPUTS:
;
;       None
;
; COMPLETION CODES:
;
;       None
;
; SIDE EFFECTS:
;
;       Message is output on varian between form-feeds
;
;--

alph:   .long   ^o100

vsmb_tell_varian::
	.word   ^m<r2>          ;entry mask
	bsbw    vsmb_form_feed  ;generate a form feed
	movl    4(ap),r2        ;get message descriptor address
	pushal  alph            ;push alphanumeric command code
	calls   #1,var$command  ;set alpanumeric mode
	pushl   4(r2)           ;push addr of message
	pushl   r2              ;push addr of length of message
	calls   #2,var$send_buf ;output the message
	bsbw    vsmb_form_feed  ;generate a form feed
	clrl    r0              ;no send to sys$output/error
	ret



;
; end of symbiont
;
	.end    vsmb_start
