/* Disk Biology Mar 29, 1984 Version: 3.7 Written by: John P. Hohensee San Bernardino, CA (714) 884-0825 The CP/M system utilizes information contained in the system (B)asic (D)isk (O)perating (S)ystem to identify the format of a specific disk. Disk Parameter Header will locate items of interest about a disk drive, while the Disk Parameter Block details the information about the drive. This program will read all drives reporting the vital stat- istics contained within the CP/M system about the drive, location of this information, specific information and what the information does for your drive. This program was written with The Software Toolworks C/80 C language compiler version 2.0. "CPMCALL.C", providing bdos and bios routines for the C/80 version of C, was written by T. Bolstad, ELECTROKONSULT AS, and published in Dr. Dobbs Journal, Jun 83. The following is an example of the output product for the CP/M standard disk format: DSK-BIO x Request specified drive parameters where x = ('a' -> 'p') OR ('A' -> 'P') DSK-BIO * Request all drive parameters DSK-BIO Or any other character, Built-in HELP file Disk Biology - Version 3.7 - John P. Hohensee Placed in the Public Domain - 29 Mar 84 DISK PARAMETER BLOCK For disk drive A: SPT = 1A00 Records per track 26 BSH = 03 Block shift fact 3 DISK PARAMETER HEADER BLM = 07 Block shift mask 7 Disk Parameter Header starts @ E345 EXM = 00 Extent mask 0 DSM = F200 Num Alloc Blocks 242 Skew table starts @ E47B DRM = 3F00 Num Dir entries -1 63 Directory Buffer starts @ F556 AL0 = 1100$0000B Blocks reserved Disk Parameter Block starts @ E3D6 AL1 = 0000$0000B for directory Directory checksum starts @ FA62 CKS = 1000 Dir check size 16 Disk allocation table @ FAA2 OFF = 0200 Num System trks 2 Allocation size = 1024 Extent size = 16K Capacity of disk = 241K Number of tracks = 77 Disk type is 8", 48tpi, Single Sided Physical Rec Sequence for logical rec: (1, 2, 3, etc): 1 7 13 19 25 5 11 17 23 3 9 15 21 2 8 14 20 26 6 12 18 24 4 10 16 22 */ #include "cpmcall.c" /* Written by T. Bolstad, ELECTROKONSULT AS */ #include "printf.c" /* Standard print formatting */ #define short char /* Makes reading the data size easier */ int res, dsk; /* Global variable, Ones count, dsk drive */ main(argc,argv) int argc; char *argv[]; { /* Test for all logical drives */ if(*argv[1] == '*') { for(dsk = 0; dsk < 16; dsk++) { biology(); printf("\n\n\t\tPress to continue:"); getchar(); } exit(); } /* Test for a specified drive */ if('A' <= *argv[1] && *argv[1] <= 'P' ) { dsk = (*argv[1] & 037) - 1; biology(); exit(); } /* Print HELP file */ printf("\nDSK-BIO Print this built-in help file."); printf("\nDSK-BIO x Parameters for the specified drive."); printf("\nDSK-BIO * Parameters for all logical drives."); } biology() { int i, j, k; /* Temp variables */ int spt, spb, bpd, nsect, tpd; /* Compute variables */ char *skew_addr; /* Skew locations */ struct dpblock{ /* DISK PARAMETER BLOCK */ unsigned spt; /* Sectors per track */ short bsh; /* Block Shift factor */ short blm; /* Block shift mask */ short exm; /* Extent mask */ unsigned dsm; /* Drive storage capacity */ unsigned drm; /* Number of directory entries -1 */ short al0; /* Reserved for directory */ short al1; /* Reserved for dir 2 */ unsigned cks; /* Directory check vector size */ unsigned off; /* Number of reserved system tracks */ } *dpbptr; struct dph{ /* DISK PARAMETER HEADER */ int *skew_table; /* Pointer to Skew table */ int b1,b2,b3; /* BDOS work area */ int *dirbuff; /* Pointer to directory buff */ struct dpblock *dpb; /* Pointer to disk param block */ int *csv; /* Pointer to directory ck sum */ int *alv; /* Pointer to block alloc tble */ } *dpbase; /* bios(funct,arg1,arg2) as defined in "CPMCALL.C", [funct] is one of the bios calls, SETTRK, SELDSK etc. [arg1] and [arg2] are information required for the function. bdos(funct,arg1) as defined in "CPMCALL.C", [funct] is one of the bdos calls, RESET, RETCD etc. [arg1] is information required for that function. */ dpbase = bios(SELDSK,dsk,0); /* Current drive */ if(dpbase == 0) exit(); /* Disk Param Block Not Found */ dpbptr = dpbase->dpb; /* Pointer to disk param */ spt = dpbptr->spt; /* Number of records per track */ printf("\nDisk Biology - Version 3.7 - John P. Hohensee\n"); printf("Placed in the Public Domain - 29 Mar 84\n"); printf("\n DISK PARAMETER BLOCK"); printf("\t\tFor disk drive %c:",dsk+'A'); printf("\nSPT = %2x%2x Records per trk %4d", (dpbptr->spt & 0377),(dpbptr->spt)>>8,dpbptr->spt); printf("\nBSH = %2x Block shift fact %4d",dpbptr->bsh,dpbptr->bsh); printf("\t\tDISK PARAMETER HEADER"); printf("\nBLM = %2x Block shift mask %4d",dpbptr->blm,dpbptr->blm); printf("\tDisk Parameter Header starts @ %4x",dpbase); printf("\nEXM = %2x Extent mask %4d",dpbptr->exm,dpbptr->exm); printf("\nDSM = %2x%2x Num Alloc Blocks %4d", (dpbptr->dsm & 0377),(dpbptr->dsm)>>8,dpbptr->dsm); skew_addr = dpbase->skew_table; if(skew_addr) if(skew_addr < 32767) printf("\tNon-Standard Skew table defined."); else printf("\tSkew table starts @ %4x",dpbase->skew_table); else printf("\tNo Skew table address given"); printf("\nDRM = %2x%2x Num Dir entries %4d", (dpbptr->drm & 0377),(dpbptr->drm)>>8,dpbptr->drm); printf("\tDirectory Buffer starts @ %4x",dpbase->dirbuff); res = 0; printf("\nAL0 = "); binary(dpbptr->al0); /* Print hex digit in binary */ printf(" Blocks reserved"); printf("\tDisk Param Block starts @ %4x",dpbptr); printf("\nAL1 = "); binary(dpbptr->al1); printf(" for directory "); printf("\tDirectory checksum starts @ %4x",dpbase->csv); printf("\nCKS = %2x%2x Dir check size %4d", (dpbptr->cks & 0377),(dpbptr->cks)>>8,dpbptr->cks); printf("\tDisk allocation table @ %4x",dpbase->alv); printf("\nOFF = %2x%2x Num System trks %4d", (dpbptr->off & 0377),(dpbptr->off)>>8,dpbptr->off); /* Allocation Size: is one CP/M record, 128 bytes, times the log2 of the BSH. This is accomplished by shifting the constant 128 left BSH times. IE. files are written in multiples of the allocation size. */ printf("\n"); j = 128; i = j <<= dpbptr->bsh; /* Compute allocation size */ /* Reserve: defines the number of reserved allocation blocks, see the number of ONE'S printed in AL0 and AL1. Each block holds information for the directory on floppy disks. */ printf("\nAllocation size = %4d",i); printf("\tExtent size = %4dK",(dpbptr->exm+1) * 16); /* Disk Capacity: (D)isk (S)ector (M)aximum, do not confuse this with your sector size, defines the number of allocation blocks on this disk drive. (B)lock (S)hift (M)ask is a log2 of the multiplier used to define the maximum disk capacity. From the maximum capacity the size of system and directory space must be subtracted. */ j = dpbptr->dsm+1; k = j <<= ((dpbptr->bsh) - 3); /* Compute disk capacity */ printf("\nCapacity of disk = %4dK",k - ( i / 1024 * res)); bpd = dpbptr->dsm+1; /* This method is used to prevent */ spb = dpbptr->blm+1; /* possible overflow when large */ nsect = 0; /* capacity disks, ie hard disks */ tpd = 1; /* are addressed. */ for(i=0; i spt) { nsect -= spt; tpd++; } } tpd += dpbptr->off; printf("\tNumber of tracks = %4d",tpd); printf("\nDisk type is "); if(tpd < 42) printf("5\", 48tpi, Single Sided"); if(tpd > 74 && tpd < 78) printf("8\", 48tpi, Single Sided"); if(tpd > 78 && tpd < 82) printf("5\", 48tpi, Double Sided or 5\", 96tpi, Single Sided"); if(tpd > 150 && tpd < 158) printf("8\", 48tpi, Double Sided"); if(tpd > 158) printf("undeterminable."); /* SKEW PATTERN: Some drives use an offset between logical and physical records to improve the read/write speed of the drive. This pattern is reflected in the Physical record sequence. The print-out will display the sequence of logical records on the drive. */ if(skew_addr > 32767) /* Print skew table if used */ { skew_addr--; /* Initial decrement of skew location */ printf("\n\nPhysical Rec Sequence for logical rec: (1, 2, 3, etc)\n"); for(i=0; i