; NEW BIOS BOOT MAINTENENCE PROGRAM ; ;PURPOSE ; THIS PROGRAM PROVIDES THE MEANS TO SYSGEN A NEW ; BIOS CP/M SYSTEM. IT WRITES THE BOOT, BDOS AND BIOS TO ; THE SYSTEM TRACKS OF DISK B. IT CAN BE USED FOR MULTIPLE ; GENERATIONS WITH AN OPTIONAL SYSTEM OBTAINED FROM DRIVE ; A. ;DATE WRITTEN ; MAY 23, 1980 WITH THE HELP OF S.J. SINGER'S PGEN PROGRAM ;OUTLINE ; TO GENERATE A NEW SYSTEM, DO THE FOLLOWING: ; DDT CPMXX.COM (XX = MEMORY SIZE) ; -M1180,1F80,980 ; -I21BIOS.HEX ; -H1780,NNNN (NNNN = START OF BIOS, ; SEE ASSEMBLY LISTING.) ; XXXX YYYY ; -RYYYY (LOADS BIOS) ; -^C ; NPGEN ; GET SYSTEM (Y/N)? N ; PUT SYSTEM (Y/N)? Y ; ETC. ; TOGENERATE FROM AN OLD SYSTEM, JUST RUN NPGEN TELLING ; IT TO GET THE SYSTEM FROM DRIVE A. ; ; MACLIB MACRO ;INCLUDE MACROS FALSE EQU 00H TRUE EQU NOT FALSE ; SPOOL EQU FALSE ;TRUE FOR KLH SPOOLER ; ; MSIZE EQU 61 ;MEMORY SIZE IN KBYTES CBASE EQU (MSIZE-20)*1024 CPMB EQU CBASE+3400H ;START OF CP/M BDOS EQU CPMB+0800H ;START OF BDOS (ROUNDED TO ; EVEN SECTOR BOUNDARY) BIOS EQU CPMB+1600H ;START OF BIOS IF SPOOL JMPDSP EQU 033H+9 ;DISPLACEMENT TO SPECIAL BIOS JUMPS ENDIF IF NOT SPOOL JMPDSP EQU 033H ;DISPLACEMENT TO SPECIAL BIOS JUMPS ENDIF TPA EQU 100H RDCON EQU 1 WRBUF EQU 9 START EQU 900H FBYTE EQU 97FH ;DISK FORMAT BYTE LOCATION ; ; ; ORG TPA ; ; LXI H,0 ;ZERO HL DAD SP ;GET OLD STACK POINTER SHLD OLDSTK ;AND SAVE IT LHLD 1 SHLD SAVADR LXI SP,STACK MAIN: PRINT PRINT CALL GET$BOOTER CALL PUT$BOOTER JMP REBOOT ; ; SELDSK: ;SELECT DISK PUSH H LHLD 1 MVI L,00H+JMPDSP XTHL RET ; ; HOME: ;HOME DISK PUSH H LHLD 1 MVI L,03H+JMPDSP XTHL RET ; ; SEEK: ;SEEK TRACK PUSH H LHLD 1 MVI L,06H+JMPDSP XTHL RET ; ; READ: ;READ A SECTOR PUSH H LHLD 1 MVI L,09H+JMPDSP XTHL RET ; WRITE: ;WRITE A SECTOR PUSH H LHLD 1 MVI L,0CH+JMPDSP XTHL RET ; ; GET$BOOTER: ;MAYBE A BOOTER COMES IN PRINT CHARIN CPI 'Y' RNZ ;RETURN IF NOT YES PRINT CHARIN CPI 3 ;IS IT CONTROL C JZ MAIN MVI A,0FFH STA RDFLG ;SET FLAG CALL DO$READ RET ;DONE ; ; PUT$BOOTER: ;DOES THE BOOTER GO OUT? PRINT CHARIN CPI 3 ;CONTROL C JZ MAIN CPI 'Y' RNZ ;EXIT IF NO PUT$AGAIN: ;ELSE START TO PUT PRINT CHARIN CPI 3 ;CHECK FOR CONTROL C JZ MAIN CALL READ$FMT ;READ T 0 S 1 FROM DESTINATION DISK CALL MOVE$BOOT PRINT CALL WRITE$FMT LDA FMFLG ;CHECK IF KNOWN FORMAT ORA A CNZ GET$FORMAT ; *** TEMPORARY *** LDA FBYTE ;MUST BE SINGLE DENSITY CPI 020H ;128-BYTE SECTORS. JNZ FMT$ERR ; *** END OF TEMPORARY *** CALL DO$WRITE ;NOW PUT IT OUT PRINT CHARIN CPI 'Y' JZ PUT$AGAIN ;WRITE IT AGAIN RET ;ALL DONE ; *** TEMPORARY *** FMT$ERR: PRINT RET ; *** TEMPORARY *** ; ; REBOOT: ;PULL BACK CP/M PRINT CHARIN MVI C,0 CALL SELDSK ;SELECT DRIVE 0 LHLD SAVADR SHLD 1 LHLD OLDSTK ;RECOVER ORIGINAL STACK POINTER SPHL ;RESTORE IT JMP 0 ;************************************************ ;* READ IN ALL SYSTEM TRACKS ASSUMING * ;* SD 128-BYTE SECTORS FOR ALL. * ;************************************************ DO$READ: ;READ IN THE BOOTER MVI C,0 ;SELECT DISK CALL SELDSK CALL TIME CALL HOME ;MAKE SURE IT'S INITIALIZED LXI B,1 ;B=TRK C=SECTOR LXI H,START ;START OF AREA. DR$LOOP: ;THEN PUT IT OUT PUSH B PUSH H PUSH B MOV C,B ;SEEK TRACK. CALL SEEK POP B POP H ;RESTORE BUFFER PTR. PUSH H CALL READ ;READ A SECTOR. POP H POP B LXI D,128 ;BUMP BUFFER PTR. DAD D INR C ;BUMP SECTOR PTR. MOV A,C ;END OF TRACK? CPI 26+1 JC DR$LOOP ;...NO. MVI C,1 ;RESET SECTOR. INR B ;BUMP TRACK PTR. MOV A,B ;END OF SYSTEM TRACKS? CPI 1+1 JC DR$LOOP ;...NO. RET ;************************************************ ;* WRITE OUT ALL SYSTEM TRACKS ASSUMING * ;* SD 128-BYTE SECTORS FOR ALL. * ;************************************************ DO$WRITE: ;READ IN THE BOOTER MVI C,1 ;SELECT DISK CALL SELDSK CALL TIME CALL HOME ;MAKE SURE IT'S INITIALIZED LXI B,1 ;B=TRK C=SECTOR LXI H,START ;START OF AREA. DW$LOOP: ;THEN PUT IT OUT PUSH B PUSH H PUSH B MOV C,B ;SEEK TRACK. CALL SEEK POP B POP H ;RESTORE BUFFER PTR. PUSH H CALL WRITE ;READ A SECTOR. POP H POP B LXI D,128 ;BUMP BUFFER PTR. DAD D INR C ;BUMP SECTOR PTR. MOV A,C ;END OF TRACK? CPI 26+1 JC DW$LOOP ;...NO. MVI C,1 ;RESET SECTOR. INR B ;BUMP TRACK PTR. MOV A,B ;END OF SYSTEM TRACKS? CPI 1+1 JC DW$LOOP ;...NO. RET ; ; MOVE$BOOT: ;MOVE BOOT CODE TO 900H LXI H,900H ;POINT TO MEMORY LXI D,BOOT ;POINT TO BOOT CODE MVI C,ENDBOOT-BOOT ;LENGTH OF CODE MLOOP: LDAX D ;GET A BYTE MOV M,A ;STORE IT INX H INX D ;INCR POINTERS DCR C ;BYTE COUNT JNZ MLOOP MVI A,0C7H ;RESTART ZERO INSTRUCTION STA 97DH ;PUT IT IN BUFFER TOO RET ; GET$FORMAT: ;READ DISK FORMAT FROM CONSOLE AND SET FBYTE PRINT CHARIN CPI 'Y' RNZ GF1: PRINT CHARIN CPI 'Y' MVI A,20H ;SINGLE DENSITY CODE JZ GF2 MVI A,10H ;DOUBLE DENSITY CODE GF2: STA FBYTE ;SAVE IN FBYTE PRINT CHARIN CPI 'Y' MVI B,0 ;128 BYTE CODE JZ GFE PRINT CHARIN CPI 'Y' MVI B,1 ;256 BYTE CODE JZ GFE PRINT CHARIN CPI 'Y' MVI B,2 ;512 BYTE CODE JZ GFE PRINT CHARIN CPI 'Y' MVI B,3 ;1024 BYTE CODE JZ GFE PRINT MVI B,0 GFE: LDA FBYTE ORA B ;OR IN THE BYTE CODE STA FBYTE RET ; READ$FMT: ;READ FORMAT CODE FROM DESTINATION DISK MVI C,1 ;SELECT THE DISK CALL SELDSK CALL TIME CALL HOME CALL TIME LXI H,START MVI C,1 CALL READ ;READ DRIVE B TRACK 0 SECTOR 1 RET ; WRITE$FMT: ;DECODE FORMAT BYTE AND DISPLAY MVI A,0FFH STA FMFLG ;SET FLAG TO KNOWN FORMAT LDA FBYTE CPI 20H JNZ WF2 PRINT <'SINGLE DENSITY 128 BYTE SECTORS',CR,LF> RET WF2: CPI 22H JNZ WF3 PRINT <'SINGLE DENSITY 512 BYTE SECTORS',CR,LF> RET WF3: CPI 23H JNZ WF4 PRINT <'SINGLE DENSITY 1024 BYTE SECTORS',CR,LF> RET WF4: CPI 10H JNZ WF5 PRINT <'DOUBLE DENSITY 128 BYTE SECTORS',CR,LF> RET WF5: CPI 11H JNZ WF6 PRINT <'DOUBLE DENSITY 256 BYTE SECTORS',CR,LF> RET WF6: CPI 12H JNZ WF7 PRINT <'DOUBLE DENSITY 512 BYTE SECTORS',CR,LF> RET WF7: CPI 13H JNZ WF8 PRINT <'DOUBLE DENSITY 1024 BYTE SECTORS',CR,LF> RET WF8: PRINT <'NO FORMAT CODE ON DISK',CR,LF> XRA A STA FMFLG ;SET FLAG FOR NO FORMAT RET ; TIME: LXI B,3000H ;TIMING DELAY DELAY: DCX B MOV A,B ORA C JNZ DELAY RET ; OLDSTK: DW 0 ;STORAGE FOR OLD STACK POINTER SAVADR: DW 0 RDFLG DB 0 ;INDICATES BOOTER READ FROM DISK FMFLG DB 0 ;INDICATES FORMAT FLAG ON DEST DISK ; ; ; ; BDOS/BIOS BOOT LOADER ; ;THIS IS A MODIFICATION OF TARBELL'S BOOT LOADER DESIGNED TO RUN AT 0H ;THE CODE IS MOVED TO 900H BY PGEN WITH THE PROPER FORMAT CODE IN THE ;LAST BYTE FOR WRITING ON THE SYSTEM TRACK OF A PASCAL DISK. ;THE PROGRAM LOADS 51 SECTORS FROM DISK WHEN EXECUTED STARTING WITH ;TRACK 0 SECTOR 2. ; ; DISK EQU 0F8H ;BASE ADDR FOR DISK I/O PORTS DCOM EQU DISK DSTAT EQU DISK TRACK EQU DISK+1 SECT EQU DISK+2 DDATA EQU DISK+3 WAIT EQU DISK+4 NS EQU 51 ;NUMBER OF SECTORS TO LOAD ; OFFSET EQU 00H ;BOOT OFFSET ; ; ; BOOT: MVI E,10 BLOOP: LXI SP,100H MVI D,NS ;D CONTAINS SECTOR COUNT LXI H,BDOS ;STARTING LOAD ADDR FOR PROGRAM MVI C,2 ;SECTOR NUMBER. RNTRK: MVI B,4 ;FOR HEAD LOAD. RNSEC: CALL BREAD-BOOT+OFFSET ;READ A SECTOR. DCR D ;IF DONE. JZ BIOS ;GO TO CP/M. MVI B,0 ;FOR NO HEAD LOAD. INR C ;INCR TRACK COUNT. MOV A,C ;DONE WITH CPI 26+1 ;THIS TRACK? JC RNSEC-BOOT+OFFSET ;...NO. MVI A,053H ;ISSUE STEP COMMAND. OUT DCOM IN WAIT ;WAIT UNTIL DONE. MVI C,1 ;RESET SECTOR NUMBER. JMP RNTRK-BOOT+OFFSET ; BREAD: MOV A,C ;SET SECTOR. OUT SECT MVI A,088H ;GET READ CMD. ORA B ;GET HEAD LOAD BIT. OUT DCOM ;ISSUE IT. RLOOP: IN WAIT ;WAIT FOR DRQ ORA A JP CHECK-BOOT+OFFSET ;JUMP IF DONE IN DDATA MOV M,A INX H JMP RLOOP-BOOT+OFFSET ; CHECK: IN DSTAT ;READ STATUS. ANI 09DH RZ DCR E JNZ BLOOP-BOOT+OFFSET STA EC-BOOT+OFFSET HERE: JMP HERE-BOOT+OFFSET ; EC: DS 1 ENDBOOT: DS 128 ;LOTS OF SPACE FOR STACK STACK: EQU $ END