;*********************************************************
;Program:	showbase
;Author:	Bruce Ellis
;Synopsis:	This program displays the base virtual addresses of
;		shareable images
;*********************************************************

;Macro definitions
	.macro	check	?lab
	blbs	r0,lab
	$exit_s	r0
lab:
	.endm	check
;Macro library includes
	.library	/sys$library:lib/
	.link	/sys$system:sys.stb/
	$pcbdef
	$phddef
	$pridef
	$ipldef
	$acbdef
	$shldef
	$iafdef
	$dyndef
;***Note: NO ICB OFFSETS DEFINED BY DEC
imgname=^X14
baseva=^X5C
ef=32
;data area
pid_asc:
	.long	8
	.address	10$
10$:	.blkb	8
pid:	.blkl	1
prompt:	.ascid	/Pid?/
shls:	.blkb	<4+28>*100
count:	.long	0
out:	.long	80
	.address	20$
20$:	.blkb	80
c:	.ascid	/Image name: !28AC base = !XL/
lock_adr:
	.address	lock1
	.address	lock2
	
;Code
	.entry	shl,^m<>
	$lkwset_s	inadr=lock_adr	;No page faults at high ipl
	check
	pushal	pid_asc			;Determine which process we
	pushal	prompt			;  are supposed to get the info
	pushal	pid_asc			;  from.
	calls	#3,g^lib$get_input
	check
	pushal	pid			;Convert pid from ascii to binary
	pushal	pid_asc			;
	calls	#2,g^ots$cvt_tz_l	;
	check

	$cmkrnl_s	routin=get_shl	;Queue a special kernel ast to the
	check				;process to obtain the needed info
	$waitfr_s	efn=#ef		;wait until sp kast sets efn for 
	check				;asynchronous completion
	movl	count,r6		;How many shareable images
	moval	shls,r7			;set up pointer to base va
10$:	moval	4(r7),r8		;set up pointer to shl name
	$fao_s	ctrstr=c,outbuf=out,-	;format the output
		outlen=out,p1=r8,p2=(r7)
	pushal	out			;dump it to the tube
	calls	#1,g^lib$put_output	;
	addl	#<4+28>,r7		;point to next shl
	movl	#80,out			;reset buffer length
	sobgtr	r6,10$			;loop till all shls processed
	ret				;Auf Wiedersehen!

;****************************************************
;	Special kast setup
;****************************************************
	.entry	get_shl,^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>
;	movzwl	pid,r2			;get index
	movl	pid,r0			;get the epid
	jsb	g^exe$epid_to_ipid	;convert to meaningful pid
	movzwl	r0,r2
	cmpw	r2,g^sch$gl_swppid	;Is this swapper or null?
	bgtru	ok1			;If not process
	brw	err_ret			;otherwise exit with error status
ok1:	movl	g^sch$gl_pcbvec,r10	;get base of pcb vector table
	movl	(r10)[r2],r10		;Get processes PCB address
	cmpl	#sch$gl_nullpcb,r10	;If null do not process
	bneq	ok2
	movl	#ss$_nonexpr,r0
	brw	err_ret
ok2:	moval	acb,r6			;set up acb
	movl	g^sch$gl_curpcb,r4	;Save my 
	movl	pcb$l_pid(r4),acb_l_mypid	;  pid for return sp kast
	movl	@#ctl$gl_phd,r9		;get phd address
	movl	phd$l_imgcnt(r9),imgcnt	; Save the image count so return AST
					;knows whether we are in same image or
					; not
	moval	shls,shl_ret_adr	;save return address from p0 space
	moval	count,count_ret_adr	;save return count address from p0
	movl	#size_of_pool,r1	;Set up for allocating pool
	jsb	g^exe$alononpaged	;get it
	blbs	r0,ok3			;continue if all is cool
	brw	err_ret			;else get out
ok3:	pushr	#^m<r0,r1,r2,r3,r4,r5>	;save regs from movc3
	movc3	#size_of_pool,acb,(r2)	;copy acb and routines to pool
	popr	#^m<r0,r1,r2,r3,r4,r5>	;restore regs
	movw	r1,acb$w_size(r2)	;save size of pool
	movb	#dyn$c_acb,acb$b_type(r2)	;setup type
	movb	#<1@acb$v_kast>,acb$b_rmod(r2)	;set up for sp kast
	movl	pcb$l_pid(r10),acb$l_pid(r2)	;define acb of process to get ast
	moval	<copy_shl-acb>(r2),acb$l_kast(r2) ;set ast address for kast

	movl	r2,r5			;set up r5 for sch$qast
