.title tt_ucb ;;; idllb - determine idle (and other) information for terminals (privileged) ; ; revision history ;16-Sep-1986 Incclude Units.Mlb to get Max_Units (RAC). ; 8-Mar-1985 Get RTT stuff to work after Craig Leres (LBL). ;30-Jan-1985 Rename to tt_ucb since it now gets a lot more than idle time. ;29-Jan-1985 Add arguments for Physical terminal name and number ;24-JAN-1985 VMS V4.0 changes. Craig Watkins (Penn State) and ; Mark London (MIT): Virtual terminal stuff; ; and IPID --> EPID ; ; 03a 27Oct83 cal .Added a new argument to hold the ucb$w_rtt_link value ; for remote terminals. Modified so that the idle time ; and ucb link value buffers are optional arguments. ; 02b 07Oct83 cal .Corrected addressing modes in the probew instructions. ; 02a 08Nov82 cal .Written; this routine has been coded again from ; scratch. Revision history after this point has ; no reason for existing and can be safely ingnored. ; 01b 16jul82 vp .Added .title ; 01a 12Mar82 cal .Taken from a Decus tape ; ; synopsis ; ; status = tt_ucb ( [buf_tim], buf_pid, [buf_dev], [buf_unit], ; [buf_ucb], buf_siz ) ; ; buf_tim - buffer of longwords to receive idle times (optional) ; buf_pid - buffer of longwords to receive pids ; buf_dev - buffer for physical device controller generic names (4 words) (opt.) ; buf_unit - buffer for physical device unit numbers (opt.) ; buf_ucb - buffer of longwords to receive ucb decnet link addresses (optional) ; buf_siz - number of units to get information about ; ; The buffers are longwords (integer*4) arrays of size buf_siz. The idle ; times, process ids, and remote link values are stored in the two buffers ; in consecutive elements with a zero longword in the pid buffer to mark ; end of the list. The idle time and link value buffer arguments are optional. ; The information is ordered by terminal name. ; ; Note: Use of this routine requires the privilege CMKRNL. ; .library /sys$library:lib.mlb/ .library /units.mlb/ ;RAC $ucbdef $ddbdef $ipldef $ttyucbdef ; ; Useful constants ; acp_remote = 3 ; acp class number for remote ap_tim = 4 ; offset to due time buffer ap_pid = 8 ; offset to pid buffer ap_dev = 12 ap_unit = 16 ap_ucb = 20 ; offset to ucb buffer ap_siz = 24 ; offset to buffer size num_args = 6 ; number of arguments fudge = 2 ; add this to exe$gl_abstim sizeof_long = 4 ; size of a longword units ; max units to report about sizeof_buf = max_units * sizeof_long ; size of return buffers .entry tt_ucb,^M cmpl #num_args,(ap) ; need this many arguments beql 10$ ; branch if correct movl #ss$_badparam,r0 ; setup error status ret ; go give him the bad news 10$: cmpl @ap_siz(ap),#max_units ; want at least this many units bgequ 20$ ; we'll allow his to be bigger movl #ss$_ivbuflen,r0 ; setup error status ret ; return to caller 20$: tstl ap_tim(ap) ; test for time buffer argument beql 30$ ; branch if none probew #0,#sizeof_buf,@ap_tim(ap) ; see if we can write there... beql 60$ ; bail out if not 30$: probew #0,#sizeof_buf,@ap_pid(ap) ; see if we can write there... beql 40$ ; bail out if not 40$: tstl ap_dev(ap) ; test for device buffer argument beql 50$ ; branch if none probew #0,#sizeof_buf,@ap_dev(ap) ; see if we can write there... beql 60$ ; bail out if not 50$: tstl ap_unit(ap) ; test for unit buffer argument beql 55$ ; branch if none probew #0,#sizeof_buf,@ap_unit(ap) ; see if we can write there... beql 60$ ; bail out if not 55$: tstl ap_ucb(ap) ; test for ucb buffer argument beql 70$ ; branch if none probew #0,#sizeof_buf,@ap_ucb(ap) ; see if we can write here too bneq 70$ ; branch if we can 60$: movl #ss$_accvio,r0 ; setup error status 65$: ret ; return to caller 70$: $lkwset_s inadr=lock ; lock routine into working set cmpl #ss$_wasclr,r0 ; did we lock the pages? beql 80$ ; branch if so cmpl #ss$_wasset,r0 ; were they already locked? bneq 65$ ; if not, then error 80$: $cmkrnl_s routin=ttucbkrn ; do the privileged stuff movl r0,r6 ; save status for later $ulwset_s inadr=lock ; unlock kernel routine cmpl #ss$_wasclr,r0 ; did we unlock the pages? beql 90$ ; branch if so cmpl #ss$_wasset,r0 ; were they already unlocked? bneq err ; if not, then error 90$: tstl ap_tim(ap) ; test for time buffer argument beql 100$ ; branch if none movc3 al_cnt,bl_tim,@ap_tim(ap) ; store idle time info 100$: movc3 al_cnt,bl_pid,@ap_pid(ap) ; store pid info tstl ap_dev(ap) ; test for devicebuffer argument beql 110$ ; branch if none movl al_cnt,r0 ; get size of buffer ashl #2,r0,r0 ; mutiply by 4 for this one movc3 r0,bl_dev,@ap_dev(ap) ; store device name info 110$: tstl ap_unit(ap) ; test for unit no.buffer argument beql 120$ ; branch if none movc3 al_cnt,bl_unit,@ap_unit(ap) ; store unit no. info 120$: tstl ap_ucb(ap) ; test for ucb buffer argument beql 130$ ; branch if none movc3 al_cnt,bl_ucb,@ap_ucb(ap) ; store ucb info 130$: movl r6,r0 ; restore status err: ret ; that's all folks! ; ; Descriptor used to lock kernel routine into our working set ; lock: .address ttucbkrn .address ttucbkrnend ; ; Entry point for the privileged search and slurp. The following ; registers are used: ; ; r0 - return status ; r1 - scratch ; r3 - system absolute time ; r4 - reserved for PCB pointer by SCH$... routines - set by CHKRNL ; r5 - address of due time storage area ; r6 - address of pid storage area ; r7 - address of ucb decnet link storage area ; r8 - address of device name storage area ; r9 - address of unit no. storage area. ; r10 - address of current unit control block ; r11 - address of current device data block ; .entry ttucbkrn,^M movl #bl_tim,r5 ; address of due time buffer movl #bl_pid,r6 ; address of pid buffer movl #bl_ucb,r7 ; address of ucb link buffer movl #bl_dev,r8 ; address of device name buffer movl #bl_unit,r9 ; address of unit no. buffer jsb sch$iolockr ; lock io data base for read dsbint #ipl$_synch ; raise ipl while mucking... addl3 #fudge,exe$gl_abstim,r3 ;; add fudge to abstim movl ioc$gl_devlist,r11 ;; ddb list in r11 brb jump1 ;; jump into middle loop loop1: movl ddb$l_link(r11),r11 ;; look at next ddb jump1: bneq 1$ ;; already did last controller? jmp finish ;; no more - all done 1$: movl ddb$l_ucb(r11),r10 ;; fetch first ucb of this ddb brb jump2 ;; jump into innermost loop loop2: movl ucb$l_link(r10),r10 ;; look at next ucb jump2: beql loop1 ;; no more units left cmpb #dc$_term,ucb$b_devclass(r10) ;; is this unit a terminal? bneq loop1 ;; next ddb if not bbs #dev$V_rtt,ucb$l_devchar2(r10),3$ ;; if remote skip down tstl ucb$l_tl_phyucb(r10) ;; is this a physical terminal? beql loop1 ;; next ddb if not bbs #dev$v_red,ucb$l_devchar2(r10),5$ ;; is this redirected terminal? ;; if so, skip process test 3$: tstl ucb$l_pid(r10) ;; check for a process beql loop2 ;; skip if no process 5$: movl ucb$l_tt_logucb(r10),r1 ;; get logical UCB address bbc #dev$V_rtt,ucb$l_devchar2(r10),6$ ;; if not remote skip movl r10,r1 ;; fake logical ucb for rtt 6$: subl3 ucb$l_duetim(r10),r3,r2 ;; idle time in r2 bbc #ucb$v_tim,ucb$w_sts(r10),10$ ;; see if unit is timed out brb 20$ ;; timed out so go zero time 10$: bbs #ucb$v_bsy,ucb$w_sts(r1),30$ ;; see if unit is busy 20$: clrl r2 ;; if true, zero idle time 30$: movl r2,(r5)+ ;; stow idle time movl ucb$l_pid(r1),r0 ;; get owner pid jsb g^exe$ipid_to_epid ;; convert to extended PID movl r0,(r6)+ ;; stow owner pid clrl r2 ;; assume not remote bbc #dev$V_rtt,ucb$l_devchar2(r10),40$ ;; if not remote skip down movzwl ucb$w_rtt_link(r10),r2 ;; link value in r2 40$: movl r2,(r7)+ ;; stow link address movl ddb$t_name(r11),(r8)+ ;; stow device name movl ddb$t_name+4(r11),(r8)+ ;; '' '' '' movl ddb$t_name+8(r11),(r8)+ ;; '' '' '' movl ddb$t_name+12(r11),(r8)+ ;; '' '' '' movzwl ucb$w_unit(r10),(r9)+ ;; stow physical unit number cmpl #bl_pid+sizeof_buf,r6 ;; have we run out of buffer? blssu 50$ jmp loop2 ;; if not negative we're ok 50$: subl #sizeof_long,r6 ;; backup just a tad movl #ss$_bufferovf,r0 ;; setup return status brb krnerr ;; and exit finish: movl #ss$_normal,r0 ;; setup return status krnerr: movl r0,r3 ;; store status jsb sch$iounlock ;; unlock io data base enbint ;; restore ipl clrl (r6)+ ; flag end of list subl3 #bl_pid,r6,al_cnt ; calculate size of transfer movl r3,r0 ; restore status ret ; back to user mode bl_tim: .blkl sizeof_buf ; storage for due time bl_pid: .blkl sizeof_buf ; storage for pid bl_dev: .blkl sizeof_buf*4 ; storage for device names bl_unit: .blkl sizeof_buf ; storage for unit numbers bl_ucb: .blkl sizeof_buf ; storage for magic ucb address al_cnt: .long 0 ; size of transfer ttucbkrnend: ; end of locked memory .end