.TITLE DEALLOC .LIBRARY /SYS$LIBRARY:LIB/ .LINK 'SYS$SYSTEM:SYS.STB' /SELECTIVE_SEARCH ; Global symbol definitions $ACBDEF ;Access Control Block Definitions $DSCDEF ;Descriptor Definitions $DYNDEF ;DYN$C_ACB $IPLDEF ;Interrupt Priority Level Definitions $PSLDEF ;Access Mode Definitions $PRIDEF ;Priority increment definitions (PRI$_TICOM) .PSECT STATIC RD,NOWRT,NOEXE,LONG,PIC LCKKNL: .ADDRESS FORCE_DEALLOCATE ;Lock in memory code which executes .ADDRESS FORCE_DEALLOCATE_END ;at elevated IPL LCKAST: .ADDRESS AST_BEGIN ;Lock in memory AST code and data .ADDRESS AST_END ;(all copied while at eleveted IPL) DEVPROMPT: .ASCID /Device to deallocate: / PIDPROMPT: .ASCID /PID of process which has device allocated: / .PSECT DATA RD,WRT,NOEXE,LONG ;The following argument list is sent to the kernel mode routine FORCE_DEALLOCATE ;It is then used as the argument list to EXE$NAMPID which FORCE_DEALLOCATE calls NAMPID_ARGLST: .LONG 2 ;2 arguments .ADDRESS TARGET_PID ;PID (extended) of process to send AST to .LONG 0 ;PRCNAM. Not used by us. Left at 0. ;Place for target PID (extended PID) TARGET_PID: .LONG 0 ;The following buffer is used to prompt for the PID BUFLEN=80 ;length of input buffer INPUTBUFD: .WORD BUFLEN ;descriptor pointing to input buffer .BYTE DSC$K_DTYPE_T .BYTE DSC$K_CLASS_S .ADDRESS INPUTBUF INPUTBUF: .BLKB BUFLEN ;the input buffer ;============================================================================== .PSECT MAINCODE NOWRT,EXE,LONG .ENTRY MAIN,^M<> ;Get name of device to deallocate. PUSHAW DEVICED ; length of device name entered PUSHAQ DEVPROMPT ; prompt for device PUSHAQ DEVICED ; Store result in AST_CODE CALLS #3,G^LIB$GET_INPUT ; PROMPT FOR DEVICE NAME ;Get PID of process to which has device allocated ;This is the PID of the process to send the AST to ;(Fancier code could figure this out automatically given the device ; to deallocate as prompted for above) PUSHAW INPUTBUFD ; length of input string (returned) PUSHAQ PIDPROMPT ; prompt string (by descriptor) PUSHAQ INPUTBUFD ; input buffer (by descriptor) CALLS #3,G^LIB$GET_INPUT ; PROMPT FOR PID ;Convert PID string to an integer and store value in TARGET_PID PUSHAL TARGET_PID ;Unsigned integer result goes here PUSHAQ INPUTBUFD ;Input buffer descriptor containing PID CALLS #2,G^OTS$CVT_TZ_L ;Convert hexadecimal string (the PID) ; to unsigned integer (TARGET_PID) BLBC R0,1$ ;Branch to exit if error ;Lock pages in memory so we won't page fault at elevated IPL. $LKWSET_S inadr=LCKKNL ; kernel mode eleveted IPL code BLBC R0,1$ ; (branch to exit if error) $LKWSET_S inadr=LCKAST ; AST code copied while at elevated IPL BLBC R0,1$ ; (branch to exit if error) ;Call our kernel mode routine which does the work $CMKRNL_S routin=FORCE_DEALLOCATE, arglst=NAMPID_ARGLST ;Exit with status in R0 1$: $EXIT_S R0 ;------------------------------------------------------------------------------ .SUBTITLE KERNELCODE ;+ ; This is the kernel mode routine which queues the AST to the target process ; Upon entry, R4 = PCB of our process (set by SYS$CMKRNL) ; We also have the following arglst which is used for the call to EXE$NAMPID: ; (AP) = 2 Two arguments follow ; 4(AP) = TARGET_PID External Process Identification number (EPID) ; 8(AP) = 0 Not used by us ;- .PSECT KERNELCODE NOWRT,EXE,LONG .ENTRY FORCE_DEALLOCATE, ^M ; 1. Convert EPID to IPID JSB G^EXE$NAMPID ;Convert EPID to IPID CMPL R0,#SS$_NORMAL ;Test for success BNEQ EXIT ;Branch to exit on error ; 2. On successful call to EXE$NAMPID, we return at IPL SCHED (SCHED ; database locked, IPL=8). R1 contains the IPID of our target process. ; Now temporarily store IPID of target process in R6 and ; allocate non-paged memory for AST MOVL R1,R6 ;Save IPID MOVZWL #,R1 ;Size of memory needed. JSB G^EXE$ALONONPAGED ;Allocate nonpaged memory BLBC R0,EXIT ;Branch on error ;R1 = Size of nonpaged pool allocated (returned from EXE$ALONONPAGED) ;R2 = Address of nonpaged pool allocated (returned from EXE$ALONONPAGED) ;Fill in the allocated memory with the AST Control Block (ACB) header and code ;Initialize ACB header: MOVW R1,ACB$W_SIZE(R2) ; Set size of non-paged memory block MOVB #DYN$C_ACB,- ; Set type of memory block to ACB ACB$B_TYPE(R2) ; MOVB #PSL$C_KERNEL,- ; Set RMOD to KERNEL mode AST ACB$B_RMOD(R2) ; MOVL R6,ACB$L_PID(R2) ; IPID of target process MOVAB ACB$K_LENGTH(R2),- ; AST routine entry point (AST code ACB$L_AST(R2) ; is placed right after ACB header) ;Copy the AST code and data to the non-paged memory MOVL R2,R6 ;Save ACB address (destroyed by MOVC3) MOVC3 #AST_SIZE, AST_BEGIN,- ;Copy AST code into nonpaged pool. ACB$K_LENGTH(R2) ;(MOVC3 destroys R0 - R5) MOVL R6,R2 ;Restore ACB address ;Calculate address of DEVICED and place in DALLOC_ARGLST first argument MOVAQ (R2),- (R2) ;Calculate address of DEVBUF and place in DEVICED descripor. ;(Here we assume that DEVBUF comes immediately after the DEVICED descriptor) MOVAB (R2),- (R2) ;Calculate address of DALLOC_ARGLST and place in ASTPRM field of ACB MOVAB (R2),ACB$L_ASTPRM(R2) ;Queue the AST to the target process. MOVL R2,R5 ;Set R5 = ACB address MOVL #PRI$_TICOM, R2 ;Set AST priority increment class JSB G^SCH$QAST ;Queue the AST ;Reset IPL and exit returning status in R0 EXIT: UNLOCK LOCKNAME=SCHED, - ;Reset IPL to 0 NEWIPL=#0, - PRESERVE=YES ;Preserve R0 return status RET ;Normal exit here FORCE_DEALLOCATE_END: ;----------------------------------------------------------------------- .SUBTITLE ASTCODE ;+ ; This is the AST routine. It gets executed by the process it is queued to. ; Note that it is stored here as DATA (.PSECT ASTCODE set to NOEXE). ; The code comes first, followed by the data. ; ; When this AST routine is called, the following argument list is ; passed to it: ; +----------------+ ; | | 5 | 00(AP) ; +----------------+ ; | ASTPRM | 04(AP) (From the ACB header field ASTPRM) ; +----------------+ ; | Saved R0 | 08(AP) ; +----------------+ ; | Saved R1 | 0C(AP) ; +----------------+ ; | Saved PC | 10(AP) ; +----------------+ ; | Saved PSL | 14(AP) ; +----------------+ ; ; Inputs: ; Upon entry to the AST routine, 4(AP) contains the address of DALLOC_ARGLST. ;- .PSECT ASTCODE RD,WRT,NOEXE,LONG,PIC AST_BEGIN: ;This is the AST code: .ENTRY AST_CODE, ^M CALLG @4(AP),G^SYS$DALLOC ;Deallocate the device RET ;This is the AST data: .ALIGN LONG ;longword align DALLOC_ARGLST AST_DALLOC_ARGLST_OFFSET = . -AST_BEGIN ;Offset from beginning of AST block DALLOC_ARGLST: .LONG 2 ;Two arguments follow .LONG 0 ;address of DEVICED goes here .LONG PSL$C_KERNEL ;KERNEL access mode MAXDEVLEN=80 ;maximum device name length AST_DEVICED_OFFSET = . - AST_BEGIN ;Offset from beginning of AST block DEVICED: .WORD MAXDEVLEN .BYTE DSC$K_DTYPE_T .BYTE DSC$K_CLASS_S .ADDRESS DEVBUF DEVBUF: .BLKB MAXDEVLEN ASSUME DEVICED+8 EQUAL DEVBUF AST_END: ;AST_CODE ends here AST_SIZE = . - AST_BEGIN ;AST_SIZE = length of AST code & data ;------------------------------------------------------------------------------ .END MAIN