STAT und der DPB

STAT DEV: liefert Informationen über den Disk Parameter Block.

A>stat dsk:
    A: Drive Characteristics
 6400: 128 Byte Record Capacity
  800: Kilobyte Drive  Capacity
  192: 32  Byte Directory Entries
  192: Checked  Directory Entries
  128: Records/ Extent
   16: Records/ Block
   40: Sectors/ Track
    0: Reserved Tracks

Der zugehörige Disk Parameter Block DPB enthält die folgenden Werte. Daraus berechnet STAT die Werte für records per block und bytes per block und daraus die Ausgaben.

dpb:	dw	40		;SPT sectors per track
	db	4		;BSF block shift factor
	db	15		;BLM block mask
	db	0		;EXM null mask
	dw	399		;DSM disk size-1
	dw	191		;DRM directory max
	db	0E0H		;AL0 alloc 0
	db	0		;Al1 alloc 1
	dw	48		;CKS check size
	dw	0		;OFS track offset


rpb := 1<<BSF = 2^BSF; 			/* records/block */	= 2^4 = 16
bpb := 1<<BSF * 128 = 2^BSF * 128; 	/* bytes per block */	= 2^4*128 = 2048

Drive Characteristics		:= Laufwerk		= A
128 Byte Record Capacity	:= (DSM+1) * rpb	= (399+1) * 16 = 6400
Kilobyte Drive  Capacity	:= (DSM+1) * bpb / 1024 = (399+1) * 2048 / 1024 = 800
32  Byte Directory Entries	:= DRM+1		= 191+1 = 192
Checked  Directory Entries	:= CKS<<2 = CKS*4	= 48 * 4 = 192
Records/ Extent			:= (EXM+1) * 128	= (0+1) * 128 = 128
Records/ Block			:= rpb			= 16
Sectors/ Track			:= SPT			= 40
Reserved Tracks			:= OFS			= 0

Der originale Codeauszug von STAT, geschrieben in PL/M, ist relativ leicht zu verstehen. Lediglich die Berechnung der Gesamtkapazität ist ewas komplexer gelöst; PLM arbeitet nur mit 16 Bit. Deshalb muss die Multiplikation über diesen Zahlenbereich hinaus anders gelöst werden.

/* function call 32 returns the address of the disk parameter
block for the currently selected disk, which consists of:
        scptrk      (2 by) number of sectors per track
        blkshf      (1 by) log2 of blocksize (2**blkshf=blksize)
        blkmsk      (1 by) 2**blkshf-1
        extmsk      (1 by) logical/physical extents
        maxall      (2 by) max alloc number
        dirmax      (2 by) size of directory-1
        dirblk      (2 by) reservation bits for directory
        chksiz      (2 by) size of checksum vector
        offset      (2 by) offset for operating system
*/

    dpb based dpba structure
    (spt address, bls byte, bms byte, exm byte, mxa address,
     dmx address, dbl address, cks address, ofs address),
    scptrk literally 'dpb.spt',
    blkshf literally 'dpb.bls',
    blkmsk literally 'dpb.bms',
    extmsk literally 'dpb.exm',
    maxall literally 'dpb.mxa',
    dirmax literally 'dpb.dmx',
    dirblk literally 'dpb.dbl',
    chksiz literally 'dpb.cks',
    offset literally 'dpb.ofs';

declare bpb address; /* bytes per block */

set$bpb: procedure;
    call set$dpb; /* disk parameters set */
    bpb = shl(double(1),blkshf) * sectorlen;
    end set$bpb;

getalloca: procedure address;
    /* get base address of alloc vector */
    return mon3(27,0);
    end getalloca;

add$block: procedure(ak,ab);
    declare (ak, ab) address;
    /* add one block to the kilobyte accumulator */
    declare kaccum based ak address; /* kilobyte accum */
    declare baccum based ab address; /* byte accum */
    baccum = baccum + bpb;
        do while baccum >= 1024;
        baccum = baccum - 1024;
        kaccum = kaccum + 1;
        end;
    end add$block;

count: procedure(mode) address;
    declare mode byte; /* true if counting 0's */
    /* count kb remaining, kaccum set upon exit */
    declare
        ka  address,  /* kb accumulator */
        ba  address,  /* byte accumulator */
        i   address,  /* local index */
        bit byte;     /* always 1 if mode = false */
    ka, ba = 0;
    bit = 0;
        do i = 0 to maxall;
        if mode then bit = getalloc(i);
        if not bit then call add$block(.ka,.ba);
        end;
    return ka;
    end count;

drivestatus: procedure;
    declare
        rpb address,
        rpd address;
    pv: procedure(v);
        declare v address;
        call crlf;
        call pdecimal(v,10000);
        call printchar(':');
        call printb;
        end pv;
    /* print the characteristics of the currently selected drive */
    call print(.('    ',0));
    call printchar(cselect+'A');
    call printchar(':');
    call printx(.(' Drive Characteristics',0));
    rpb = shl(double(1),blkshf); /* records/block=2**blkshf */
    if (rpd := (maxall+1) * rpb) = 0 and (rpb <> 0) then
        call print(.('65536: ',0)); else
        call pv(rpd);
        call printx(.('128 Byte Record Capacity',0));
    call pv(count(false));	/* (maxall+1)*bpb/1024 */
        call printx(.('Kilobyte Drive  Capacity',0));
    call pv(dirmax+1);
        call printx(.('32  Byte Directory Entries',0));
    call pv(shl(chksiz,2));
        call printx(.('Checked  Directory Entries',0));
    call pv((extmsk+1) * 128);
        call printx(.('Records/ Extent',0));
    call pv(rpb);
        call printx(.('Records/ Block',0));
    call pv(scptrk);
        call printx(.('Sectors/ Track',0));
    call pv(offset);
        call printx(.('Reserved Tracks',0));
    call crlf;
    end drivestatus;