.Title devices - Get all device names of a given class .Ident /V01.001/ .Enable SUP .Default Displacement,Word .Subtitle Introduction ;+ ; ; ----- devices - Get all device names of a given class ; ; ; Facility: ; ; VAX/VMS system programming ; ; Abstract: ; ; This module provides a routine which can be called from any ; VAX native language to obtain all the device names of a specific ; class. ; ; Environment: ; ; VAX/VMS native mode, VMS V4.2 or later, CMKRNL privilege. ; ; Version: V01.001 ; Date: 12-Apr-1988 ; ; ; Modifications: ; ; ;- .Page .Subtitle Local definitions .Library "SYS$LIBRARY:LIB" ;Get special macros from here .Link "SYS$SYSTEM:SYS.STB"/Selective_Search ;Ease the link process a bit .NoCross ;Save a tree $DCDEF ;Device class & type definitions $DDBDEF ;Device data block offsets $IPLDEF ;interrupt priority level $SBDEF ;System Block $SSDEF ;System service codes $TTYUCBDEF ;Terminal UCB offsets $UCBDEF ;UCB offsets .Cross ;Turn CREF back on .Page .Subtitle device names ;+ ; ; ----- devices - Get device names ; ; ; The calling program must have CMKRNL privilege and must be linked ; with SYS.STB. ; ; Call sequence: ; ; status.wlv = devices (device-class, pid, num-elemnts, elemnt-size, array) ; device-class = -1 means all devices, else, specifies class of device ; pid = if -1, match on any pid other than zero, if 0 match on anything ; else match on pid ; num-elemnts = number of elements in array ; elemnt-size = size of each element in array ; note: includes 4 bytes for PID, 2 bytes for length, and string ; array = address of array ; ; Inputs: ; ; 4(AP) - address of the device class ; 8(AP) - address of flags ; 12(AP) - number of elements in device name array ; 16(AP) - size of elements in device name array ; ; Outputs: ; ; 20(AP) - Address of a device name array ; ; R0 - SS$_NOPRIV: No CMKRNL privilege. ; - SS$_ACCVIO: One of the arguments is not accessible. ; - SS$_NORMAL: Success. ; ;- ARGS = 5 .Psect devices EXE,RD,NOWRT,PIC,SHR,PAGE .Entry devices,^M<> ;Entry here $CMKRNL_S ROUTIN=B^20$,- ;Do this ARGLST=(AP) ; in kernel mode 10$: RET ;Done, status in R0 ; Here in kernel mode to do all of the actual work. 20$: .Word ^M ;Here in kernel mode to get some info ; First, check to see if we can read the argument list. MOVL #SS$_ACCVIO,R0 ;Presume we can't IFNORD #<*4>,(AP),10$ ;Probe the argument list ; Check the number of arguments MOVL #SS$_INSFARG,R0 ;Presume we have too few arguments CMPB #ARGS,(AP) ;Do we have enough arguments? BNEQ 10$ ;If NEQ no, it's wrong somehow ; Check to see if we can read the device-type MOVL #SS$_ACCVIO,R0 ;Presume we can't IFNORD #4,@4(AP),10$ ;Probe the device type MOVL @4(AP),R9 ;save the device type ; Check to see if we can read the PID MOVL #SS$_ACCVIO,R0 ;Presume we can't IFNORD #4,@4(AP),10$ ;Probe the PID MOVL @8(AP),R3 ;save the PID ; Check to see if we can read the 'number of elemnts in array' MOVL #SS$_ACCVIO,R0 ;Presume we can't IFNORD #4,@8(AP),10$ ;Probe the array size MOVL @12(AP),R8 ;save the array size ; Check to see if we can read the 'size of elemnts in array' MOVL #SS$_ACCVIO,R0 ;Presume we can't IFNORD #4,@8(AP),10$ ;Probe the size MOVL @16(AP),R6 ;save the size ; make sure R6 is bigger than 6 MOVL #SS$_BUFFEROVF,R0 ;Presume it isnt CMPL R6,#6 BLSS 10$ ; multiply to get the size of the array in bytes MULL3 R6,R8,R1 ; Check to see if we can write the device-name-array MOVL #SS$_ACCVIO,R0 ;Presume we can't IFNOWRT R1,@20(AP),10$ ;Probe the device name array MOVL 20(AP),R7 ;save the address of array ; Ok. Now go though the I/O database! MOVL G^SCH$GL_CURPCB,R4 ;Get my PCB address JSB G^SCH$IOLOCKR ;Lock the I/O database mutex ; we are now at IPL 2, and we can happily page fault! CLRQ R10 ; clear r10, and r11 - for ioc$scan_iodb 30$: JSB G^IOC$SCAN_IODB BLBC R0,50$ ; well, we're done. ; R9 contains device class, if -1 then go ahead and take this ; otherwise, check class, if not equal skip to next ddb CMPL R9,#-1 BEQL 35$ CMPB R9,UCB$B_DEVCLASS(R10) BEQL 35$ CLRL R10 ; Implies end of ucb chain BRB 30$ 35$: ; match on any PID? (even zero) TSTL R3 BEQL 37$ ; yes, go get it ; PID must be non-zero, else skip this device MOVL UCB$L_PID(R10),R0 ; may as well prepare for conversion BEQL 30$ ; go on to the next device ; match on any PID? CMPL #-1,R3 BEQL 37$ ; yes, don't bother checking it.. ; must have exact PID match, convert pid to proper format JSB G^EXE$IPID_TO_EPID ; Convert to extended PID CMPL R3,R0 ; exact match? BNEQ 30$ ; nope, skip to next device 37$: MOVL #SS$_BUFFEROVF,R0 ; need a better error - too many units TSTL R8 BEQL 60$ 40$: ; r6 contains length, r7 = address of string ; need to move length to R0, and address to R1 MOVQ R6,R0 SUBL #6,R0 ; decrement size ADDL #6,R1 ; leave room for length MOVL #-1,R4 ; type of device name wanted ; okay, we have a UCB in R10, ioc$cvt_devnam needs it in R5 MOVL R10,R5 JSB G^IOC$CVT_DEVNAM MOVW R1,4(R7) ; save length BLBS R0,45$ ; everything okay? MOVW #-1,4(R7) ; if overflow, set length to -1 45$: MOVL UCB$L_PID(R10),R0 JSB G^EXE$IPID_TO_EPID ; Convert to extended PID MOVL R0,(R7) ; move pointer into array ahead by one string length ADDL R6,R7 ; r8 = number of elements left in the array DECL R8 BRB 30$ 50$: MOVL #SS$_NORMAL,R0 ;Success! 60$: MOVL G^SCH$GL_CURPCB,R4 ;Get my PCB address again PUSHL R0 ;Save the return status JSB G^SCH$IOUNLOCK ;Unlock the I/O database mutex SETIPL #0 ;Drop back down from IPL$_ASTDEL POPL R0 ;Restore the return status RET ;Back to user mode .END