lock1:	setipl	#ipl$_synch		;synch w/sched db
	movzwl	acb$l_pid(r5),r4	;retrieve the pid of the process we want
	movl	g^sch$gl_pcbvec,r1	;get pointer to pcb vector table
	movl	(r1)[r4],r4		;get his pcb
	cmpl	pcb$l_pid(r4),acb$l_pid(r5)	;Is he still there?
	bneq	err_ret_deallo		;if not clean up and leave
	movl	#pri$_ticom,r2		;give him a boost
	movl	g^sch$gl_curpcb,r4	;restore our pcb address
	jsb	g^sch$qast		;queue an ast to the process
	movl	#ss$_normal,r0		;Get outta here
	setipl	#0
	ret
err_ret_deallo:
	movl	r5,r0			;r0 points to the pool to return
	jsb	g^exe$deanonpaged
	movl	#ss$_insfmem,r0
err_ret:
lock2:	ret

acb:	.blkb	acb$l_kast+4		;allocate space for the acb portion
acb_l_mypid:
	.blkl	1
ret_ast_adr:
	.blkl	1
shl_ret:
	.blkb	<4+28>*100
count_ret:
	.long	0
shl_ret_adr:
	.blkl	1
count_ret_adr:
	.blkl	1
imgcnt:	.blkl	1

;*****************************************************
;Special kernel ast code
;*****************************************************
copy_shl:
	pushr	#^m<r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>
	movl	acb_l_mypid,acb$l_pid(r5)	;reset pid for return trip
	moval	ret_ast,acb$l_kast(r5)		;set return ast address
	bisb2	#<1@acb$v_kast>,acb$b_rmod(r5)	;set up for sp kast
	clrl	count_ret			;zero counter of shl names
	moval	shl_ret,r11			;Point to save buffer for shl
	moval	@#iac$gl_image_list,r10		;setup link to fixup vectors
nxt_iaf:
	movl	(r10),r10		;get first fixup vector
	cmpl	r10,#iac$gl_image_list
	beql	all_done1			;no more fixup vecs so scram 
	incl	count_ret			;otherwise update return count
	pushr	#^m<r0,r1,r2,r3,r4,r5>
	movc3	#28,imgname(r10),4(r11)	;copy image name
	movl	baseva(r10),(r11)		;get base virtual address for image
	addl	#<4+28>,r11
	popr	#^m<r0,r1,r2,r3,r4,r5>
all_done2:
	brb	nxt_iaf
all_done1:
;*****************************************************
;We have the info now let us send it back to the 
;original process.
;*****************************************************
	setipl	#ipl$_synch			;synch with sched db for astdel
	movzwl	acb$l_pid(r5),r1		;set up return pid for astdel
	movl	g^sch$gl_pcbvec,r2		;get at pcb vector table
	movl	(r2)[r1],r1			;get our pcb address
						;Who are we anyway? (Zelig)
	cmpl	pcb$l_pid(r1),acb$l_pid(r5)	;are we still around or are we
						; The Ghost in the Machine
	bneq	err_ast_exit			;if initial process is not
						;here exit
	clrl	r2				;no boost for the ast
	jsb	g^sch$qast			;return to home
	setipl	#ipl$_astdel			;return to initial ipl
	popr	#^m<r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>
	rsb					;back to astdel
err_ast_exit:
	setipl	#ipl$_astdel			;restore ipl
	popr	#^m<r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>
	movl	r5,r0				;deallocate ourselves
	jmp	g^exe$deanonpaged		;and don't come back here 
						;instead go directly back to
						;astdel and do not collect $200

;****************************************************************
;We are back home now so lets put the info at his
;doorstep, ring the doorbell, and disappear
;****************************************************************
ret_ast:
	pushr	#^m<r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>
	movl	pcb$l_phd(r4),r3		;get our process header
	cmpl	phd$l_imgcnt(r3),imgcnt		;are we still in the same
						;image? If not get out.
	bneq	exit				;
	mull3	#<4+28>,count_ret,r2		;how much to return?
	pushr	#^m<r0,r1,r2,r3,r4,r5>
	movc3	r2,shl_ret,@shl_ret_adr		;return the goods
	popr	#^m<r0,r1,r2,r3,r4,r5>
	movl	count_ret,@count_ret_adr	;return the number of parcels
	movl	#ef,r3				;set efn ef
	movl	pcb$l_pid(r4),r1		;for ourselves
	clrl	r2				;no boost
	jsb	g^sch$postef			; set it
exit:	popr	#^m<r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>
	movl	r5,r0
	jmp	g^exe$deanonpaged		;become a non-entity
size_of_pool = .-acb
	.end	shl	
