.TITLE CLRREF - Clear Device Reference count .IDENT /002-0/ ;++ ; ; CLRREF.MAR 16-Sep-1991 Ehud Gavron ; So you want to clear a device that someone has left allocated and gone ; away, huh? Be vewy vewy caweful. We'we huntin' wabbits. ; ; Ehud Gavron gavron@Spades.ACES.COM ; ;-- ; V1.0.0 Created because I'm not getting enough interesting ; kernel-coding to do in my regular job. ; ; V2.0.0 Made it $ASSIGN, set reference count to 1, $DASSGN ; 19-Sep-1991 Ehud Gavron ; ; V2.0.1 Added clearing of mount bit so I can use this to ; release tapes owned by nonexistent processes. ; ; ; Definitions ; .library "sys$Library:lib.mlb" ; find $xxxdefs .link "sys$system:sys.stb"/selective_search ; find xxx$x_xs $ccbdef ; Channel Control Block offsets (to get UCB) $pcbdef ; Process Control Block offsets (to get PID) $prvdef ; Privilege definitions (to get BYPASS and _IO) $orbdef ; Object Resource Block offsets (to clear owner) $ssdef ; System Service status values (for normal status) $ucbdef ; Unit Control Block offsets (miscellaneous) ; ; Macros ; .macro check ?l1 blbs r0,l1 $exit_s r0 l1: .endm check ; ; Variables ; Channel: .blkl 1 ; channel number Device: .ascid "$all$ddcuuuu:" ; the device (max size I expect) Privmsk: .blkl 2 ; privilege mask Prompt: .ascid "Device: " ; the prompt if someone didn't enter it Ucb: .blkl 1 ; address of UCB Clrref_arg: .long 1 ; The argument list to give the UCB .address ucb ; address to the kernel-mode routine ; ; Start of user-mode code ; .entry clrref,^m<> ; ; Get the device name from the command line ; pushl #0 ; flags pushal Device ; resultant-length pushal Prompt ; prompt-string pushal Device ; resultant-string calls #4,g^lib$get_foreign check ; ; Enable privileges ; movl #,privmsk $setprv_s enbflg=#1,prvadr=privmsk check ; ; Assign channel to the device ; $assign_s devnam=device,chan=channel check ; ; Get UCB address from CCB ; movl @#ctl$gl_ccbbase,r0 ; Get CCB table base address movzwl channel,r1 ; Get channel number (byte offset) subl r1,r0 ; Get address of CCB for this channel movl ccb$l_ucb(r0),ucb ; Get UCB address ; ; Call the kernel-mode routine to set the reference count and owner ; $cmkrnl_s routin=clrref_k,arglst=clrref_arg check ; ; Deassign the channel ; $dassgn_s chan=channel $exit_s r0 ; ; The kernel-mode code ; .entry clrref_k,^m<> ; ; Get the Unit Control Block (UCB) address ; movl 4(ap),r1 ; Address of Ucb variable movl (r1),r1 ; Address of device UCB ; ; Get PCB address into R4 (really we already have this from $cmkrnl) ; movl ctl$gl_pcb,r4 ; ; Raise IPL, acquire Mutex, and set the reference count ; lock lockname=iolock8 ; Raise IPL, acquire lock movw #1,ucb$w_refc(r1) ; Set reference count to 1 bicl #dev$m_all,ucb$l_devchar(r1) ; Clear the allocated bit bicl #dev$m_mnt,ucb$l_devchar(r1) ; Clear the mount bit (tapes) movl pcb$l_pid(r4),ucb$l_pid(r1) ; Set us as the owner in UCB ; ; Get the Object Resource Block (ORB) address ; movl ucb$l_orb(r1),r1 ; Object Resource Block offset from UCB movl pcb$l_pid(r4),orb$l_owner(r1) ; Set us as the owner in ORB ; ; Return to user mode ; unlock lockname=iolock8,newipl=#0 ; Release lock (lower IPL) movl #ss$_normal,r0 ; Status ok ret ; G'bye .end clrref