Files
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

252 lines
6.4 KiB
NASM
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

; Figure 7-5.
;
; Example Put CP/M
;
; This program writes out the CP/M Cold Boot Loader, the
; CCP, BDOS and BIOS to a floppy diskette. It runs under
; CP/M as a normal Transient Program.
;
Version EQU '01' ;Equates used in the sign on message
Month EQU '07'
Day EQU '24'
Year EQU '82'
;
;
; The actual PUTCPMF5.COM program consists of this code,
; plus the BOOTF5.HEX, the CCP, BDOS and BIOS.
;
; When this program executes, the memory image should
; look like this :
;
; Component Base Address
; BIOS 1F80H
; BDOS 1180H
; CCP 0980H
; BOOTF5 0780H
;
; The components are produced as follows :
;
; BIOS.HEX By assembling source code
; BDOS ) From a CPMnn.COM file output
; CCP ) by MOVCPM and SAVEd on disk
; BOOTF5.HEX By assembling source code
;
; The components are pieced together using DDT with the
; following commands :
;
; DDT CPMnn.COM
; IPUTCPMF5.HEX
; R (Reads in this program)
; IBOOTF5.HEX
; R680 (Reads in Boot at 0780H)
; IBIOS.HEX
; R2980 (Reads in BIOS at 1F80H)
; G0 (Exit from DDT)
; SAVE 40 PUTCPMF5.COM (Create final .COM file)
;
; The actual layout of the diskette is as follows :
;
; Track 0 Sector
; 1 2 3 4 5 6 7 8 9
; Head +-----+-----+-----+-----+-----+-----+-----+-----+-----+
; 0 |Boot |<======== CCP ========>|<======= BDOS ========|
; +-----+-----+-----+-----+-----+-----+-----+-----+-----+
; 1 |====== BDOS ====>|<============= BIOS ============>|
; +-----+-----+-----+-----+-----+-----+-----+-----+-----+
; 10 11 12 13 14 15 16 17 18
; Sector
;
; Equates for defining memory size and the base address and
; length of the system components.
;
Memory$Size EQU 64 ;Number of Kbytes of RAM
;
; The BIOS Length must match that declared in the BIOS.
;
BIOS$Length EQU 0900H
;
Boot$Length EQU 512
CCP$Length EQU 0800H ;Constant
BDOS$Length EQU 0E00H ;Constant
;
Length$In$Bytes EQU CCP$Length + BDOS$Length + BIOS$Length
;
Start$Image EQU 980H - Boot$Length ;Address of CP/M Image
Length$Image EQU Length$In$Bytes + Boot$Length
;
;
; Disk Characteristics
;
; These equates describe the physical characteristics of
; the floppy diskette so that the program can move from
; one sector to the next, updating the track and resetting
; the sector when necessary.
;
First$Sector$on$Track EQU 1
Last$Sector$on$Track EQU 18
Last$Sector$on$Head$0 EQU 9
Sector$Size EQU 512
;
;
; Controller Characteristics
;
; On this computer system, the floppy disk controller can write
; multiple sectors in a single command. However, in order to
; to produce a more general example it is shown only reading one
; sector at a time.
;
Sectors$Per$Write EQU 1
;
;
; Cold Boot Characteristics
;
Start$Track EQU 0 ;Initial values for CP/M image
Start$Sector EQU 1 ;= " =
Sectors$To$Write EQU (Length$Image + Sector$Size - 1) / Sector$Size
;
;
B$PRINTS EQU 9 ;Print string terminated by $
BDOS EQU 5 ;BDOS Entry Point
;
;
ORG 100H
Put$CPM:
JMP Main$Code ;Enter main code body
;For reasons of clarity, the main
; data structures are shown before the
; executable code.
CR EQU 0DH ;Carriage Return
LF EQU 0AH ;Line Feed
;
Signon$Message:
DB CR,LF,'Put CP/M on Diskette'
DB CR,LF
DB 'Version '
DW Version
DB ' '
DW Month
DB '/'
DW Day
DB '/'
DW Year
DB CR,LF,'$'
;
; Disk Control Tables
;
Disk$Control$5 EQU 45H ;5 1/4" Control Byte
Command$Block$5 EQU 46H ;Control Table Pointer
Disk$Status EQU 43H ;Completion status
;
;
; The command table Track and DMA$Address can also be used
; as working storage and updated as the load process
; continues. The Sector in the command table cannot be
; used directly as the disk controller requires it to be
; the sector number on the specified head (1 - 9) rather
; than the sector number on track. Hence a separate variable
; must be used.
;
Sector: DB Start$Sector
;
Command$Table: DB 02H ;Command - Write
Unit: DB 0 ;Unit (Drive) number = 0 or 1
Head: DB 0 ;Head number = 0 or 1
Track: DB Start$Track ;Used as working variable
Sector$on$head: DB 0 ;Converted by low-level driver
Byte$Count: DW Sector$Size * Sectors$Per$Write
DMA$Address: DW Start$Image
Next$Status: DW Disk$Status ;Pointer to next Status Block
; if commands are chained.
Next$Control: DW Disk$Control$5 ;Pointer to next Control Byte
; if commands are chained.
Main$Code:
LXI SP,Put$CPM ;Stack grows down below code
LXI D,Signon$Message ;Sign on
MVI C,B$PRINTS ;Print string until $
CALL BDOS
LXI H,Command$Table ;Point the disk controller at
SHLD Command$Block$5 ; the command block
MVI C,Sectors$To$Write ;Set sector count
Write$Loop:
CALL Put$CPM$Write ;Write data onto diskette
DCR C ;Downdate sector count
JZ 0 ;Warm Boot
LXI H,Sector ;Update sector number
MVI A,Sectors$Per$Write ; by adding on number of sectors
ADD M ; by controller
MOV M,A ;Save result
MVI A,Last$Sector$On$Track + 1 ;Check if at end of track
CMP M
JNZ Not$End$Track
MVI M,First$Sector$On$Track ;Yes, reset to beginning
LHLD Track ;Update Track number
INX H
SHLD Track
Not$End$Track:
LHLD DMA$Address ;Update DMA Address
LXI D,Sector$Size * Sectors$Per$Write
DAD D
SHLD DMA$Address
JMP Write$Loop ;Write next block
;
Put$CPM$Write: ;At this point, the description of the
; operation required is in the variables
; contained in the Command Table, along
; with the Sector variable.
PUSH B ;Save sector count in C
;------ Change this routine to match the disk controller in use ------
MVI B,0 ;Assume head 0
LDA Sector ;Get requested sector
MOV C,A ;Take a copy of it
CPI Last$Sector$on$Head$0+1 ;Check if on head 1
JC Head$0 ;No
SUI Last$Sector$on$Head$0 ;Bias down for head 1
MOV C,A ;Save copy
INR B ;Set head 1
Head$0:
MOV A,B ;Get head
STA Head
MOV A,C ;Get sector
STA Sector$On$Head
LXI H,Disk$Control$5 ;Activate controller
MVI M,80H
Wait$For$Boot$Complete:
MOV A,M ;Get status byte
ORA A ;Check if complete
JNZ Wait$For$Boot$Complete ;No
;Yes, check for errors
LDA Disk$Status
CPI 80H
JC Put$CPM$Error ;Yes, an error occurred
;------ End of Physical Write routine ------
POP B ;Recover sector count in C
RET
;
Put$CPM$Error:
LXI D,Put$CPM$Error$Message
MVI C,B$PRINTS ;Print string until $
CALL BDOS ;Output error message
JMP Main$Code ;Restart the loader
;
Put$CPM$Error$Message:
DB CR,LF,'Error in writing CP/M - retrying...',CR,LF,'$'
END Put$CPM