home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
SIMTEL
/
CPMUG
/
CPMUG082.ARK
/
NSGEN.ASM
< prev
next >
Wrap
Assembly Source File
|
1984-04-29
|
11KB
|
375 lines
TITLE 'NSGEN V3.4 - WRITE CP/M 2.2 TO NORTH STAR DISK'
; PAGE 44
;
; These routines copyright (c) 1980, 1981, 1982 by Steve Bogolub,
; 2338 S. Scoville Ave., Berwyn, IL 60402. This software may be
; used freely for non-commercial purposes only, and may not be sold.
;
;************************************************************
;
; THIS PROGRAM IS SET UP TO PROVIDE THE FUNCTIONS
; OF THE DIGITAL RESEARCH STANDARD CP/M PROGRAM
; 'SYSGEN', BUT FOR A NORTH STAR DOUBLE DENSITY
; VERSION OF CP/M. SINCE THE NORTH STAR HAS 10
; SECTORS PER TRACK, WITH 512 BYTES PER SECTOR
; USING DOUBLE DENSITY, THE STANDARD SYSGEN PROGRAM
; IS WORTHLESS. USING THIS VERSION, THE CCP AND
; BDOS ARE WRITTEN OUT TO CONSECTIVE SECTORS OF
; TRACK ONE, 0-9 INCLUSIVE. ELEVEN 512-BYTE
; SECTORS ARE REQUIRED, SO THE LAST ONE IS
; WRITTEN OUT TO TRACK ZERO, SECTOR THREE. THE
; CCP/BDOS CODE IS ASSUMED TO BE LOADED INTO
; CONTIGUOUS MEMORY LOCATIONS STARTING AT 0980H.
; THE CONTROL CODE FOR THE JADE DOUBLE D FLOPPY
; DISK CONTROLLER IS EXPECTED AT ADDRESS 1F80H,
; EXTENDING FOR 1024 BYTES. THIS CODE IS WRITTEN
; OUT TO TRACK ZERO, SECTORS ONE AND TWO. THE
; NORTH STAR BIOS IS ASSUMED TO RESIDE IN MEMORY
; FROM 2380H TO 2F7FH INCLUSIVE. THE LAST 512 BYTES
; OF BIOS (2D80H - 2F7FH) PERFORM THE FUNCTION
; OF DISK BOOT, AND ARE WRITTEN OUT TO TRACK ZERO,
; SECTOR FOUR, WHERE THE NORTH STAR PROM BOOT
; EXPECTS TO FIND THE SYSTEM BOOT CODE. THE REST
; OF BIOS (1ST 3K, 2380H - 2D7FH) IS WRITTEN OUT
; TO TRACK ZERO, SECTORS 5-9 INCLUSIVE. TRACK
; ZERO, SECTOR ZERO IS RESERVED FOR A LIFEBOAT-
; COMPATIBLE ID AND FUTURE ADDITIONS.
;
; IN ORDER TO FIND THE RIGHT SECTORS, WE ASSUME
; THAT THERE ARE 40 LOGICAL SECTORS PER TRACK,
; NUMBERED 1-40 INCLUSIVE. IN ORDER TO WRITE AT
; HIGH SPEED, WE ASSUME THAT THERE ARE 4 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 (WHERE CCP LEFT BY MOVCPM)
;
CPMIA EQU 0980H
;
; PROGRAM START. SET UP STACK PTR AND GET SOURCE DISK.
;
NSGEN: LXI SP,NSGEN ;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 BIT INTO POSITION
ANI 1 ;TRACK IS ZERO OR ONE
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 7FH ;STRIP TRACK BIT
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 'NSGEN V3.4',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. IF HIGH BIT IS SET,
; SECTOR IS ON TRACK ONE. IF NOT, SECTOR IS
; ON TRACK ZERO. LOW SEVEN 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,00,02+80H,01,03+80H,02,04+80H,03 ; 1,0
DB 13+80H,12,14+80H,13,15+80H,14,16+80H,15 ; 1,3
DB 25+80H,24,26+80H,25,27+80H,26,28+80H,27 ; 1,6
DB 37+80H,36,38+80H,37,39+80H,38,40+80H,39 ; 1,9
DB 09+80H,08,10+80H,09,11+80H,10,12+80H,11 ; 1,2
DB 21+80H,20,22+80H,21,23+80H,22,24+80H,23 ; 1,5
DB 33+80H,32,34+80H,33,35+80H,34,36+80H,35 ; 1,8
DB 05+80H,04,06+80H,05,07+80H,06,08+80H,07 ; 1,1
DB 17+80H,16,18+80H,17,19+80H,18,20+80H,19 ; 1,4
DB 29+80H,28,30+80H,29,31+80H,30,32+80H,31 ; 1,7
DB 13+00H,40,14+00H,41,15+00H,42,16+00H,43 ; 0,3
DB 25+00H,56,26+00H,57,27+00H,58,28+00H,59 ; 0,6
DB 37+00H,68,38+00H,69,39+00H,70,40+00H,71 ; 0,9
DB 09+00H,48,10+00H,49,11+00H,50,12+00H,51 ; 0,2
DB 21+00H,52,22+00H,53,23+00H,54,24+00H,55 ; 0,5
DB 33+00H,64,34+00H,65,35+00H,66,36+00H,67 ; 0,8
DB 05+00H,44,06+00H,45,07+00H,46,08+00H,47 ; 0,1
DB 17+00H,72,18+00H,73,19+00H,74,20+00H,75 ; 0,4
DB 29+00H,60,30+00H,61,31+00H,62,32+00H,63 ; 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 NSGEN