	.title	'DSC/3, DSC/4 CP/M 1.4 Floppy bootstrap loader'
	.sbttl	'FBOOT.ASM'
	.pabs
	.phex
;----------
; DSC/3, DSC/4 CP/M 1.4 Floppy bootstrap loader
;
; Update history:
;
; 1.40	 Initial release
; 1.424  Changed specify to 03,8F,02
; 1.426  Added boot from drive 1
; 1.427  Added serial number
; 1.430  Change boot disk code
; 1.431  Add floppy network option
;
; Conditional assembly options:
;
FLOPboot =\	"
Enter 0 for stand-alone system
      1 for floppy network master "
NETboot	== 1-FLOPboot
;
; Data and address definitions:
;
Msize	==	64	; memory size (Kbytes)
.ife	FLOPboot,[lenBIOS = 0F00h]
.ife	NETboot, [lenBIOS = 1100h]
BOOT	==	09000h	; base of the BOOTstrap loader
DDToff	==	900h-BOOT ; offset for DDT sysgen
BIOS	==	Msize*1024-lenBIOS ; base of the BIOS
CBASE	==	(Msize-16)*1024+512-lenBIOS
CPM	==	CBASE+2900h ; base of CP/M
BDOS	==	CBASE+3106h ; base of the BDOS
SELDSK	==	BIOS+1Bh
CPMMAP	==	BIOS+63h
;
; PROM Monitor entry points:
command	==	3F3h	; send command to floppy
result	==	3F6h	; receive result from floppy
ioerr	==	3F9h	; I/O error routine
;
; Port definitions:
;
DMA	==	38h	; DMA chip
FLOPP	==	18h	; Floppy DMA channel
SETMAP	==	03h	; Set memory map register
STOPFLOP==	03h	; Stop floppy controller
ONMAP	==	00h	; Activate DSC/4 memory map
OFFPROM	==	02h	; Deactivate DSC/3 PROM
	.page
;----------
; Bootstrap loader
;
; This program is loaded and executed by the 'BF'
; command of the PROM Monitor.  It is stored on track 0
; sectors 1-2 of a standard CP/M diskette.  It will do
; the following:
;
; (1) Set up the DSC/4 memory map, temporarily keeping
;     pages 0 and 9 in local memory.
; (2) Read the BIOS into page F.
; (3) Move remainder of bootstrap to page 4.
; (4) Map pages 0 and 9 to external memory on the DSC/4
;     and disable the PROM on the DSC/3.
; (5) Store active drive number for CP/M
; (6) Jump to the cold boot entry point of the BIOS.
;
; Note the step 1 is required for the DSC/4 only; 
; it has no deleterious effect on the DSC/3.
	.loc	BOOT 
;
; (1) Set up a memory map, temporarily keeping pages 0
;     and 9 in local memory.
;
	lixd	3FEh	; get serial number
	lxi	H,memmap ; point to base of memory map
	lxi	B,0<8+SETMAP ; initialize reg F first
domap:	outi
	mvi	A,11h
	add	B
	mov	B,A	; load next mm reg no into B
	jrnz	domap
	in	ONMAP	; activate DSC-4 memory map
;
; (2) Read the BIOS into memory.
;
; Setup drive number
	lda	9391h	; drive no. put here by PROM
	sta	seekFLOP+1
	sta	readFLOP+1
	exaf		; save bFLOPboot
