.title GETDISKS - return all disk drive names .ident /V1.01B/ .sbttl Documentation ; ; This routine will return all physical disk drive names ; on a system (or cluster). It does this by filling a ; user-supplied scratch area with the device names, then ; returning them one-at-a-time until that list has been ; exhausted. the status SS$_NOSUCHDEV is returned when ; the list is completely scanned. ; ; Calling format: ; ; STATUS = GETDISKS(CTXBUF, CONTEXT, DISKNAME, DISKLEN, [CLASS]) ; ; Where: ; ; STATUS = VMS Error status returned ; CTXBUF = User-supplied character buffer for the disk names ; ; CTXBUF must be big enough to store all of the disk ; names in it at once. If this is not the case, the ; status SS$_IVBUFLEN will be returned to the caller. ; ; CONTEXT = Context variable to maintain the position in the disk list ; DISKNAME = The returned disk name ; ; Note that if this string is too short, SS$_BUFFEROVF ; will be returned as well. ; ; DISKLEN = The length of the returned disk name ; ; CLASS = An optional parameter supplied to search for devices ; other than DISKS. these class types are defined in ; $DCDEF ; ; To abort walking the current buffered list and do a "fresh" ; lookup on the disks, zero the context variable. (This is done ; for you when a lookup is done after the last disk is returned.) ; ; Eric F. Richards ; Gould OSD VAXcluster VMS V4.2 ; 03-Mar-86 ; .sbttl Macros And Setup .page .library /sys$library:lib/ ; use version-sensitive library .link /sys$system:sys.stb//selective_search ; ...and symbol table .enable suppression ; clean up list files .disable traceback, debug ; and object files $ucbdef ; Unit Control Block offsets $dcdef ; Device class codes $ssdef ; System Service status codes $prdef ; Privileged register def'ns $ipldef ; Interrupt priority level codes numargs = 4 ; number of arguments to get usrbuf = 4 ; address of user buffer descriptor diskptr = 8 ; address of inter disk address ptr disknam = 12 ; address of single disk descriptor disklen = 16 ; address of char count for disk name class = 20 ; address of optional class type .sbttl Kernel-mode code .page .psect $aaaakrnl, page, nowrt, pic, shr krncod: .word ^m movzwl #ss$_ivbuflen, r0 ; set error at invalid length subl3 #4, 4(ap), r8 ; r8 = buffer length - safety bleq abort0 ; continue only if enough rm movl 8(ap), r7 ; r7 = buffer address movl 12(ap), r6 ; r6 = dev class to scan for movl g^sch$gl_curpcb, r4 ; get PCB for locking database jsb g^sch$iolockr ; lock I/O data base for read movl #1, r4 ;; return DVI$_ALLDEVNAM clrl r11 ;; init search context loop: jsb g^ioc$scan_iodb ;; begin I/O database scan movl r10, r5 ;; r5 has UCB address beql finish ;; r10=0 ==> no more to do! cmpb r6, ucb$b_devclass(r5) ;; is this what we want? bneq loop ;; skip if no movl r8, r0 ;; r0 has output buffer length movl r7, r1 ;; r1 has output buffer address ;; r4 has formation code still jsb g^ioc$cvt_devnam ;; build device name cmpw #ss$_normal, r0 ;; normal success? bneq abort ;; no: quit now incl r1 ;; r1 has length+1 subl r1, r8 ;; adjust r8 to reflect new len bleq abort ;; if negative, buffer overflow addl r1, r7 ;; set new starting address brb loop ;; continue until done abort: pushl #ss$_ivbuflen ;; set return status brb common ;; go to common cleanup code finish: pushl #ss$_normal ;; set success common: movl g^sch$gl_curpcb, r4 ;; get PCB for unlocking d-b jsb g^sch$iounlock ;; unlock I/O database setipl #0 ;; restore user IPL popl r0 ; set return status abort0: ret ; go back to user mode .sbttl User-mode Code .page .align long .entry getdisks, ^m movzwl #ss$_insfarg, r0 ; assume insufficient args movzbl #dc$_disk, r6 ; assume search for disk cmpb #numargs, (ap) ; did we get enough to work w/? beql 5$ ; if no extra args, go here bgtru 100$ ; if not, exit now movzbl @class(ap), r6 ; get dev class if supplied 5$: movl usrbuf(ap), r3 ; get descriptor location movzwl (r3), r8 ; get length from descr movl 4(r3), r9 ; r9 now has buffer address movl @diskptr(ap), r7 ; get our pointer into disk buf bneq 10$ ; if not null, have usable info movc5 #0, (sp), #0, r8, (r9) ; init buffer, check access pushl r6 ; else, build CMKRNL arg list pushl r9 ; ...arg 1 is buf len, arg 2 is pushl r8 ; ...the buffer address, arg 3 pushl #3 ; ...is the class to find movl sp, r0 ; save descr address $cmkrnl_s routin=w^krncod, - ; do the privileged stuff arglst=(r0) ; use this argument list blbc r0, 100$ ; bomb out if error movl r9, r7 ; init context pointer 10$: tstw (r7) ; are we out of disks? beql 60$ ; if so, return error addl r9, r8 ; calculate the length of... subl r7, r8 ; ...the rest of the buffer locc #0, r8, (r7) ; find the disk name end beql 60$ ; if none, return error addl3 #1, r1, r6 ; set context to new position subl r7, r1 ; r1=length of disk name movl disknam(ap), r4 ; get diskname descr movzwl (r4), r5 ; now have length of dest. str. movl 4(r4), r3 ; r3 has buffer address now movc5 r1, (r7), #^a/ /, r5, (r3) ; move disk into single dsk buf bgtru 70$ ; is the outbuf too small? movzwl #ss$_normal, r0 ; set success brb 90$ ; go to common return 60$: movzwl #ss$_nosuchdev, r0 ; no more devices clrl r6 ; zero our context pointer brb 95$ ; touch nothing else, exit 70$: movzwl #ss$_bufferovf, r0 ; set buffer overflow 90$: subl3 r7, r1, @disklen(ap) ; set output disk length 95$: movl r6, @diskptr(ap) ; save context variable 100$: ret ; go home .end ; ...th-th-that's all, folks!