;***************************************; ; ; ; S U R V E Y ; ; ; ;***************************************; ;By Michael Friese 9/22/79 ;* Lists Kbytes used and remaining plus number of files ; on all logged disks (up to 8) ;* Prints Memory map and synopsis of all machine memory ;* Lists all active I/O Ports ;* Uses disk allocation block for all disk calculations ; ;06/24/80 - Removed MACLIB statement, included required macros ; in source. Bruce R. Ratoff ; ;06/28/80 - Added IMS400 equate (prevents Industrial Micro Systems ; controller from hanging up during port scan). BRR ; ;06/29/80 - Added version number test and calculations for CP/M ; version 2 compatibility. This program should now work ; properly on all versions 1.4 and later. BRR ; ; ; ;*******************************; ; SYSTEM MACROS ; ;*******************************; ;Increments 16 bit memory location X INXI MACRO X LOCAL JUST8 PUSH H LXI H,X INR M JNZ JUST8 INX H INR M JUST8: POP H ENDM ;.................................................................. ; ; SAVE MACRO SAVE SPECIFIED REGISTERS ; ; SAVE R1,R2,R3,R4 ; ; R1-R4 MAY BE B,D,H OR PSW SAVED IN ORDER SPECIFIED ; IF REGS ARE OMITTED SAVE B,D AND H ; SAVE MACRO R1,R2,R3,R4 IF NOT NUL R1&R2&R3&R4 IRP R,<,,,> IF NUL R EXITM ENDIF PUSH R ENDM ELSE IRPC REG,BDH PUSH REG ENDM ENDIF ENDM ; ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; ; RESTORE MACRO RESTORE REGISTERS (INVERSE OF SAVE) ; ; RESTORE R1,R2,R3,R4 ; ; R1-R4 MAY BE B,D,H OR PSW RESTORED IN ORDER SPECIFIED ; IF REGS OMITTED RESTORE H,D AND B ; RESTORE MACRO R1,R2,R3,R4 IF NOT NUL R1&R2&R3&R4 IRP R,<,,,> IF NUL R EXITM ENDIF POP R ENDM ELSE IRPC REG,HDB POP REG ENDM ENDIF ENDM ; ; . . . . . . . . . . . . . . ... ... . .. . . . . . . . . ; ; CHAROUT MACRO CONSOLE OUTPUT FROM A ; ; CHAROUT ADDR ; CHAROUT MACRO ADDR IF NOT NUL ADDR LDA ADDR ENDIF MVI C,2 ;;CONOUT MOV E,A ;;CHAR TO E CALL 5 ;;CALL BDOS ENDM ; ; ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; ; DECOUT MACRO CONVERT A POSITIVE INTEGER TO DECIMAL AND OUTPUT ; TO THE CONSOLE. ; ; DECOUT ADDR ; ; IF ADDR OMITTED, NUMBER ASSUMED TO BE IN HL, ELSE LOADED TO HL ; LEADING ZEROS SUPRESSED. MAXIMUM NUMBER 65,767 ; DECOUT MACRO ADDR LOCAL ENDDEC,DX JMP ENDDEC @DECOUT:SAVE ;;PUSH STACK LXI B,-10 ;;RADIX FOR CONVERSION LXI D,-1 ;;THIS BECOMES NO DIVIDED BY RADIX DX DAD B ;;SUBTRACT 10 INX D JC DX LXI B,10 DAD B ;;ADD RADIX BACK IN ONCE XCHG MOV A,H ORA L ;;TEST FOR ZERO CNZ @DECOUT ;;RECURSIVE CALL MOV A,E ADI '0' ;;CONVERT FROM BCD TO HEX MOV E,A ;;TO E FOR OUTPUT CHAROUT ;;CONSOLE OUTPUT RESTORE ;;POP STACK RET ENDDEC: DECOUT MACRO ?ADDR IF NOT NUL ?ADDR LHLD ?ADDR ENDIF CALL @DECOUT ;;CALL THE SUBROUTINE ENDM DECOUT ADDR ENDM ; ; ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; ; HEXOUT MACRO CONVERT BINARY NO AND OUTPUT TO CONSOLE ; ; HEXOUT ADDR ; ; NUMBER ASSUMED IN A IF NO ARGUMENT ; HEXOUT MACRO ADDR LOCAL OUTCHR,HEXEND JMP HEXEND HEXPRN: SAVE PSW RRC RRC RRC RRC ;;SHIFT RIGHT 4 CALL OUTCHR RESTORE PSW OUTCHR: ANI 0FH ;;MASK 4 BITS ADI 90H ;;ADD OFFSET DAA ;;DEC ADJUST ACI 40H ;;ADD OFFSET DAA ;;DEC ADJUST MOV E,A ;;TO E FOR OUTPUT MVI C,2 ;;CONOUT JMP 5 ;;CALL BDOS HEXEND: HEXOUT MACRO ?ADDR IF NOT NUL ?ADDR LDA ?ADDR ENDIF CALL HEXPRN ENDM HEXOUT ADDR ENDM ; ; ;*******************************; ; SYSTEM EQUATES ; ;*******************************; TRUE: EQU -1 FALSE: EQU NOT TRUE TARBEL: EQU FALSE ; Tarbell FDC IMS400 EQU TRUE ; Industrial Micro Systems FDC TARBAS: EQU 0F8H ; Base of Tarbell IF TARBEL SKIPORT EQU TARBAS+4 ; Port # to skip if Tarbell FDC ENDIF IF IMS400 SKIPORT EQU 08FH ; Port # to skip if IMS FDC ENDIF BDOS: EQU 5 ; Base of BDOS CRLF: EQU 0A0DH ; CR LF sequence CRLFE: EQU 8A0DH ; CR LF with EOL EOL: EQU 80H ; End of line TAB: EQU 'I'-40H ; Tab character ESC: EQU 1BH ; Escape character TABS: EQU 9 ; Tab columns ;***********************; ; MAIN PROGRAM ; ;***********************; ORG 100H START: LXI H,0 ; Save stack pointer DAD SP SHLD OLDSP LXI SP,FINIS+64 CALL TYPE ; Type initial CRLF DB TAB,TAB,TAB,'*** SYSTEM SURVEY ***' DW CRLF,CRLFE ;DISK SURVEY LXI H,8 ; Init drive counter MVI C,24 ; Get login vector PUSH H CALL BDOS POP H ROTBIT: RAR ; RAR login bit to C JNC NOTLOG ; Drive not logged PUSH PSW ; Save login PUSH H ; and counter ;Print drive letter CALL TYPE DB 'Drive' DB ' '+EOL MVI A,'A' ; Get ASCII bias ADD H ; Add to drive # MOV E,A ; Print drive letter CALL TCHR CALL TYPE ; and colon DB ':',' '+EOL POP H ; Restore drive # PUSH H ;Print K already allocated MOV E,H MVI C,14 ; Log drive CALL BDOS MVI C,27 ; Index allocation vect CALL BDOS MOV L,A ; Put in decent regs MOV H,B PUSH H ; save for later MVI C,12 ; get version # CALL BDOS MOV A,L ; zero if version 1 ORA A JNZ V2X ; otherwise, use 2.x style params LHLD BDOS+1 ; get vers 1 style params MVI L,3CH MOV A,M ; get block shift factor STA BLKSHF INX H INX H MOV L,M ; get max. block number MVI H,0 SHLD MAXALL MVI B,32 ; assume 32 bytes in block map JMP GETALC ; continue V2X: MVI A,'?' ; Use wild user # STA FCB ; in filename search MVI C,31 ; Get 2.x parameter block CALL BDOS INX H INX H MOV A,M ; Get and save ablock shift factor STA BLKSHF INX H INX H INX H MOV A,M ; Get maximum block number INX H ; (double precision) MOV H,M MOV L,A SHLD MAXALL INX H MVI B,3 ; map size is (MAXALL+1)/8 V2SH: MOV A,H ORA A ; do 16 bit right shift RAR MOV H,A MOV A,L RAR MOV L,A DCR B ; 3 times JNZ V2SH MOV B,L LDA MAXALL ; allow for leftover bits if any ANI 3 JZ GETALC INR B GETALC: POP H LXI D,0 ; Init group counter NXBYTE: MVI C,8 ; Bit counter for byte MOV A,M ; Get map byte NXBIT: RAR ; Rotate to C JNC NOBIT ; No group allocated INX D ; Inc group counter NOBIT: DCR C ; Dec bit counter JNZ NXBIT INX H ; Index next byte DCR B JNZ NXBYTE CALL SHF16 PUSH H CALL BINDEC CALL TYPE DB 'K bytes in',' '+EOL ;Print number of files LXI D,FCB ; Fake file cont block MVI C,17 ; Search for 1st file CALL BDOS LXI H,0 ; File counter LOOK: CPI 255 ; Failure JZ PFILE ADD A ; File offset times 2 ADD A ; 4 ADD A ; 8 ADD A ; 16 ADD A ; 32 ADI 80H ; Make sure it's not a deleted file MOV E,A MVI D,0 LDAX D CPI 0E5H JZ LOOK1 INX H ; Bump file counter LOOK1: LXI D,FCB ; Restore FCB MVI C,18 ; Look for addtl files PUSH H ; Save file counter CALL BDOS POP H JMP LOOK PFILE: CALL BINDEC ; Print # of files CALL TYPE DB ' files with',' '+EOL ;Print K remaining LHLD MAXALL ; Get number of blocks XCHG INX D ; Inc for actual value CALL SHF16 XCHG POP H MOV A,H ; Ones comp & move CMA MOV H,A MOV A,L CMA MOV L,A INX H ; Twos complement DAD D ; and subtract CALL BINDEC ; K remaining CALL TYPE DB 'K bytes remaining' DW CRLFE ;Set up to print next drive POP H ; Restore bit counter POP PSW ; and bitmap byte NOTLOG: INR H ; Bump drive counter DCR L ; Dec bit counter JNZ ROTBIT ;MEMORY SURVEY ;Create header MSURV: CALL TYPE DW CRLF DB 'MEMORY MAP:' DW CRLF DB '0',TAB,'8',TAB,'16',TAB,'24',TAB,'32' DB TAB,'40',TAB,'48',TAB,'56',TAB,'64' DW CRLF REPT 8 DB '|',TAB ENDM DB '|' DW CRLF DB 'T'+EOL LXI H,RAM MVI M,LOW 1023 ; Init RAM counter INX H MVI M,HIGH 1023 MVI B,4 ; Clear ROM, EMP CLREG: INX H MVI M,0 DCR B JNZ CLREG LXI H,1024 ; Init memory pointer MVI C,63 ; K to be checked ;Start of analysis loop BEGANA: LXI D,1024 ; Byte counter XRA A ; Clear flag bytes STA RAMF STA EMPF ANALP: MOV A,M ; Get test byte and MOV B,A ; store for later CMA MOV M,A ; Put invertd tst byte SUB M ; Check for good write MOV M,B ; Restore orignl data JNZ NOTMEM ; Wasn't good write INXI RAM ; Bump memory counter JMP NEXT ; To next byte NOTMEM: STA RAMF ; Not considered RAM MVI A,0FFH ; Is it empty space? SUB B JNZ NOTEMP ; Inc ROM, set flag LDA EMPF ; Any non empty space ANA A ; before here? JZ NEXT JMP NOTEM ; To next byte NOTEMP: STA EMPF ; Set no empty flag NOTEM: INXI ROM NEXT: INX H ; Index next byte DCX D ; Decrement K counter XRA A ORA D ORA E JNZ ANALP ; K counter not 0 PUSH B PUSH H LDA RAMF ; Is it RAM? ANA A JNZ NOTRAM ; No LDA BDOS+2 ; Yes, get top of TPA DCR H CMP H ; Compare with pointer JC NOTTPA CALL TYPE ; It's TPA DB 'T'+EOL JMP NEXTK NOTTPA: ADI 20 ; Get base of bios JNC EVALC MVI A,0FFH EVALC: CMP H JC NOTCPM CALL TYPE ; It's CPM DB 'C'+EOL JMP NEXTK NOTCPM: CALL TYPE DB 'M'+EOL ; It's just memory JMP NEXTK NOTRAM: LDA EMPF ; Is it empty? ANA A JZ NOMEM ; Yes, no memory CALL TYPE ; No, must be ROM DB 'R'+EOL JMP NEXTK NOMEM CALL TYPE DB ' '+EOL NEXTK: POP H POP B DCR C ; Decrement K counter JNZ BEGANA CALL TYPE DW CRLF,CRLF DB 'T=TPA',TAB,'C=CPM',TAB,'M=Unassigned Memory' DB TAB,'R=ROM or Bad Memory' DW CRLF,CRLFE ;MEMORY SYNOPSIS LHLD RAM PUSH H ; Save RAM CALL BINDEC ; Type RAM CALL TYPE DB ' Bytes RAM',TAB,TAB+EOL LHLD ROM PUSH H CALL BINDEC ; Type ROM CALL TYPE DB ' Bytes ROM',TAB,TAB+EOL LHLD BDOS+1 CALL BINDEC CALL TYPE DB ' Bytes in TPA' DW CRLFE POP D ; Get RAM POP H ; Get RAM DAD D ; Add 'em PUSH H ; and save result LXI D,0 ; Subtract from this MOV A,H ; Complement 16 bits CMA MOV H,A MOV A,L CMA MOV L,A ; 2s comp bias in D DAD D ; Subtract CALL BINDEC CALL TYPE DB ' Bytes Empty ',TAB+EOL POP H ; Restore RAM+ROM CALL BINDEC CALL TYPE DB ' Total Active Bytes' DW CRLF,CRLF ;PORT SURVEY DB 'ACTIVE I/O PORTS' DW CRLFE LXI H,1000H ; DELAY SO MESSAGE OUTPUT PDLY: DCX H ; DOESN'T GIVE A FALSE READING MOV A,H ; ON CONSOLE STATUS PORT ORA L JNZ PDLY LXI H,0 ; Intit port counter LXI D,TABS ; Init tab & port ctrs PORTLP: MOV A,D IF TARBEL OR IMS400 ; Single port mask CPI SKIPORT JZ ISPORT ; Print mask port ENDIF STA INPORT+1 INPORT: IN 0 ; Modifiable code CPI 0FFH ; Active port? JZ NEXTPT ; No, get next ISPORT: MOV A,D ; Get port # PUSH D PUSH H HEXOUT POP H POP D INX H DCR E ; Dec tab counter JNZ TAB1 MVI E,TABS ; Reset tab counter CALL TYPE DW CRLFE JMP NEXTPT ; Get next port TAB1: CALL TYPE ; Tab out 1 DB TAB+EOL NEXTPT: INR D ; Bump port counter JNZ PORTLP ; Not done CALL TYPE ; Done DW CRLFE CALL BINDEC CALL TYPE ; Type Active Ports DB ' Ports active' DW CRLFE CCP: LHLD OLDSP SPHL RET ;***********************; ; SUBROUTINES ; ;***********************; ;Binary to decimal conversion BINDEC: DECOUT ; From LIB RET ;Types a string of text terminated with bit 7 high TYPE: XTHL ; Get string address PUSH D TYPELP: MOV A,M ; Get type data MOV D,A ; Save for later ANI 7FH ; Mask ASCII MOV E,A PUSH H PUSH D CALL TCHR POP D POP H INX H MVI A,EOL ; End of line bit ANA D JP TYPELP ; Not done POP D XTHL ; Get return address RET ;Types a single character on console TCHR: MVI C,2 JMP BDOS ;Checks sectors per block and multiplies or divides block size ;Enter with data in D. Result returned in H,L SHF16: LDA BLKSHF ; Get shift factor (gives block size) CPI 3 ; Is it 1K (std)? JNZ NOT3 MOV L,E ; Yes, use present # ZH: MVI H,0 RET NOT3: CPI 2 ; Is it minifloppy? JNZ NOT2 MOV A,E ; Yes, divide by 2 RRC ANI 7FH MOV L,A JMP ZH NOT2: SUI 3 ; Must be something MOV B,A ; larger like double XCHG ; sided or double dens BITSHF: DAD H ; 16 bit 2^(B-1) DCR B JNZ BITSHF RET ;***********************; ; DATA STORAGE ; ;***********************; FCB: DB 0,'???????????',0,0,0 ; File control block DS 17 ; Extra FCB workspace OLDSP: DS 2 ; Old stack pointer RAM: DS 2 ; RAM counter ROM: DS 2 ; ROM counter RAMF: DS 1 ; RAM good flag EMPF: DS 1 ; Empty so far flag BLKSHF: DS 1 ; block shift factor MAXALL: DS 2 ; maximum block number FINIS EQU $ ; End of program END