MODULE lister;

(* example code showing how to scan the DOS device list
   to work out what devices are available to DOS,
   what their types are ( whether they're a device, a dir etc ),
   and how to extract info on properties of devices ( host device
   physical parameters etc )
*)

(* by J Davis v1.0 10/89            *)
(*            v1.1 6/90             *)
(* compiled using TDI M-2 v3.01a    *)

(* thanks to Patrick Horgan for the  code he 
   posted to UseNet showing how to do the enviroment probing 
*)

FROM DOSLibrary      IMPORT DOSName,DOSBase,BPTR,BSTR;
FROM DOSExtensions   IMPORT DosBaseRec,RootNode,DosInfo,DeviceList;
FROM AmigaUtils      IMPORT PtrFromBPTR;
FROM SYSTEM          IMPORT NULL;
FROM InOut           IMPORT WriteString,WriteLn,Write;
FROM LongInOut       IMPORT WriteLongCard,WriteLongInt,WriteLongHex;
FROM Libraries       IMPORT OpenLibrary,CloseLibrary;
FROM DOSLibrary      IMPORT DateStampRec;
FROM FileHandler     IMPORT DeviceNode,FileSysStartupMsg;
FROM SYSTEM          IMPORT ADDRESS,BYTE;

TYPE 

string = ARRAY [0..255] OF CHAR;
strptr = POINTER TO string;

DOSenv = ARRAY [0..255] OF LONGCARD;

VAR

ourdosbase : POINTER TO DosBaseRec;             (* use this to access dosbase *)
infoptr    : POINTER TO DosInfo;                (* points to DOSinfo node     *)
devlistptr : POINTER TO DeviceList;             (* points to current place is DOS devlist *)
devnodeptr : POINTER TO DeviceNode;             (* used for accessing device nodes *)
fssm       : POINTER TO FileSysStartupMsg;      (* used to access the filesystemstartupmessage *)  
dosenvptr  : POINTER TO DOSenv;

nameptr    : strptr;
cptr       : POINTER TO CHAR;
p          : CARDINAL;



PROCEDURE WriteBSTR(b:BPTR);
(* output a BSTR *)
VAR
nptr : strptr;
c    : CARDINAL;
BEGIN
nptr:=PtrFromBPTR(b);
IF nptr^[0]>=CHR(1) THEN
   FOR c:=1 TO ORD(nptr^[0]) DO
       Write(nptr^[c]);
   END;
END;
END WriteBSTR;


BEGIN

DOSBase:=OpenLibrary(DOSName,0);   
(* open the dos lib *)

WriteString("listdevs v1.2 By John Davis 6/90");
WriteLn;

ourdosbase:=DOSBase;                              
(* get a usable pointer onto dosbase *)

infoptr:=PtrFromBPTR(ourdosbase^.dlRoot^.rnInfo); 
(* get pointer to dosinfo struct *)

devlistptr:=PtrFromBPTR(infoptr^.diDevInfo);      
(* get a pointer to start of devlist *)

WHILE devlistptr<>NULL DO
      (* scan down device list checking as we go *)
          
      (* print out the device name *)
      WriteString("node name : ");
      WriteBSTR(devlistptr^.dlName);
      WriteLn;
      
      Write(CHR(9));
      
      (* determine the nodes type and display it *)
      IF devlistptr^.dlType=0 THEN
         WriteString("Type         : DEV ");
         WriteLn;
      ELSIF devlistptr^.dlType=1 THEN
         WriteString("Type         : DIR ");
         WriteLn;
      ELSIF devlistptr^.dlType=2 THEN
         WriteString("Type         : VOL ");
         WriteLn;
      ELSE
         WriteString("Type         : ??? ");
         WriteLn;
      END;
         
      (* I'm primarily interested in devices,  
             VOLUMES are simply currently mounted disks
             DIRS are assigned logical drives ( such as fonts: )
      *)

      IF devlistptr^.dlType=0 THEN
         (* node is a device node, extract extra info *)
        
         devnodeptr:=ADDRESS(devlistptr);          
         (* transform to right type *)
          
         fssm:=PtrFromBPTR(devnodeptr^.dnStartup); 
         (* get pointer to filesystemstartup block *)
         
         dosenvptr:=PtrFromBPTR(fssm^.fssmEnviron);
         (* get pointer into enviroment block *)
                  
         (* if there's no fssm the fssmptr _should_ be null, but this
            doesn't seem to be always true ( espec on par, prt and ser )
            so check to see if the dosenv[de_tablesize] makes sense also
         *)
         IF (fssm<>NULL) AND (dosenvptr^[0]<=16) THEN

            (* printout host device for this dev *)
            Write(CHR(9));
            WriteString("Device       : ");
            WriteBSTR(fssm^.fssmDevice);
            WriteLn;

            (* and the host devices unit *)
            Write(CHR(9));
            WriteString("Unit         : ");
            WriteLongCard(fssm^.fssmUnit,8);
            WriteLn;
            
            (* now probe the enivroment space *)
           
            FOR p:=0 TO SHORT(dosenvptr^[0]) DO
                Write(CHR(9));
                
                CASE p OF
                   0:  WriteString("env size     : "); |
                   1:  WriteString("block size   : "); |
                   2:  WriteString("SecOrg       : "); |
                   3:  WriteString("Num Heads    : "); |
                   4:  WriteString("Sec / Blk    : "); |
                   5:  WriteString("blks / track : "); |
                   6:  WriteString("reserved     : "); |
                   7:  WriteString("prefac       : "); |
                   8:  WriteString("Interleave   : "); |
                   9:  WriteString("Low Cyl      : "); |
                  10:  WriteString("High Cyl     : "); |
                  11:  WriteString("Buffers      : "); |
                  12:  WriteString("bufmemtype   : "); |
                  13:  WriteString("Maxtransfer  : "); |
                  14:  WriteString("Mask         : "); |
                  15:  WriteString("bootpri      : "); |
                  16:  WriteString("DOStype      : ");
                END;
         
                IF p<>16 THEN
                   WriteLongCard(dosenvptr^[p],8);
                ELSE
                   WriteLongHex(dosenvptr^[p],16);
                END;
         
                WriteLn;
            END;         
         END;
         
         (* display the taskpri of the device handler *)
         Write(CHR(9));
         WriteString("Pri          : ");
         WriteLongInt(devnodeptr^.dnPriority,8);
         WriteLn;

         (* and the amunt of stack for that task *)
         Write(CHR(9));
         WriteString("Stack        : ");
         WriteLongCard(devnodeptr^.dnStackSize,8);
         WriteLn;
         
         (* print out the name of the handler *)
         Write(CHR(9));
         WriteString("Handler      : ");
         cptr:=PtrFromBPTR(devnodeptr^.dnHandler);
         IF cptr^ = CHR(0) THEN
            WriteString(" default dos handler");
         ELSE
            WriteBSTR(devnodeptr^.dnHandler);
         END;
         WriteLn;
               
      END; (* device case *)

      (* I don't bother extracting any info from VOLUMES|DIRS
         there's not much of interest in there anyway
      *)
    
      WriteLn;
      
      devlistptr:=PtrFromBPTR(devlistptr^.dlNext); 
      (* scan on down devlist *)
END;


CloseLibrary(DOSBase);

END lister.
