home *** CD-ROM | disk | FTP | other *** search
- TITLE 'SDNSGEN V4.0 - WRITE CP/M 2.2 TO N* SD DISK'
- ;
- ; THIS PROGRAM IS SET UP TO PROVIDE THE FUNCTIONS
- ; OF THE DIGITAL RESEARCH STANDARD CP/M PROGRAM
- ; 'SYSGEN', BUT FOR A NORTH STAR SINGLE DENSITY
- ; VERSION OF CP/M. SINCE THE NORTH STAR HAS 10
- ; SECTORS PER TRACK, WITH 256 BYTES PER SECTOR
- ; USING SINGLE DENSITY, THE STANDARD SYSGEN PROGRAM
- ; IS WORTHLESS. USING THIS VERSION, THE CCP
- ; IS WRITTEN OUT TO TRACK 1, SECTORS 0-7. BDOS
- ; REQUIRES 14 SINGLE DENSITY SECTORS. IT IS WRITTEN
- ; TO TRACK 1, SECTORS 8-9, THEN TO ALL OF TRACK 2
- ; (SECTORS 0-9). TRACK 0 SECTOR 1 AND TRACK 0
- ; SECTOR 9 ARE USED TO HOLD THE REST OF BDOS.
- ; THE SINGLE DENSITY BIOS REQUIRES FOUR SECTORS
- ; FOR THE DISK I/O PORTION (SDNBIOS) AND TWO
- ; SECTORS FOR THE CONSOLE AND LIST FUNCTIONS (USER).
- ; SDNBIOS IS WRITTEN OUT TO TRACK 0, SECTORS 5-8.
- ; USER IS WRITTEN OUT TO TRACK 0, SECTORS 2-3.
- ; THE BOOTSTRAP ROUTINE OCCUPIES THE SINGLE SECTOR
- ; ON TRACK 0, SECTOR 4. TRACK 0, SECTOR 0 IS
- ; RESERVED FOR A LIFEBOAT- COMPATIBLE ID AND
- ; FUTURE ADDITIONS.
- ;
- ; THE CCP/BDOS CODE IS ASSUMED TO BE LOADED INTO
- ; CONTIGUOUS MEMORY LOCATIONS STARTING AT 0980H.
- ; THE USER ROUTINES ARE LOADED AT 1F80H. THE DISK
- ; I/O PART OF BIOS IS ASSUMED TO RESIDE IN MEMORY
- ; FROM 2180H TO 247FH INCLUSIVE. THE BOOTSTRAP
- ; BLOCK IS LOADED AT 880H.
- ;
- ; IN ORDER TO FIND THE RIGHT SECTORS, WE ASSUME
- ; THAT THERE ARE 20 LOGICAL SECTORS PER TRACK,
- ; NUMBERED 1-20 INCLUSIVE. IN ORDER TO WRITE AT
- ; HIGH SPEED, WE ASSUME THAT THERE ARE 2 LOGICAL
- ; SECTORS PER PHYSICAL SECTOR, AND LOAD THE C-REG
- ; WITH THE APPROPRIATE DEBLOCKING FLAG BEFORE
- ; CALLING BIOS TO WRITE A SECTOR. IN ADDITION,
- ; WE READ OR WRITE EVERY 3RD NORTH STAR SECTOR.
- ;
- ORG 0100H ;ORG TO TPA
- ;
- ; BDOS EQUATES
- ;
- BDOS EQU 0005H ;BDOS ENTRY ADDRESS
- CONIN EQU 1 ;CONSOLE INPUT
- CONOUT EQU 2 ;CONSOLE OUTPUT
- ;
- CR EQU 0DH ;ASCII CR
- LF EQU 0AH ;ASCII LF
- ;
- ; BIOS OFFSET EQUATES
- ;
- WARMB EQU 0000H ;BIOS WARM BOOT VECTOR
- BIOS EQU WARMB+1 ;PTR TO BIOS VECTOR TABLE
- ;
- SELDSK EQU 1BH-3 ;SELECT DISK DRIVE
- SETTRK EQU SELDSK+3 ;SET TRACK NUMBER
- SETSEC EQU SETTRK+3 ;SET SECTOR NUMBER
- SETDMA EQU SETSEC+3 ;SET DMA ADDRESS
- READ EQU SETDMA+3 ;READ SELECTED SECTOR
- WRITE EQU READ+3 ;WRITE SELECTED SECTOR
- ;
- NDRVS EQU 2 ;# OF DRIVES WE CAN USE
- ;(ONLY A: AND B: ARE N*)
- ;
- ; CP/M IMAGE ADDRESS
- ;
- CPMIA EQU 0880H
- ;
- ; PROGRAM START. SET UP STACK PTR AND GET SOURCE DISK.
- ;
- SDNSGEN: LXI SP,SDNSGEN ;SET STACK PTR
- LXI H,HELLO ;PRINT OUT SIGNON
- CALL MSGOT
- ;
- GETSRC: LXI H,SRCMSG ;ASK FOR SOURCE DISK LETTER
- CALL MSGOT
- CALL CHARIN ;GET SINGLE CHAR FOLDED
- CPI CR ;IS ANSWER <RET>?
- JZ GETDST ;SKIP SOURCE GET IF SO
- STA SRCLET ;SAVE LETTER IF NOT
- SUI 'A' ;MAP TO BINARY VALUE FROM 0
- CPI NDRVS ;MAKE SURE NOT TOO BIG
- JC SRCOK ;PASS IF OK
- LXI H,BADNAM ;FLAG ERROR IF NOT
- CALL MSGOT
- JMP GETSRC ; AND TRY AGAIN
- ;
- SRCOK: CALL BSEL ;CALL BIOS TO SELECT DISK
- LXI H,SRCON ;PROMPT FOR SOURCE DISK
- CALL MSGOT
- CALL CHARIN ;WAIT FOR <RET>
- CPI CR
- JNZ REBOOT ;REBOOT IF ANYTHING ELSE TYPED
- ;
- ; READ THE SYSTEM FROM THE SPECIFIED DRIVE
- ;
- XRA A ;IF OK, FLAG DISK READ OPS
- STA DFLAG
- CALL XFRSYS ;READ SYSTEM INTO MEMORY
- JNZ GETSRC ;IF ABORTED, TRY AGAIN
- LXI H,FNCDUN ;FUNCTION DONE
- CALL MSGOT
- ;
- ; GET THE DESTINATION DISK
- ;
- GETDST: LXI H,DSTMSG ;GET DESTINATION NAME
- CALL MSGOT
- CALL CHARIN
- CPI CR ;SEE IF DONE
- JZ REBOOT ;GET OUT IF SO
- STA DSTLET ;IF NOT, SAVE DEST LETTER
- SUI 'A' ;MAKE SURE IN RANGE
- CPI NDRVS
- JC DSTOK ;PASS IF SO
- LXI H,BADNAM ;FLAG BAD NAME IF NOT
- CALL MSGOT
- JMP GETDST ; THEN ASK AGAIN
- ;
- DSTOK: CALL BSEL ;CALL BIOS TO SELECT DISK
- LXI H,DSTON ;PROMPT FOR SOURCE DISK
- CALL MSGOT
- CALL CHARIN ;WAIT FOR <RET>
- CPI CR
- JNZ REBOOT ;REBOOT IF ANYTHING ELSE TYPED
- ;
- ; WRITE TO THE DESTINATION DISK
- ;
- MVI A,1 ;FLAG DISK WRITE
- STA DFLAG
- CALL XFRSYS ;WRITE OUT SYSTEM
- JNZ GETDST ;NO MSG IF ABORTED
- LXI H,FNCDUN ;INDICATE DONE
- CALL MSGOT
- JMP GETDST ;ASK ABOUT WRITING AGAIN
- ;
- ; HERE WHEN DONE TO SELECT DRIVE A AND REBOOT
- ;
- REBOOT: XRA A ;SELECT DRIVE A
- CALL BSEL
- JMP WARMB ; THEN REBOOT CP/M
- ;
- ; SUBROUTINE XFRSYS TRANSFERS THE SYSTEM IMAGE FROM
- ; OR TO THE SELECTED DISK, BASED ON THE CONTENTS OF
- ; 'DFLAG'. IF 'DFLAG' CONTAINS ZERO, THE SYSTEM IS
- ; READ IN. IF 'DFLAG' CONTAINS ONE, THE SYSTEM IS
- ; WRITTEN OUT. BIOS DISK READ AND WRITE ARE CALLED
- ; DIRECTLY TO DO I/O. IF AN ERROR IS RETURNED FROM
- ; BIOS, IT IS REPORTED TO THE OPERATOR, WHO IS GIVEN
- ; THE OPTION OF IGNORING THE ERROR, OR ABORTING THE
- ; XFER. IF THE XFER WAS ABORTED, WE RETURN NON-ZERO
- ; IN ACC. BECAUSE THE HOST BUFFER CONTENTS ARE
- ; SCRAPPED ON I/O ERROR, WE CANNOT RETRY THE I/O.
- ; BESIDES, THE BIOS HAS ALREADY RETRIED IT FOR US.
- ;
- XFRSYS: MVI A,MAXSEC ;GET # OF CP/M SECTORS TO XFER
- STA SCOUNT ; AND SET COUNT TO DO
- LXI H,SECTBL ;PT TO SECTOR TABLE
- SHLD SECPTR ;INIT THE SECTOR ADDRESS PTR
- ;
- ; GET NEXT SECTOR ADDRESS FROM TABLE, AND SET BIOS PTRS
- ;
- NXTSEC: LHLD SECPTR ;GET NEXT SECTOR ADDRESS
- MOV A,M ; INTO ACC
- RLC ;BRING TRACK BITS INTO POSITION
- RLC
- ANI 3 ;TRACK IS ZERO, ONE, OR TWO
- MOV C,A ;PUT TRK # IN C FOR BIOS
- CALL BTRK ;CALL BIOS TO SET TRACK #
- LHLD SECPTR ;GET SECTOR ADDRESS AGAIN
- MOV A,M
- ANI 3FH ;STRIP TRACK BITS
- MOV C,A ;GET INTO CORRECT REG
- INX H ;BOP SECTOR TABLE PTR
- SHLD SECPTR ; AND UPDATE
- CALL BSEC ;CALL BIOS TO SET SECTOR #
- LHLD SECPTR ;GET TABLE PTR AGAIN
- MOV A,M ;GET LOGICAL SECTOR #
- RRC ;CALC MEM OFFSET HIGH BYTE
- ANI 7FH
- MOV B,A ;PUT FINAL VALUE IN BC
- MOV A,M ;NOW CALC LOW BYTE
- RRC
- ANI 80H
- MOV C,A
- INX H ;BOP PTR AGAIN
- SHLD SECPTR
- LXI H,CPMIA ;CALC MEM ADDR
- DAD B
- MOV B,H ;NEED IT IN BC
- MOV C,L
- CALL BDMA ;CALL BIOS TO SET DMA ADDR
- ;
- ; TIME TO DO THE SECTOR READ OR WRITE. CHECK DFLAG TO DECIDE.
- ;
- DOIO: LDA DFLAG ;ARE WE READING OR WRITING?
- ORA A ;IF ZERO, READING
- JNZ WRTSEC ;BRANCH IF WRITING
- CALL BREAD ;IF READING, CALL BIOS TO DO IT
- JMP CHKSEC ;NOW GO CHECK FOR ERRORS
- ;
- WRTSEC: CALL BWRITE ;CALL BIOS TO WRITE SECTOR
- ;
- CHKSEC: ORA A ;ERROR IF BIOS RETURNS NON-ZERO
- JZ XFROK ;PASS IF I/O OK
- ;
- ; I/O ERROR. ASK OPERATOR FOR A RULING.
- ;
- IOERR: LXI H,IOEMSG ;REPORT ERROR, AND ASK
- CALL MSGOT ; WHAT ACTION TO TAKE
- CALL CHARIN ;GET REPLY
- CPI 'I' ;IGNORE THE ERROR?
- JZ XFROK ;GO ON IF SO
- SUI 'A' ;ABORT THE XFER?
- JNZ IOERR ;ASK AGAIN IF NEITHER OF THE ABOVE
- INR A ;IF ABORT,
- RET ; RETURN NON-ZERO TO CALLER
- ;
- ; COUNT OFF LAST SECTOR TO SEE IF DONE
- ;
- XFROK: LDA SCOUNT
- DCR A ;COUNT OFF LAST SECTOR
- STA SCOUNT
- JNZ NXTSEC ;IF MORE TO DO, GO BACK
- RET ; ELSE RET ZERO TO CALLER
- ;
- ;
- ; BIOS I/O ROUTINES -- DISK SELECT
- ;
- BSEL: MOV C,A ;MOVE DISK # TO BIOS REG
- LXI D,SELDSK ;SELECT DISK
- JMP GOBIOS
- ;
- ; -- SET TRACK
- ;
- BTRK: LXI D,SETTRK ;SET TRACK C
- JMP GOBIOS
- ;
- ; -- SET SECTOR
- ;
- BSEC: LXI D,SETSEC ;SET SECTOR C
- JMP GOBIOS
- ;
- ; -- SET DMA ADDRESS
- ;
- BDMA: LXI D,SETDMA ;SET DMA ADDR BC
- JMP GOBIOS
- ;
- ; -- READ SECTOR
- ;
- BREAD: LXI D,READ ;READ SETUP SECTOR
- JMP GOBIOS
- ;
- ; -- WRITE SECTOR
- ;
- BWRITE: LXI D,WRITE ;WRITE SETUP SECTOR
- ;
- ; SINCE WE KNOW THAT THE NORTH STAR I/O IS BEING
- ; DEBLOCKED, LOAD C-REG WITH A VALUE OF 2 TO PREVENT
- ; PRE-READ FOR EVERY SECTOR BUT THE LAST ONE. FOR THAT
- ; SECTOR, LOAD C-REG WITH A VALUE OF 1 TO FORCE A WRITE
- ; TO FLUSH THE BIOS DEBLOCKING BUFFER BEFORE WE LEAVE,
- ; OR A REBOOT MAY LOSE THE LAST PHYSICAL SECTOR WE
- ; WANTED TO WRITE OUT.
- ;
- MVI C,2 ;WRITE TO UNALLOCATED
- LDA SCOUNT ;CHECK FOR WRITING TO
- DCR A ; LAST SECTOR
- JNZ GOBIOS ;JUMP IF NOT
- DCR C ;FORCE WRITE IF LAST
- ;
- ; XFER TO BIOS VIA VECTOR WHOSE OFFSET IS IN DE
- ;
- GOBIOS: LHLD BIOS ;PT TO BIOS WARM BOOT VECTOR
- DAD D ;CALC DESIRED VECTOR ADDR
- PCHL ;GO THERE
- ;
- ;
- ; OUTPUT MESSAGE PT'ED AT BY HL TO CONSOLE. MESSAGE
- ; IS A STRING OF CHARACTERS TERMINATED BY A ZERO BYTE.
- ;
- MSGOT: MOV A,M ;GET NEXT BYTE
- ORA A
- RZ ;IF NULL, DONE
- PUSH H ;IF NOT, SAVE PTR
- MOV E,A ;CHAR TO BDOS REG
- MVI C,CONOUT ;FUNCTION
- CALL BDOS ;GO OUTPUT CHAR
- POP H ;RESTORE PTR
- INX H ;PT TO NEXT BYTE
- JMP MSGOT ;GO BACK FOR MORE
- ;
- ; CONSOLE INPUT CHAR FUNCTION. LOWER CASE IS FOLDED
- ; TO UPPER ON RETURN.
- ;
- CHARIN: MVI C,CONIN ;CONSOLE INPUT FUNCTION
- CALL BDOS ;GET CHAR FROM CONSOLE
- CPI 'A'+20H ;FOLD LOWER CASE
- RC
- CPI 'Z'+20H+1
- RNC
- SUI 20H
- RET
- ;
- ; MESSAGES
- ;
- HELLO: DB 'SDNSGEN V4.0',0
- SRCMSG: DB CR,LF,'Enter source drive name (A-','A'+NDRVS-1
- DB ') or <ret> to skip: ',0
- DSTMSG: DB CR,LF,'Enter destination drive name (A-'
- DB 'A'+NDRVS-1,') or <ret> to reboot: ',0
- BADNAM: DB CR,LF,'Invalid drive name.',0
- SRCON: DB CR,LF,'Source on '
- SRCLET: DB ' :, then type <ret>: ',0
- DSTON: DB CR,LF,'Destination on '
- DSTLET: DB ' :, then type <ret>: ',0
- FNCDUN: DB CR,LF,'Function complete.',0
- IOEMSG: DB CR,LF,'Disk I/O error. Type "I" to ignore or'
- DB ' "A" to abort transfer: ',0
- ;
- ; SECTOR ADDRESS TABLE. EACH ENTRY CONSISTS
- ; OF TWO BYTES. THE FIRST BYTE REPRESENTS THE
- ; SECTOR'S DISK LOCATION. THE TRACK NUMBER IS
- ; REPRESENTED BY THE HIGH TWO BITS, NUMBERED
- ; 00, 01, OR 10. LOW SIX BITS REPRESENT SECTOR
- ; NUMBER WITHIN TRACK. THE SECOND BYTE OF THE
- ; ENTRY IS THE LOGICAL SECTOR OFFSET FROM THE
- ; START OF THE CP/M IMAGE IN MEMORY, WHICH IS
- ; USED TO CALCULATE THE ACTUAL MEMORY ADDRESS
- ; OF THAT SECTOR SO THAT I/O CAN BE DONE.
- ;
- ; MAXSEC REPRESENTS THE TOTAL NUMBER OF
- ; SECTORS IN THE TABLE. REASSEMBLE TO CHANGE
- ; THE NUMBER OF SECTORS INVOLVED IN A TRANSFER.
- ;
- SECTBL: ;SECTOR TABLE
- ;
- ; NORTH STAR TRK, SEC
- ;
- DB 01+80H,22,02+80H,23 ; 2,0
- DB 07+80H,28,08+80H,29 ; 2,3
- DB 13+80H,34,14+80H,35 ; 2,6
- DB 19+80H,40,20+80H,41 ; 2,9
- DB 05+80H,26,06+80H,27 ; 2,2
- DB 11+80H,32,12+80H,33 ; 2,5
- DB 17+80H,38,18+80H,39 ; 2,8
- DB 03+80H,24,04+80H,25 ; 2,1
- DB 09+80H,30,10+80H,31 ; 2,4
- DB 15+80H,36,16+80H,37 ; 2,7
- DB 01+40H,02,02+40H,03 ; 1,0
- DB 07+40H,08,08+40H,09 ; 1,3
- DB 13+40H,14,14+40H,15 ; 1,6
- DB 19+40H,20,20+40H,21 ; 1,9
- DB 05+40H,06,06+40H,07 ; 1,2
- DB 11+40H,12,12+40H,13 ; 1,5
- DB 17+40H,18,18+40H,19 ; 1,8
- DB 03+40H,04,04+40H,05 ; 1,1
- DB 09+40H,10,10+40H,11 ; 1,4
- DB 15+40H,16,16+40H,17 ; 1,7
- DB 07+00H,48,08+00H,49 ; 0,3
- DB 13+00H,52,14+00H,53 ; 0,6
- DB 19+00H,44,20+00H,45 ; 0,9
- DB 05+00H,46,06+00H,47 ; 0,2
- DB 11+00H,50,12+00H,51 ; 0,5
- DB 17+00H,56,18+00H,57 ; 0,8
- DB 03+00H,42,04+00H,43 ; 0,1
- DB 09+00H,00,10+00H,01 ; 0,4
- DB 15+00H,54,16+00H,55 ; 0,7
- ;
- MAXSEC EQU ($-SECTBL)/2 ;# OF SECTORS IN TABLE
- ;
- ; VARIABLE DATA
- ;
- DFLAG: DS 1 ;=0, READ SYS. =1, WRITE SYS.
- SECPTR: DS 2 ;PTR INTO SECTBL
- SCOUNT: DS 1 ;COUNT OF SECTORS LEFT TO XFER
- ;
- END SDNSGEN
-