;======================================================================= ; ; MEMORY DISK FORMAT PROGRAM FOR CP/M PLUS 29 Aug 87 ; ---------------------------------------- --------- ; This program is executed from PROFILE.SUB which is itself processed ; on a system reset. ; ; It looks for a particular directory label on the memory drive. If ; one is found then the program assumes the memory drive is formatted ; and terminates with no further action. If one is not found then ; this program formats the memory drive and executes the command tail. ; Typically, the command tail would invoke some utility to copy files ; into the memory drive. ; ; The idea of all this is to automatically format and load the memory ; drive on a power up but to leave it alone on a system reset, thereby ; speeding up the reboot sequence considerably. ; ; This program requires CP/M3 and a Z80 but otherwise it is not ; hardware-dependent. If your BIOS supports a memory drive then you ; can probably use this program. My PROFILE.SUB contains:- ; ; MFORMAT NULU -O MDFILES -E P:*.* -X ; ; Jon Saxton, ; TIE-Line RCPM+ ; Dural, NSW ; AUSTRALIA ; +61 2 651-1404 ; ;======================================================================= ASEG .Z80 ; Keep M80 happy, Z80ASM doesn't care ORG 0100H BDOS EQU 5 BS EQU 8 CR EQU 13 LF EQU 10 PUTSTR EQU 9 CPMVSN EQU 12 SELDSK EQU 14 DIR1ST EQU 17 DIRNXT EQU 18 SETDMA EQU 26 GETDPB EQU 31 CHNPGM EQU 47 FLUSH EQU 48 SGSCB EQU 49 BIOSFN EQU 50 DIRLBL EQU 100 RTNCODE EQU 108 DDMA EQU 80H JR START MEMDRV: DEFB 'P' ; Change 102h to match your RAM-drive START: LD DE,GREET CALL PRINT LD C,CPMVSN ; Ensure we are using CP/M version 3.x CALL BDOS CP 30H JR NC,CPM3 LD DE,NEED3 CALL PRINT RST 0 CPM3: LD DE,DDMA PUSH DE LD C,SETDMA CALL BDOS POP HL ; Save command tail LD C,(HL) LD B,0 INC BC LD DE,COMMAND LDIR LD C,SELDSK ; Select the disk via the BDOS LD A,(MEMDRV) SUB 'A' LD E,A PUSH DE CALL BDOS ; ; The following bit of code is PROBABLY unnecessary since it is highly ; unlikely anyone would implement record skewing on a RAM-disk. However ; since I did not write your BIOS I'm not taking that chance.... ; LD HL,1 ; Select the disk via the BIOS LD (DEREG),HL POP HL LD A,BIOSSEL CALL BIOS ; DPH address returned in HL LD E,(HL) ; Pick up translate table address INC HL LD D,(HL) LD (TTA),DE ; Save it for RECTRAN ; ; Look for a particular directory label. If we find it then we assume ; the disk is already formatted and loaded up with files. ; LD DE,ALLFILES LD C,DIR1ST FILELU: CALL BDOS ; Get a directory entry CP 0FFH ; Finished? JP Z,FORMAT ; Yes but no label so do the format LD HL,DDMA ; Not yet - build directory entry address ADD A,A ADD A,A ADD A,A ADD A,A ADD A,A ; Offset = entry number * 32 ADD A,L LD L,A ;; LD A,0 ; (unnecessary since offset < 256) ;; ADC A,H ;; LD H,A ; HL now points at the directory entry LD DE,LABEL ; Point at target directory label LD B,12 ; Number of bytes to compare CALL STRCMP LD C,DIRNXT JR NZ,FILELU ; Keep looking if no match ; ; We get to here if we found the target directory label ; LD DE,NOFMT CALL PRINT RST 0 ; Exit if directory label found ; ;----------------------------------------------------------------------- ; ; This section of code formats the RAMdisk via the BIOS ; ;----------------------------------------------------------------------- ; PRPT EQU 0 ; Word: logical records per track PBRH EQU 2 ; Byte: block shift factor PBLM EQU 3 ; Byte: block mask PEXM EQU 4 ; Byte: extent mask PDRM EQU 5 ; Word: blocks - 1 POFF EQU 13 ; Word: reserved tracks PPRH EQU 15 ; Byte: physical record shift factor PPHM EQU 16 ; Byte: physical record mask BIOSSEL EQU 9 SETTRK EQU 10 SETREC EQU 11 BSDMA EQU 12 WRITE EQU 14 RECTRN EQU 16 SETBNK EQU 28 TPABANK EQU 1 FORMAT: LD C,GETDPB ; Get disk parameter block address CALL BDOS PUSH HL ; Put it into an index register for easy POP IY ; Reference to DPB fields LD HL,RECBUF ; Initialize the data area LD DE,RECBUF+1 LD BC,2048 ; (Most memory drives use 128-byte records LDIR ; So this is probably more than enough) LD L,(IY+PRPT) ; Calculate number of physical LD H,(IY+PRPT+1) ; records per track LD A,(IY+PPRH) INC A PRHLOOP: DEC A JR Z,PRHEND SRL H RR L JR PRHLOOP PRHEND: ; HL now has physical records per track LD (RPT),HL ; Remember it LD A,(IY+PBRH) ; Calculate physical records per block SUB (IY+PPRH) ; A has a "block/record shift factor" LD L,(IY+PDRM) ; Get number of blocks LD H,(IY+PDRM+1) INC HL LD B,A DRMLOOP: ADD HL,HL ; HL ends up with number of physical DJNZ DRMLOOP ; records on the disk LD (RPD),HL ; (This breaks if memory disk is bigger ; than 8Mb and uses 128-byte records ; but I doubt if that will be a real ; problem.) ; ; Ready to do the formatting .... ; LD HL,0 ; Track = record = 0 LD (TRACK),HL LD (RECORD),HL LD DE,FMSG ; Printf("Formatting pseudo-track 0000"); CALL PRINT FMTLOOP: LD HL,(RPD) ; For (; rpd--;) LD A,H ; { OR L JR Z,FMTEXIT DEC HL LD (RPD),HL LD HL,(TRACK) ; SETRK(track); LD A,SETTRK CALL BIOS LD HL,(RECORD) ; SETREC(RECTRN(record)); LD DE,(TTA) LD (DEREG),DE LD A,RECTRN CALL BIOS LD A,SETREC CALL BIOS LD DE,RECBUF ; SEDDMA(&RECBUF[0]); PUSH DE LD C,SETDMA CALL BDOS POP HL ; /* Must do it via BIOS as well! */ LD A,BSDMA CALL BIOS ;; LD A,TPABANK ; SETBNK(TPABANK); ;; LD (AREG),A ; /* BIOS "set DMA" function selects ;; LD A,SETBNK ; The TPA bank automatically */ ;; CALL BIOS LD A,WRITE ; If (rslt=WRITE()) LD HL,1 CALL BIOS OR A ; Printf("Write error ... Code=%02x\n", CALL NZ,FMTERR ; rslt); LD HL,(RECORD) ; If (++record == RPT) INC HL LD (RECORD),HL EX DE,HL LD HL,(RPT) OR A SBC HL,DE JR NZ,FMTLOOP ; { LD HL,0 ; Record = 0; LD (RECORD),HL LD DE,BACKSP ; Printf("\b\b\b\b%04x", ++track); CALL PRINT LD HL,(TRACK) INC HL LD (TRACK),HL CALL HEX16 ; } JR FMTLOOP ; } FMTEXIT: LD C,FLUSH ; Flush all disk buffers LD E,0 ; (probably not necessary) CALL BDOS LD DE,FMTDONE ; Say we've finished formatting CALL PRINT LD DE,LABEL ; Set the directory label LD A,(MEMDRV) SUB '@' LD (DE),A XOR A LD (LABEL+12),A LD C,DIRLBL CALL BDOS INC A ; Check for error (format must have failed!) JR NZ,EXECCMD LD DE,FMTFAIL ; Let human know we couldn't set the directory CALL PRINT ; Label and exit without doing anything further RST 0 EXECCMD: LD DE,LBLDONE ; Say we've set the directory label CALL PRINT LD DE,DDMA ; Reload the command tail into LD HL,COMMAND ; the default DMA buffer at 80h LD C,(HL) ; and ensure it is terminated LD B,0 ; with a zero byte, then chain INC HL ; to the command. LDIR XOR A LD (DE),A LD C,CHNPGM CALL BDOS ; Should never return, but .... RST 0 PCHL: JP (HL) ; ; Invokes the BIOS via BDOS(50). Expects function number in A and ; principal parameter in HL. Any secondary parameters must have been ; pre-loaded into the BIOS parameter block. ; BIOS: LD (BCREG),HL LD DE,BIOSPB LD (DE),A LD C,BIOSFN CALL BDOS RET ; ; Compares two strings and sets Z flag if they are equal. HL and DE ; point at the strings, B holds the (maximum) number of bytes to compare. ; STRCMP: LD A,(DE) CP (HL) RET NZ INC HL INC DE DJNZ STRCMP RET ; ; Reports an error if the BIOS returns one while writing to the memory ; drive. ; FMTERR: PUSH AF LD DE,ERRMSG CALL PRINT POP AF CALL HEX8 LD DE,CRLF CALL PRINT RET ; ; Hexadecimal display routines ; HEX16: PUSH HL LD A,H CALL HEX8 POP HL LD A,L HEX8: PUSH AF RRA RRA RRA RRA CALL HEX4 POP AF HEX4: AND 15 ADD A,90H DAA ADC A,40H DAA LD E,A LD C,2 CALL BDOS RET ; ; Display a string on the console. Uses the normal BDOS function. ; PRINT: LD C,PUTSTR CALL BDOS RET ; ;----------------------------------------------------------------------- ; ; Data ; ;----------------------------------------------------------------------- ; GREET: DEFB 'RAM-disk format program by Jonathan Saxton',CR,LF DEFB 'TIE-Line RCPM+, AUSTRALIA. 29 August 1987',CR,LF DEFB CR,LF,'$' FMTFAIL: DEFB 'Error in setting directory label. Probably indicates a',CR,LF DEFB 'problem during the formatting phase which may not have',CR,LF DEFB 'shown up as a write error. Program terminated.$' NOFMT: DEFB 'RAM-disk is already formatted$' NEED3: DEFB 'This program only runs under CP/M version 3.x$' FMSG: DEFB 'Formatting pseudo-track 0000$' BACKSP: DEFB BS,BS,BS,BS,'$' ERRMSG: DEFB 'Write error during format. Code=$' CRLF: DEFB CR,LF,'$' FMTDONE: DEFB CR,LF,'RAM-disk formatted',CR,LF,'$' LBLDONE: DEFB 'Directory label set',CR,LF,LF,'$' RPT: DEFS 2 ; (Physical) records per track RPD: DEFS 2 ; (Physical) records per disk TRACK: DEFS 2 ; Current track number RECORD: DEFS 2 ; Current record number TTA: DEFS 2 ; Translate table address (probably zero) LABEL: DEFB 20H,'RAMDISK JRS' ; Directory label FCB DEFW 0,0,0,0,0,0,0,0,0,0,0,0 ALLFILES: DEFB '????????????' ; FCB to match all files DEFW 0,0,0,0,0,0,0,0,0,0,0,0 BIOSPB: ; BIOS parameter block DEFS 1 ; Function number AREG: DEFS 1 ; A register BCREG: DEFS 2 ; BC register DEREG: DEFS 2 ; DE register DEFS 2 ; HL register COMMAND: DEFS 256 ; Storage for command tail RECBUF: DEFB 0E5H ; Format pattern END START