:DSTAT C *DSTAT COMEIDSTAT DOC)VDSTAT.DOC 06/03/86 Every library should have a DOC file... This program dumps all available information in the Disk Parameter Header and Disk Parameter Block. It can be run with no arguments to report on the current disk, or with one argument which is the disk name. Note that since this is NOT a ZCPR utility, named directories are not supported. Nor have I tried this under CP/M 3.0, I have a feeling that at best it would return incorrect data. This is in response to an inquiry by Jay Sage, sysop of the Newton Centre ZNode: (617) 965-7259. See the end of this file for his suggestions and comments. One thing this program does NOT do is trace the vectors in the DPH (the Translation Vector, the Scratch Pad Vector, and the Allocation Vector). Two reasons for this are: I consider their information of limited usefulness, and the single reference I used to write this program, the CP/M 2.2 Operating System Manual, was vague as to the format and size of those vectors. I have A. Johnson-Laird's book, The Programmer's Guide to CP/M_, but it's at home today. Two other things this program does not do are: report on all available disks in the system, and dump the directory buffer. Both things were left out to reduce verbosity. I wrote this in C for one reason: speed in development. Nobody should have any complaints about execution time for this program, and I'll be the first to say that it's Too Damn Big, but you can't beat the time it took to write: three hours, with interruptions. No kidding, I was on the phone to Jay's ZNode at 3:00pm, and it's now 6:15pm. Also, it's a natural for C: only one extra routine (to print a number in binary), no special library routines aside from direct BDOS and BIOS calls, no include files... piece of cake. If I were really concerned with this program, I'd probably re-do it in assembler, using the C source as an outline. However, I view this as one of those utilities you put on the "Miscellaneous" disk, and only drag it out on rare occasions. I compiled it with the Aztec compiler - to be nice to the world at large, I used the 8080 compiler, rather than the Z80 compiler (not a big deal). One fix, however: Aztec uses lower-case letters for their Hex numbers; I patched these (at location A26) to use upper-case. Feel free to elaborate on this program - take my code, please! Wilson H. Bent, Jr. 39 Maple Ave. Fair Haven, NJ 07701 Work: (201) 949-1277 UN*X: ... ihnp4!hoh-1!whb RCP/M: Lillipute: (312) 649-1730 Chicago Msg 095 is 19 line(s) on 05/16/86 from JAY SAGE to PROGRAMMERS about PROPOSAL FOR CP/M BIOS UTILITY I would like to propose a CP/M utility program. There are a number of programs that will print for the user information about his operating system, such as the location of the CCP, BDOS, and BIOS. Some will even display the addresses of the actual BIOS routines as extracted from the initial jump table. I have not seen a program that will work its way through the disk parameter header (DPH) and disk parameter block (DPB) tables for all supported drives and display all the information contained in them for the user. STAT, DU, PATCH, and some other programs will display information about the data format on the drives, but they do not give the addresses of the directory buffer, allocation vector tables, etc. The reason why I wanted this kind of information recently is that I was looking for places in the BIOS to squeeze in the coldboot initialization code for a ZCPR3 installation. This is a handy way to get ZCPR3 running when you have no source for the BIOS but do have a MOVCPM that will move the BIOS. I got the information the hard way (just as the proposed utility would do it), but a ready-made utility would have been nice. The next message has some ideas on how this program would work. Msg 096 is 19 line(s) on 05/16/86 from JAY SAGE to PROGRAMMERS about HOW BIOS UTILITY WOULD WORK Here is how I think the total BIOS information utility would work Basically, the BIOS SELDSK routine (pointed to by the jump at BIOS+1BH) would be called for each disk in turn (0..15 in the C register). This code returns in HL the address of the disk parameter header or 0 if the drive is not a valid drive. With that information the program would simply work its way through the DPH table, following the pointers it contains to the skew translation table, the directory buffer, the disk parameter block (DPB), the directory check vector, and the allocation vector. The DPB would be queried to determine all the disk format information (at least what CP/M knows about it). See David Cortesi's book "Inside CP/M" for good technical information on the BIOS calls and the tables. And note his caution about calling the BIOS SELDSK routine directly. Make sure that the program determines what drive is selected at the beginning and that there is a last call to SELDSK using that drive. I think that should take care of that possible pitfall. One might even make a menu-driven version of this program that would allow the user to specify what information is desired.  One might even make a menu-driven version of this program /* DSTAT : Disk Stat: the Whole Shebang * Wilson H. Bent, Jr. : RCP/M: Lillipute: (312) 649-1730 Chicago * Version 0.1 : Last Mod 06/02/86 * * A Thorough Dump of the Disk Parameters as known by the BIOS. * Written for Aztec C : uses functions bioshl() and bdos() */ /* BDOS Defines */ #define SELDISK 14 #define CRNTDSK 25 /* BIOS Defines */ #define SELDSK 9 /* The structure member names are those used in * the CP/M 2.2 Operating System Manual */ /* Disk Parameter Header */ struct dph { char *xlt; /* Logical-Physical Translation pointer */ int xxx[3];/* (used by BDOS) */ char *dbuf; /* Directory Buffer pointer */ struct dpb *dpb; /* Disk Parameter Block pointer */ int *csv; /* Scratch Pad pointer */ int *alv; /* Allocation Vector pointer */ } *dphp; /* Disk Parameter Block */ struct dpb { int spt; /* Sectors per Track */ char bsh; /* Block Shift */ char blm; /* Block Mask */ char exm; /* Extent Mask */ int dsm; /* Max. Block Number */ int drm; /* No. of Dir Entries - 1 */ char al0, al1; /* Dir Block Bitmap */ int cks; /* Dir Check Vector Size */ int off; /* Reserved Tracks Offset */ } *dpbp; int currdisk; /* Current Disk */ int seldisk; /* Selected Disk */ unsigned int bls; /* Block Size */ long dcap; /* Disk Capacity */ main (argc, argv) char *argv[]; { register int i; /* preserve the current disk */ currdisk = bdos (CRNTDSK, 0); /* get the argument disk, if one is asked for */ if (argc > 1) seldisk = *argv[1] - 'A'; /* ..otherwise, use the current disk */ else seldisk = currdisk; /* use the BIOS call to get a pointer to the DPH */ dphp = bioshl (SELDSK, seldisk, 0); printf ("Disk %c:\n DPH: 0%04x\n", seldisk + 'A', dphp); if (dphp == 0) { printf ("No such disk!\n"); goto away; } /* The DPH Stats! */ printf ("Log-Phys Trans:\t0%04x\n", dphp -> xlt); printf ("Dir Buff:\t0%04x\n", dphp -> dbuf); printf ("Scratch Pad:\t0%04x\n", dphp -> csv); printf ("Alloc Vector:\t0%04x\n", dphp -> alv); /* the DPH has the pointer to the DPB */ dpbp = dphp -> dpb; /* The DPB Stats! */ printf ("\n DPB Addr: 0%04x\n", dpbp); printf ("Sect per Track:\t%5d\n", dpbp -> spt); printf ("Block Shift:\t %2d\n", (int)dpbp -> bsh); printf ("Block Mask:\t %2d\n", (int)dpbp -> blm); printf ("Extent Mask:\t %2d\n", (int)dpbp -> exm); /* Block Size is a computed value, not in the DPB */ for (i = dpbp -> bsh, bls = 1; i > 0; --i) bls <<= 1; bls *= 0x80; printf ("Block Size: %u bytes\n", bls); /* the Disk Capacity is also a computed value */ printf ("Max Block:\t %4xh\n", dpbp -> dsm + 1); dcap = (long) bls * (long) (dpbp -> dsm + 1); printf ("DISK CAPACITY (incl. Directory): %ld (0%lx) Bytes\n", dcap, dcap); printf ("Dir Entries:\t%5d\n", dpbp -> drm); printf ("Dir Bitmap: "); pbits (dpbp -> al0, 8); pbits (dpbp -> al1, 8); putchar ('\n'); printf ("DSV Size:\t%5d\n", dpbp -> cks); printf ("Sys Tracks:\t%5d\n", dpbp -> off); /* back to the proper disk! */ away: bdos (SELDISK, currdisk); } /* print NUM in binary, which is of size BITS */ pbits(num,bits) int num; int bits; { unsigned mask; for (mask = 1 << (bits - 1); mask; mask >>= 1) putchar ((num & mask) ? '1' : '0'); } m; int bits; { unsigned mask; for (mask = 1 << (bits - 1); mask; mask >>= 1) putchar ((num & mask) ? '1' ÷ !!"'!9^#V!#D! 9^#V##^#V^!"'J*'"'!*'! "'*'*'A!dG*'|ˆ!{GV*'^#V!G*'^#V!G*' ^#V!G*'^#V!G*' ^#V"'*'!G*'^#V!G*'##^!G*'###^!G*'^!-G*'##^BK!"'P`i+DM`i#m!*'~""'K!*'L""'*'!BG*'^#V#!XG!'*'^#V#9"H*'/"V̈́!6!'$H!'$H!jG! 9*'^#V!G!G!*' ^!*' ^! , *' ^#V!G*' ^#V!G*'!Disk %c: DPH: 0%04x No such disk! Log-Phys Trans: 0%04x Dir Buff: 0%04x Scratch Pad: 0%04x Alloc Vector: 0%04x DPB Addr: 0%04x Sect per Track: %5d Block Shift: %2d Block Mask: %2d Extent Mask: %2d Block Size: %u bytes Max Block: %4xh DISK CAPACITY (incl. Directory): %ld (0%lx) Bytes Dir Entries: %5d Dir Bitmap: DSV Size: %5d Sys Tracks: %5d ! 9^#V+!~"!9s#r!!9~#fo͎"s#r!9~#F! 9^#V!9~#foͣ";!1>!0, ! 9! 9^#V!, e8!9N#F!"h%!9^#V"f%!9~#fo#s#r+^"d%|t *d%%"S !!9s!"j%! "l%!'"n%!9~#fo#s#r+^"d%-"!"j%!9~#fo#s#r+^"d%*d%0"0!0"l%!9~#fo#s#r+^"d%*d%*"h*f%##"f%++^#V"p%!9~#fo#s#r+^"d%õ!"p%É!9~#fo#s#r+^"d%*d%$#^!ͣ"ʵ*p% L"*d%"p%q*d%."[!9~#fo#s#r+^"d%*"*f%##"f%++^#V"n%!9~#fo#s#r+^"d%[!"n%/!9~#fo#s#r+^"d%*d%$#^!ͣ"[*n% L"*d%"n%!"r%*d%l"ʎ!9~#fo#s#r+^"d%!"r%ò*d%h"ʲ!9~#fo#s#r+^"d%*d%B!"t%! "t%!"t%!"t%*r%!9*t%*f%x !9"v%*r%*f%"f%a*f%##"f%++^#V"v%"r%o*f%##"f%++^#V"d%*d%!9"v%sa2#c!dosux2!9*v%)#"r%*r%*n%#ʂ*n%"r%*j%|Ô*h%#"h%*p%+"p%#*r%#*l%`i͟"ʽ!Í!"t%*t%#"t%*v%~ *t%*n%# *v%#"v%+^`i͟" !*t%*h%"h%*j%|P $ *h%#"h%*p%+"p%#*r%#P ! `i͟"M ! q *d%`i͟"j !*h%#"h%Ã*h%!"x#"z#! 9~2v#G+V+^+6"t#+N+V+^!x#w#  y /w# !{#>^)| g, s+= Z! ~*t#+"t#w!x# # *t# +6-0123456789ABCDEF!#! 9^#VD !9N#F`i "z ! 9^#V! ͉ "z !! 9^#V͉ ! 9N#F! ^#V`i^#VY#ʿ !9^#V!ͣ"͇ !9^#V`i~#fo#s#r+s!ͣ"!|#DM`i#g# `i DM !9N#F!"x%`i~z ! ^!ͣ"H !͇ "x%! ^;*x%ͳ""x%! ^!ͣ"z ! ^#VC!! s*x%!9N#F! "w$! ^!ͣ"ʮ !! ^!ͣ" ! ^#V`i^#V)#"z%*z%! ^#V! ^f*z%" !`in&ͳ"s!`is#r! s#r!! 9^#V!"X !`in&ͣ"s!`is#r! s#r!`i~#i G ! ^#V!"ʢ !! 9! ^f" ! 9^#V! ^#V`is#r! ^#V! ^#V! s#r!`in&ͳ"s! 9^#V`i~#fo#s#r+s!ͣ"!|#DM`i~- `i DM#Y#* ! !`is#r! s#r! s#r`i!9N#F! ^q} !! s#r`i! s#r!͞"|%|c !! s#r!`inͳ"s*|%! s#r!d%^s# y¿ *"'*#"' # !!%!M!:o&ͣ"%s!"%!%DM!"F&*F&#ʺ`i^! "T`i^! "\`i#DM8`i~ʺ`i^!>"z!"J&Î`i^!<"k!"J&`i#DM^! "­`i^! "ʰÎ`i"H&`i#DM~`i^! "`i^! "!`i#DM+sõ*J&;*J&|!*H&͝"J& !*H&;"J&*J&"h!!Ϳ*H&!!!!! ! ÷`i*F&#"F&+)%s#r`i#DM~ʷ`i^! "¥`i^! "ʴ!`i#DM+s÷+!%*F&!Can't open file for redirection: $*w$͟!DM`i # `i#DM+;!9~#C!ͣ"C!G A:$$$.SUB!"'!!con:CON:lst:LST:prn:PRN:pun:PUN:rdr:RDR:! 9^#V!! 9^#V;!$"L&!"P&*L&"L&*P&#"P&*P& #*L&^#V!Q"!"'!!$DM!`iDM`i~#B!9^#V`i^#V͇B! ^#V"N&! 9^#V!ͣ"#"R&*R&ͣ"ʃ*N&^*L&s{ƒ!"'!*R&ͣ"ʪ*N&#^*L&#s{ª!"'!! ^#V*L&s#r*N&##^*L&##s*N&###^*L&###s!a*L&s#r*L&!9^#V!9^#V!9^#V*N&^#V͟! 9!#7!Q*L&s#r!*P&!9^#V!#a!9^#V! #k!"'!!9^#V)))$DM! ^#V! ^#V͟!9s#r!! s! s! s`is!Q! s#r!9^#V!T&DM`i'DM`i'g#`i%~!"'!! 9^#V0"'" !"'!*'"2S"'*'b! 9^#V!ͣ"T!!"ʚ! 9^#V!ͣ"ʊ!"ʗ!"'{!ý! 9^#V!ͣ""ʽ!"'{!!!! s#r!# s!$ s*'!& s`i!9^#V!s#r! 9^#V!ͣ"#!% s!0!9^#V!s#r! 9^#V!ͣ"){!!9N#F!& ^b!{!!% s!!9^#V)))$DM! 9^#V! 9^#V! ^#V! ^)$^#V͟!DM!9^#V"'*'&^b*'$~(*'$^!)#DM! 9~#foh# ! 9^#VBK! 9^#V*'({!! 9^#V`i)#͎""'|ʉ*'! 9^#V`i*'͓"'|ʉ{*'*')#~"PYDM|†!`i*'~"PYDM`i! 9~#fog#! 9^#V`i)#! 9^#V`i*'{`i{! 9^#V!9N#F#!! 9^#V!$ ^!!9^#VM!""'|8!!$ ^! 9~#foͣ"!$ s{j`i!~#fo#s#r!! 9N#F! 9^#V"'*'+"'#|`i^! "ʮ! !`i#DM+^!Æ! 9^#V! 9N#F! 9^#V"'*'+"'#| `i#DM+^! 9^#V! 9^#V!9N#F!#`i!~#E!!$ s!`i!~#fo+s#rb!!"'*'h#ʕ*'+"'^!"ʒ*'#"'Õh*'!$ s!"`i!~#fo#s#r!!$ s!!"'!9N#F!!*'PY" !! ^#V*'"m!!"'"/*'"Q!"'!!!1!"'!*'|]!`i"'!! ^#V"'!!9^#V)))!$^!Ø"*_%!"_%*]%*]%!4#4*a%+"a%}™o&"'*a%!9!29^#V0DMb!9!DM{`i"-!"'!!!9N#F! ^#V+))"'C! 9^#V͞"'|ʚ*'PY"ʚ! 9^#V*'h#ʆ*'Î! 9^#V*'M*'!9^#V###͎"#"'*'"'|!'"'"'"'*'##^#VBK`i"'! ^#VBK! ^#V`i"k! ^#V`i^#V))PY"k! ^#V*'":! ^#V##^#V"'! ^#V^#V`i~#fos#r! ^#V##^#V! s#r`i^#V*'Y#`i^#V*'"ʛ! ^#V*'##s#r*'))PY"'*'*'##s#r! ^#V*'##s#r`i^#V*')#*'s#r*'`is#r*'"'!! s#r`i`i*'"?!DM"!!`is#r!! s#r`iC*'DM!9^#V!"'*'##~#f!*'DMw! ^#VBK`i*'h#–! ^#V*'h#! ^#V`iY#*'PYh#! ^#V*'g#n! ^#V*'##s#r*'! s#r`i"'!*]%DM*_%ogo&*]%*+++*_%DM*a%!9N#F#^#Vkb6#> 6 #=C>6#=Ly d hY ځ0_zWk/‹Î : >¹ A[Ҫ@öa{`w# .ʼw#ý{o|g w#&jz!|* >?a{ 0:7!9^#V*#=*'}|=*#"#|!=!9}_|#W"' o& 2$:]% _ :$_!9Û!9F+N+V+^+~+ngxʹ¹ʹ# äog!9V+^+~+ngw#|!9!9F+N+V+^+~+ng対#xw# w|!9~#fo-#$}!9^#V#N#F#nxKs# @! 9F+N+V+^+~+ngډm}ډʝ }++w x}ɯ~# x“DM!99`i͟|DM!99!`i~# x!9]%~#! |!%'!~%~#~#~#~~%w#w#w#w!%*%*~%"%"%*%*~%"%"~%*%*%"%"%!~%>w#„!~%~!#“!=ɯ<%!%~O%!%ڠ¤+~%!%#~%!%#~%!%# ~%!%# ~%!%#1 !~%~/w#A :%?*~%*%))_ ,=W "%"~%r :%:%?ʏ W!%~w+ƒ | !NyÁ~%͑ %͑ y ~~%͑ y%͑ %!~%w# ~ %!~%w# !%w#!> !~%~w#!O%!%#'!y@!!~%4= !=q!!~%~w#L!O%!%#_!y@!6!%!%#z!!~%%~6#!> !~%~w# !ҽ!~%!%#´!=™!ͨ!!ͨ!!<ͨ!!ͨ!!!ͨ!!ͨ!!!ͼ!!ͼ!!!ͼ!!ͼ!!!"~%!"%"~%|2"!"%*~%DM!>))\" =T"}{_ʋ"|"|7g}oq"{_ʋ")†"}{_ʋ"|g}o–"|g}o|/g}/o|g}o|g}o|""}"|"!}"|"!}|"}|?>o&zo&|#}|>o&|o&}/o|/g#}}o|gBK^#VzR##yL####:##xG##~#fo}|>?o&}|>o&'???????????aaaQQQQQQQQaaaaky$py$u$z$$$$$$$$Q 00000 @@@@@@@@@@@@@@@ @@@@@@@ @@@@@ @@@@