KVC@ENGVAX.SCG.HAC.COM (Kevin Carosso) (07/28/87)
.TITLE UNLINK_VT a set of routines to unlike a VT
.IDENT /V1.0-000/
.LIBRARY /SYS$LIBRARY:LIB.MLB/
;++
;
; These routines are a system hack to allow a privileged user
; to disconnect a VT with outstanding I/O from it's physical device.
; The correct way to perform this would be to modify the code in TTDRIVER
; that does the disconnect. For testing purpose this is a more expediant
; way to accomplist this goal.
;
; NOTE:
; The required privs to use this are:
;
; 1) CMKRNL
; 2) SHARE
;
; CALLING SEQUENCE:
;
; ret_stat = UNLINK_VT (device_name)
;
; device_name - address of a string descriptor, the string must
; contain name of VT to be disconnected (ex VTA0:)
;
; AUTHOR:
;
; Forrest A. Kenney 28-August-1986
;
; REVISION HISTORY:
;
; Kevin Carosso 14-JUL-1987 Hughes Aircraft, SCG/CTC
; Modified a bit for local use, don't bother with
; the privilege checks, must have CMKRNL and SHARE only.
; Raise to device IPL while mucking in the UCB as
; Forrest Kenney suggested.
;
; Clear R2 before calling IOC$SEARCH. Since we now run
; above IPL 2, we have to lock our kernel code into memory.
;
;--
.SBTTL External and local symbol definitions
;
; External symbols
;
$CCBDEF ; Define CCB
$DVIDEF ; Device information
$IPLDEF ; Define various CPU IPL levels
$JPIDEF ; Process information
$SSDEF ; System status codes
$UCBDEF ; Unit control block
$TTYDEFS ; TTY specific definitions
$TTYMACS ; Define terminal macros
$TTYUCBDEF ; TTY UCB definitions
;+
; A simple macro to help build item list items
;-
.MACRO ITEM LENGTH,CODE,BUFF_ADDR,RET_LEN=0
.WORD LENGTH
.WORD CODE
.ADDRESS BUFF_ADDR
.ADDRESS RET_LEN
.ENDM ITEM
.SBTTL Allocate local storage
.PSECT $DATA LONG,NOEXE,RD,WRT
DEVNAM: .BLKB 64 ; Block hold PHYDEV name
DEVNAM_LEN = .-DEVNAM
DEVNAM_SIZ: ; Storage for length of PHYDEV name
.LONG 0
DISC_FLAG: ; Is device disconnectable
.LONG 0
CHANNEL:
.WORD 0 ; Channel number for assign
IOSB: .BLKW 4 ; IOSB for $GETDVI
DVILST: ITEM DEVNAM_LEN,DVI$_TT_PHYDEVNAM,DEVNAM,DEVNAM_SIZ
ITEM 4,DVI$_TT_DISCONNECT,DISC_FLAG
.LONG 0
lock_range: ; For $LKWSET call
.address begin_lock
.address end_lock
.PSECT $CODE LONG,PIC,NOWRT,RD,EXE,CON,REL,LCL,SHR
.SBTTL Validate device & request
;+
;
; This routine will validate the device to be disconnected is a
; virtual terminal and the the user has the correct privs to do it. The
; sequence is listed below:
;
; 1) Assign a channel to the device
; 2) Determine if device can be disconnected
; 3) Calls KERNEL mode routine (to get UCB address and disconnect
it)
;
; INPUTS:
; 4(AP) - Address of a descriptor containing device name
;
; OUTPUT:
; R0 - Status of operation
;
; SS$_IVDEVNAM
; SS$_NOPRIV
; any possible returns from $ASSIGN or $GETDVI
;
;-
.ENTRY UNLINK_VT,^M<>
;+
; Lock down our kernel mode, high IPL code.
;-
$LKWSET_S INADR = lock_range
blbs r0, 5$
ret
;+
; Get a channel to work with
;-
5$: CLRQ -(SP) ; Default acmode & no mailbox
MOVAW CHANNEL,-(SP) ; Address of word to hold channel #
MOVL 4(AP),-(SP) ; Address of device name string
CALLS #4,G^SYS$ASSIGN ; Assign channel
BLBS R0,10$ ; Success continue
RET ; Failed return with reason
;+
; Now get the device information and make sure it can be disconnected,
; also make sure that don't try to disconnect an already disconnected device
;-
10$: $GETDVIW_S CHAN=CHANNEL,- ; Get device information
ITMLST=DVILST,- ;
IOSB=IOSB ;
BLBS R0,20$ ; Setup ok continue
PUSHL R0 ; Save error reason
BRW 1000$ ; Branch to exit code
20$: BLBS IOSB,30$ ; OK continue
MOVZWL IOSB,-(SP) ; Store failure reason
BRW 1000$ ; Branch to exit code
30$: BLBS DISC_FLAG,40$ ; Device disconnectable cont
MOVZWL #SS$_IVDEVNAM,-(SP) ; Inproper device for requested operatio
n
BRW 1000$ ; Branch to exit code
40$: TSTL DEVNAM_SIZ ; See if got physical device name
BNEQ 80$ ; If zero length then already disconnect
ed
MOVZWL #SS$_NORMAL,-(SP) ; Store failure reason
BRW 1000$ ; Branch to exit code
;+
; Now build arg list & call Kernel mode routine
;-
80$: MOVL AP,-(SP) ; Store device argument list on stack
MOVAL KRNL_CODE,-(SP) ; Store address of Kernel routine on sta
ck
CALLS #2,SYS$CMKRNL ; Invoke kernel mode routine
PUSHL R0 ; Save status reason
;+
; We have a channel to free before exiting
;-
1000$: $DASSGN_S CHAN=CHANNEL ; Free channel
BLBS R0,1010$ ; Ok just exit with correct reason
MOVL R0,R1 ; Save channel DASSGN error
POPL R0 ; Get previous status code
BLBC R0,1020$ ; Use first error
MOVL R0,R1 ; Use DASSGN error
RET ; Return
1010$: POPL R0 ; Restore reason
1020$: RET ; Return to caller
;+
; This section of code needs to run at elevated IPL to prevent process
; deletion while owning I/O database MUTEX. It also will use a backdoor
; hook into the TTDRIVER to UNLINK the VT.
;
; Note: R4 contains the current processes PCB address it is suppiled by
; the change mode dispatcher. It is needed by SCH$IOLOCKR &
; SCH$IOUNLOCK
;
;-
begin_lock:
.ENTRY KRNL_CODE,^M<R3,R5>
DSBINT #IPL$_ASTDEL ; Raise IPL to prevent process deletion
JSB G^SCH$IOLOCKR ; Lock the I/O database for read access
MOVL 4(AP),R1 ; Get device descriptor string address
CLRL R2 ; No flags
CLRL R3 ; No lock value block
JSB G^IOC$SEARCH ; Now find the devices UCB
CMPW R0,#SS$_DEVALLOC ; See if device allocated
BEQL 10$ ; If allocated proceeded
BLBC R0,30$ ; If no device then exit
10$: DSBINT UCB$B_DIPL(R1) ; Raise to device IPL
MOVL UCB$L_TL_PHYUCB(R1),R5 ; Get device's physical UCB address
BEQL 20$ ; Device already disconnected just exit
PUSHL R4 ; Save PCB address
MOVL UCB$L_TT_CLASS(R5),R4 ; Get class dispatch table address
JSB @CLASS_DISCONNECT(R4) ; Now call disconnect code
POPL R4 ; Restore PCB address
20$: ENBINT ; drop back down
MOVZWL #SS$_NORMAL,R0 ; Store success as exit reason
30$: PUSHL R0 ; Save reason
JSB G^SCH$IOUNLOCK ; Unlock I/O database
POPL R0 ; Restore reason
ENBINT ; Lower IPL back to calling level
RET
;
; Lock down pages between "begin_lock" and here so we don't pagefault
; at high IPL
;
end_lock:
.END