Files
Digital-Research-Source-Code/CPM OPERATING SYSTEMS/CPM 2.X/CPM 2.2/CPM 2.2 SOURCE/SYSGEN.ASM
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

440 lines
8.7 KiB
NASM

TITLE 'SYSGEN - SYSTEM GENERATION PROGRAM 8/79'
; SYSTEM GENERATION PROGRAM, VERSION FOR MDS
VERS EQU 20 ;X.X
;
; COPYRIGHT (C) DIGITAL RESEARCH
; 1976, 1977, 1978, 1979
;
NSECTS EQU 26 ;NO. OF SECTORS PER TRACK
NTRKS EQU 2 ;NO. OF OPERATING SYSTEM TRACKS
NDISKS EQU 4 ;NUMBER OF DISK DRIVES
SECSIZ EQU 128 ;SIZE OF EACH SECTOR
LOG2SEC EQU 7 ;LOG 2 SECSIZ
SKEW EQU 1 ;SECTOR SKEW FACTOR
;
FCB EQU 005CH ;DEFAULT FCB LOCATION
FCBCR EQU FCB+32 ;CURRENT RECORD LOCATION
TPA EQU 0100H ;TRANSIENT PROGRAM AREA
LOADP EQU 900H ;LOAD POINT FOR SYSTEM DURING LOAD/STORE
BDOS EQU 5H ;DOS ENTRY POINT
BOOT EQU 0 ;JMP TO 'BOOT' TO REBOOT SYSTEM
CONI EQU 1 ;CONSOLE INPUT FUNCTION
CONO EQU 2 ;CONSOLE OUTPUT FUNCTION
SELF EQU 14 ;SELECT DISK
OPENF EQU 15 ;DISK OPEN FUNCTION
DREADF EQU 20 ;DISK READ FUNCTION
;
MAXTRY EQU 10 ;MAXIMUM NUMBER OF RETRIES ON EACH READ/WRITE
CR EQU 0DH ;CARRIAGE RETURN
LF EQU 0AH ;LINE FEED
STACKSIZE EQU 16 ;SIZE OF LOCAL STACK
;
WBOOT EQU 1 ;ADDRESS OF WARM BOOT (OTHER PATCH ENTRY
; POINTS ARE COMPUTED RELATIVE TO WBOOT)
SELDSK EQU 24 ;WBOOT+24 FOR DISK SELECT
SETTRK EQU 27 ;WBOOT+27 FOR SET TRACK FUNCTION
SETSEC EQU 30 ;WBOOT+30 FOR SET SECTOR FUNCTION
SETDMA EQU 33 ;WBOOT+33 FOR SET DMA ADDRESS
READF EQU 36 ;WBOOT+36 FOR READ FUNCTION
WRITF EQU 39 ;WBOOT+39 FOR WRITE FUNCTION
;
ORG TPA ;TRANSIENT PROGRAM AREA
JMP START
DB 'COPYRIGHT (C) 1978, DIGITAL RESEARCH '
;
; TRANSLATE TABLE - SECTOR NUMBERS ARE TRANSLATED
; HERE TO DECREASE THE SYSGEN TIME FOR MISSED SECTORS
; WHEN SLOW CONTROLLERS ARE INVOLVED. TRANSLATION TAKES
; PLACE ACCORDING TO THE "SKEW" FACTOR SET ABOVE.
;
OST: DB NTRKS ;OPERATING SYSTEM TRACKS
SPT: DB NSECTS ;SECTORS PER TRACK (CAN BE PATCHED)
TRAN: ;BASE OF TRANSLATE TABLE
TRELT SET 1 ;FIRST/NEXT TRAN ELEMENT
TRBASE SET 1 ;BASE FOR WRAPAROUND
REPT NSECTS ;ONCE FOR EACH SECTOR ON A TRACK
DB TRELT ;GENERATE FIRST/NEXT SECTOR
TRELT SET TRELT+SKEW
IF TRELT GT NSECTS
TRBASE SET TRBASE+1
TRELT SET TRBASE
ENDIF
ENDM
;
; NOW LEAVE SPACE FOR EXTENSIONS TO TRANSLATE TABLE
IF NSECTS LT 64
REPT 64-NSECTS
DB 0
ENDM
;
;
;
;
; UTILITY SUBROUTINES
MULTSEC:
;MULTIPLY THE SECTOR NUMBER IN A BY THE SECTOR SIZE
MOV L,A! MVI H,0 ;SECTOR NUMBER IN HL
REPT LOG2SEC ;LOG 2 OF SECTOR SIZE
DAD H
ENDM
RET ;WITH HL = SECTOR * SECTOR SIZE
;
GETCHAR:
; READ CONSOLE CHARACTER TO REGISTER A
MVI C,CONI! CALL BDOS!
; CONVERT TO UPPER CASE BEFORE RETURN
CPI 'A' OR 20H ! RC ;RETURN IF BELOW LOWER CASE A
CPI ('Z' OR 20H) + 1
RNC ;RETURN IF ABOVE LOWER CASE Z
ANI 5FH! RET
;
PUTCHAR:
; WRITE CHARACTER FROM A TO CONSOLE
MOV E,A! MVI C,CONO! CALL BDOS! RET
;
CRLF: ;SEND CARRIAGE RETURN, LINE FEED
MVI A,CR
CALL PUTCHAR
MVI A,LF
CALL PUTCHAR
RET
;
CRMSG: ;PRINT MESSAGE ADDRESSED BY H,L TIL ZERO
;WITH LEADING CRLF
PUSH H! CALL CRLF! POP H ;DROP THRU TO OUTMSG0
OUTMSG:
MOV A,M! ORA A! RZ
; MESSAGE NOT YET COMPLETED
PUSH H! CALL PUTCHAR! POP H! INX H
JMP OUTMSG
;
SEL:
; SELECT DISK GIVEN BY REGISTER A
MOV C,A! LHLD WBOOT! LXI D,SELDSK! DAD D! PCHL
;
TRK: ;SET UP TRACK
LHLD WBOOT ;ADDRESS OF BOOT ENTRY
LXI D,SETTRK ;OFFSET FOR SETTRK ENTRY
DAD D
PCHL ;GONE TO SETTRK
;
SEC: ;SET UP SECTOR NUMBER
LHLD WBOOT
LXI D,SETSEC
DAD D
PCHL
;
DMA: ;SET DMA ADDRESS TO VALUE OF B,C
LHLD WBOOT
LXI D,SETDMA
DAD D
PCHL
;
READ: ;PERFORM READ OPERATION
LHLD WBOOT
LXI D,READF
DAD D
PCHL
;
WRITE: ;PERFORM WRITE OPERATON
LHLD WBOOT
LXI D,WRITF
DAD D
PCHL
;
DREAD: ;DISK READ FUNCTION
MVI C,DREADF
JMP BDOS
;
OPEN: ;FILE OPEN FUNCTION
MVI C,OPENF ! JMP BDOS
;
GETPUT:
; GET OR PUT CP/M (RW=0 FOR READ, 1 FOR WRITE)
; DISK IS ALREADY SELECTED
;
LXI H,LOADP ;LOAD POINT IN RAM FOR CP/M DURING SYSGEN
SHLD DMADDR
;
; CLEAR TRACK TO 00
MVI A,-1 ;START WITH TRACK EQUAL -1
STA TRACK
;
RWTRK: ;READ OR WRITE NEXT TRACK
LXI H,TRACK
INR M ;TRACK = TRACK + 1
LDA OST ;NUMBER OF OPERATING SYSTEM TRACKS
CMP M ;= TRACK NUMBER ?
JZ ENDRW ;END OF READ OR WRITE
;
; OTHERWISE NOTDONE, GO TO NEXT TRACK
MOV C,M ;TRACK NUMBER
CALL TRK ;TO SET TRACK
MVI A,-1 ;COUNTS 0, 1, 2, . . . 25
STA SECTOR ;SECTOR INCREMENTED BEFORE READ OR WRITE
;
RWSEC: ;READ OR WRITE SECTOR
LDA SPT ;SECTORS PER TRACK
LXI H,SECTOR
INR M ;TO NEXT SECTOR
CMP M ;A=26 AND M=0 1 2...25 (USUALLY)
JZ ENDTRK ;
;
; READ OR WRITE SECTOR TO OR FROM CURRENT DMA ADDR
LXI H,SECTOR
MOV E,M ;SECTOR NUMBER
MVI D,0 ;TO DE
LXI H,TRAN
MOV B,M ;TRAN(0) IN B
DAD D ;SECTOR TRANSLATED
MOV C,M ;VALUE TO C READY FOR SELECT
PUSH B ;SAVE TRAN(0),TRAN(SECTOR)
CALL SEC ;SET UP SECTOR NUMBER
POP B ;RECALL TRAN(0),TRAN(SECTOR)
MOV A,C ;TRAN(SECTOR)
SUB B ;-TRAN(0)
CALL MULTSEC ;*SECTOR SIZE
XCHG ;TO DE
LHLD DMADDR ;BASE DMA ADDRESS FOR THIS TRACK
DAD D ;+(TRAN(SECTOR)-TRAN(0))*SECSIZ
MOV B,H
MOV C,L ;TO BC FOR SEC CALL
CALL DMA ;DMA ADDRESS SET FROM B,C
; DMA ADDRESS SET, CLEAR RETRY COUNT
XRA A
STA RETRY ;SET TO ZERO RETRIES
;
TRYSEC: ;TRY TO READ OR WRITE CURRENT SECTOR
LDA RETRY
CPI MAXTRY ;TOO MANY RETRIES?
JC TRYOK
;
; PAST MAXTRIES, MESSAGE AND IGNORE
LXI H,ERRMSG
CALL OUTMSG
CALL GETCHAR
CPI CR
JNZ REBOOT
;
; TYPED A CR, OK TO IGNORE
CALL CRLF
JMP RWSEC
;
TRYOK:
; OK TO TRY READ OR WRITE
INR A
STA RETRY ;RETRY=RETRY+1
LDA RW ;READ OR WRITE?
ORA A
JZ TRYREAD
;
; MUST BE WRITE
CALL WRITE
JMP CHKRW ;CHECK FOR ERROR RETURNS
TRYREAD:
CALL READ
CHKRW:
ORA A
JZ RWSEC ;ZERO FLAG IF R/W OK
;
; ERROR, RETRY OPERATION
JMP TRYSEC
;
; END OF TRACK
ENDTRK:
LDA SPT ;SECTORS PER TRACK
CALL MULTSEC ;*SECSIZ
XCHG ;TO DE
LHLD DMADDR ;BASE DMA FOR THIS TRACK
DAD D ;+SPT*SECSIZ
SHLD DMADDR ;READY FOR NEXT TRACK
JMP RWTRK ;FOR ANOTHER TRACK
;
ENDRW: ;END OF READ OR WRITE, RETURN TO CALLER
RET
;
;
START:
;
LXI SP,STACK ;SET LOCAL STACK POINTER
LXI H,SIGNON
CALL OUTMSG
;
; CHECK FOR DEFAULT FILE LOAD INSTEAD OF GET
;
LDA FCB+1 ;BLANK IF NO FILE
CPI ' '
JZ GETSYS ;SKIP TO GET SYSTEM MESSAGE IF BLANK
LXI D,FCB ;TRY TO OPEN IT
CALL OPEN ;
INR A ;255 BECOMES 00
JNZ RDOK ;OK TO READ IF NOT 255
;
; FILE NOT PRESENT, ERROR AND REBOOT
;
LXI H,NOFILE
CALL CRMSG
JMP REBOOT
;
; FILE PRESENT
; READ TO LOAD POINT
;
RDOK:
XRA A
STA FCBCR ;CURRENT RECORD = 0
;
; PRE-READ AREA FROM TPA TO LOADP
;
MVI C,(LOADP-TPA)/SECSIZ
; PRE-READ FILE
PRERD:
PUSH B ;SAVE COUNT
LXI D,FCB ;INPUT FILE CONTROL COUNT
CALL DREAD ;ASSUME SET TO DEFAULT BUFFER
POP B ;RESTORE COUNT
ORA A
JNZ BADRD ;CANNOT ENCOUNTER END-OF FILE
DCR C ;COUNT DOWN
JNZ PRERD ;FOR ANOTHER SECTOR
;
; SECTORS SKIPPED AT BEGINNING OF FILE
;
LXI H,LOADP
RDINP:
PUSH H
MOV B,H
MOV C,L ;READY FOR DMA
CALL DMA ;DMA ADDRESS SET
LXI D,FCB ;READY FOR READ
CALL DREAD ;
POP H ;RECALL DMA ADDRESS
ORA A ;00 IF READ OK
JNZ PUTSYS ;ASSUME EOF IF NOT.
; MORE TO READ, CONTINUE
LXI D,SECSIZ
DAD D ;HL IS NEW LOAD ADDRESS
JMP RDINP
;
BADRD: ;EOF ENCOUNTERED IN INPUT FILE
LXI H,BADFILE
CALL CRMSG
JMP REBOOT
;
;
GETSYS:
LXI H,ASKGET ;GET SYSTEM?
CALL CRMSG
CALL GETCHAR
CPI CR
JZ PUTSYS ;SKIP IF CR ONLY
;
SUI 'A' ;NORMALIZE DRIVE NUMBER
CPI NDISKS ;VALID DRIVE?
JC GETC ;SKIP TO GETC IF SO
;
; INVALID DRIVE NUMBER
CALL BADDISK
JMP GETSYS ;TO TRY AGAIN
;
GETC:
; SELECT DISK GIVEN BY REGISTER A
ADI 'A'
STA GDISK ;TO SET MESSAGE
SUI 'A'
CALL SEL ;TO SELECT THE DRIVE
; GETSYS, SET RW TO READ AND GET THE SYSTEM
CALL CRLF
LXI H,GETMSG
CALL OUTMSG
CALL GETCHAR
CPI CR
JNZ REBOOT
CALL CRLF
;
XRA A
STA RW
CALL GETPUT
LXI H,DONE
CALL OUTMSG
;
; PUT SYSTEM
PUTSYS:
LXI H,ASKPUT
CALL CRMSG
CALL GETCHAR
CPI CR
JZ REBOOT
SUI 'A'
CPI NDISKS
JC PUTC
;
; INVALID DRIVE NAME
CALL BADDISK
JMP PUTSYS ;TO TRY AGAIN
;
PUTC:
; SET DISK FROM REGISTER C
ADI 'A'
STA PDISK ;MESSAGE SET
SUI 'A'
CALL SEL ;SELECT DEST DRIVE
; PUT SYSTEM, SET RW TO WRITE
LXI H,PUTMSG
CALL CRMSG
CALL GETCHAR
CPI CR
JNZ REBOOT
CALL CRLF
;
LXI H,RW
MVI M,1
CALL GETPUT ;TO PUT SYSTEM BACK ON DISKETTE
LXI H,DONE
CALL OUTMSG
JMP PUTSYS ;FOR ANOTHER PUT OPERATION
;
REBOOT:
MVI A,0
CALL SEL
CALL CRLF
JMP BOOT
BADDISK:
;BAD DISK NAME
LXI H,QDISK
CALL CRMSG
RET
;
;
;
; DATA AREAS
; MESSAGES
SIGNON: DB 'SYSGEN VER '
DB VERS/10+'0','.',VERS MOD 10+'0'
DB 0
ASKGET: DB 'SOURCE DRIVE NAME (OR RETURN TO SKIP)',0
GETMSG: DB 'SOURCE ON '
GDISK: DS 1 ;FILLED IN AT GET FUNCTION
DB ', THEN TYPE RETURN',0
ASKPUT: DB 'DESTINATION DRIVE NAME (OR RETURN TO REBOOT)',0
PUTMSG: DB 'DESTINATION ON '
PDISK: DS 1 ;FILLED IN AT PUT FUNCTION
DB ', THEN TYPE RETURN',0
ERRMSG: DB 'PERMANENT ERROR, TYPE RETURN TO IGNORE',0
DONE: DB 'FUNCTION COMPLETE',0
QDISK: DB 'INVALID DRIVE NAME (USE A, B, C, OR D)',0
NOFILE: DB 'NO SOURCE FILE ON DISK',0
BADFILE:
DB 'SOURCE FILE INCOMPLETE',0
;
; VARIABLES
SDISK: DS 1 ;SELECTED DISK FOR CURRENT OPERATION
TRACK: DS 1 ;CURRENT TRACK
SECTOR: DS 1 ;CURRENT SECTOR
RW: DS 1 ;READ IF 0, WRITE IF 1
DMADDR: DS 2 ;CURRENT DMA ADDRESS
RETRY: DS 1 ;NUMBER OF TRIES ON THIS SECTOR
DS STACKSIZE*2
STACK:
END