;
; Data and address definitions:
;
Msize	==	64	; memory size (Kbytes)
.ife	FLOPboot,[lenBIOS = 0F00h]
.ife	NETboot, [lenBIOS = 1100h]
BOOT	==	09000h	; base of the BOOTstrap loader
DDToff	==	900h-BOOT ; offset for DDT sysgen
BIOS	==	Msize*1024-lenBIOS ; base of the BIOS
CBASE	==	(Msize-16)*1024+512-lenBIOS
CPM	==	CBASE+2900h ; base of CP/M
BDOS	==	CBASE+3106h ; base of the BDOS
SELDSK	==	BIOS+1Bh
CPMMAP	==	BIOS+63h
;
; PROM Monitor entry points:
command	==	3F3h	; send command to floppy
result	==	3F6h	; receive result from floppy
ioerr	==	3F9h	; I/O error routine
;
; Port definitions:
;
DMA	==	38h	; DMA chip
FLOPP	==	18h	; Floppy DMA channel
SETMAP	==	03h	; Set memory map register
STOPFLOP==	03h	; Stop floppy controller
ONMAP	==	00h	; Activate DSC/4 memory map
OFFPROM	==	02h	; Deactivate DSC/3 PROM
	.page
;----------
; Bootstrap loader
;
; This program is loaded and executed by the 'BF'
; command of the PROM Monitor.  It is stored on track 0
; sectors 1-2 of a standard CP/M diskette.  It will do
; the following:
;
; (1) Set up the DSC/4 memory map, temporarily keeping
;     pages 0 and 9 in local memory.
; (2) Read the BIOS into page F.
; (3) Move remainder of bootstrap to page 4.
; (4) Map pages 0 and 9 to external memory on the DSC/4
;     and disable the PROM on the DSC/3.
; (5) Store active drive number for CP/M
; (6) Jump to the cold boot entry point of the BIOS.
;
; Note the step 1 is required for the DSC/4 only; 
; it has no deleterious effect on th (in local memory)
	.byte	0F1h	; page 1
	.byte	0F2h	; page 2
	.byte	0F3h	; page 3
	.byte	0F4h	; page 4
	.byte	0F5h	; page 5
	.byte	0F6h	; page 6
	.byte	0F7h	; page 7
	.byte	0F8h	; page 8
	.byte	0	; page 9 (in local memory)
	.byte	0FAh	; page A
	.byte	0FBh	; page B
	.byte	0FCh	; page C
	.byte	0FDh	; page D
	.byte	0FEh	; page E
;
; Floppy commands
drive	==	0	; BIOS drive number
track	==	1	; BIOS track number
sector	==	10	; BIOS sector number
endcom	==	0FFh	; end-of-command character
seekFLOP:
	.byte	15	; seek command
	.byte	drive
	.byte	track
	.byte	endcom
IsenseFLOP:
	.byte	8	; sense interrupt status
	.byte	endcom
specFLOP:
	.byte	3	; specify command
	.byte	8Fh	; seek rate = 8ms
			; 35ms delay after head load
	.byte	02h	; 10ms delay after seek
			; DMA mode
	.byte	endcom
readFLOP:
	.byte	46h	; read double density command
	.byte	drive	; drive select
	.byte	track	; track address
	.byte	0	; head address
	.byte	sector	; first sector number
	.byte	1	; double density
	.byte	26	; last sector number
	.byte	0Eh	; gap length
	.byte	00	; sector size (not used)
	.byte	endcom
resbuf	==	9380h	; result buffer is same
			;  as used in the PROM
DMAcom:
	.byte	0C3h
	.byte	0C7h
	.byte	0CBh
	.byte	07Dh
	.word	BIOS	; load start address
	.word	lenBIOS-1
	.byte	14h
	.byte	28h
	.byte	95h
	.byte	FLOPP
	.byte	12h
	.byte	DMAvect&0FFh ; interrupt vector
	.byte	9Ah
	.byte	0CFh
	.byte	1
	.byte	0CFh
	.byte	0ABh
	.byte	87h
DMA$	==	.-DMAcom
;
	.loc	(.+1)&0FFFEh ; force at even address
DMAvect:.word	DMAdone	; DMA interrupt vector
;
; DMA interrupt routine
DMAdone:
	push	PSW
	in	STOPFLOP ; stop the floppy
	mvi	A,0C3h	; reset the DMA chip
	out	DMA
	pop	PSW
	reti
.end
