	title	'Module of Loader-BIOS for CP/M 3.0'

; MC80 Version 1.0
; 28.05.89

;		  Copyright (C), 1982
;		 Digital Research, Inc
;		     P.O. Box 579
;		Pacific Grove, CA  93950
;
;		and
;
;               Sebastian Simon
;               Haendel-Haus Halle
;               Gr. Nikolaistr. 5-6
;               Halle (Saale)
;               4020
;               Tel.: 24606

    ; CP/M 3 Disk definition macros

	maclib cpm3

    ; Z80 macro library instruction definitions

	maclib z80

	maclib	ports

	EXTRN	FLOPPY,PFTKOM,PFTADR
	EXTRN	ITIMEO,LWEXIS,ALWNR,ASPNR,SPNRL
	extrn	conout,conini
	public	prmmsg

;**************************************************************
; VEREINBARUNGEN
;**************************************************************

MAXDSK	EQU	2

    ; BIOS Jump vector.

		; All BIOS routines are invoked by calling these
		;	entry points.

?boot:	jmp boot	; initial entry on cold start
?wboot:	jmp 0

?const:	jmp 0
?conin:	jmp 0
?cono:	jmp ?conout	; send console output character
?list:	jmp 0
?auxo:	jmp 0
?auxi:	jmp 0

?home:	jmp home	; set disks to logical home
?sldsk:	jmp seldsk	; select disk drive, return disk parameter info
?sttrk:	jmp settrk	; set disk track
?stsec:	jmp setsec	; set disk sector
?stdma:	jmp setdma	; set disk I/O memory address
?read:	jmp read	; read physical block(s)
?write:	jmp 0

?lists:	jmp 0
?sctrn:	jmp sectrn	; translate logical to physical sector

?conos:	jmp 0
?auxis:	jmp 0
?auxos:	jmp 0
?dvtbl:	jmp 0
?devin:	jmp 0

?drtbl:	jmp 0
?mltio:	jmp 0
?flush:	jmp 0

?mov:	jmp ?move	; block move memory to memory
?tim:	jmp 0
?bnksl:	jmp 0
?stbnk:	jmp 0
?xmov:	jmp 0

	jmp 0		; reserved for future expansion
	jmp 0		; reserved for future expansion
	jmp 0		; reserved for future expansion

	DS	9	; PLATZ SCHAFFEN FUER INTVEKTOR

	; VEREINBARUNGEN FUER INTERRUPTVEKTOR

intvec:			; INTERRUPTTABELLE
IVDSK1:	DS	2


	; BOOT
	;	Initial entry point for system startup.

BOOT:	DI

;************* SYSTEMGRUNDEINSTELLUNGEN VORNEHMEN *************

	LXI	H,INTVEC
	MOV	A,H		; INITIALISIERUNG INTERRUPT
	STAI
	IM2

;**************** Ruecksetzen Tastaturanzeige ****************

	mvi	a,0f7h
	out	03h

;**************** Initialisieren CRT-Steuerung ***************

	call	conini		; Bildschirm loeschen

; Floppy-Initialisierung

; Port Steuer-A
	lxi	h,itimeo
	shld	ivdsk1
	LXI	H,IVDSK1
	MOV	A,L
	out	fcpioac		; Index-Interrupt
	mvi	a,7fh
	out	fcpioac		; zunaechst byte-Ausgabe
; Port Daten-B
	out	fdpiobc		; Byte Eingabe
	in	fdpiobd		; Scheineingabe
; weiter Steuer A
	mvi	a,11111101b	; AMF aus
	out	fcpioad
	mvi	a,3fh		; ab jetzt Byte Ausgabe
	out	fcpioac		
; Port Daten-A (Schreiben)
	out	fdpioac		; byte-Ausgabe
; Port Steuer-B
	mvi	a,0ffh		; bit E/A
	out	fcpiobc
	mvi	a,0f3h		; eeea aaee
	out	fcpiobc

	ei

; Ermittlung der vorhandenen Laufwerke
	mvi	c,4		; 4 LAUFWERKE WEGEN VESCH.
	mvi	d,0
	mvi	a,0f7h		; ohne lock
flka1:	rlc
	out	fdsel
	exaf
	mvi	b,85		; max 85 mal steppen
flka2:	in	fcpiobd
	rlc			; kam Spur0-Signal?
	jrnc	flka4		; -> ja
	mvi	a,01011111b	; steppen in Richtung Spur 0
	out	fcpioad
	mvi	a,11011111b	; mit Kopf oben
	out	fcpioad
	LXI	H,1000H
;	mvi	h,8		; Schrittzeit abwarten
flka3:	dcr	l
	jrnz	flka3
	dcr	h
	jrnz	flka3
	djnz	flka2		; -> weiteren Schritt ausfuehren
;****Laufwerke immer existent melden wegen 8" Beistell-Laufwerken ohne Strom
;***	jr	flka5		; -> LW nicht existent
;***
flka4:	setb	6,d		; Laufwerk existent melden
flka5:	dcr	c		; weiteres LW?
	jrz	flka6		; -> nein
	rrcr	d
	rrcr	d
	exaf
	jr	flka1		; -> naechstes LW pruefen

flka6:	mov	a,d
	sta	lwexis

	mvi	a,0ffh		; alle LW ausschalten
	out	fdsel

	xra	a
	sta	alwnr		; LW 0 ist das zuletzt benutzte, Motor ist aus
	sta	aspnr		; steht auf Spur 0
	mvi	b,maxdsk
	lxi	h,spnrl
flka7:	mov	m,a		; alle alten Spurnr. sind 0
	inx	h
	djnz	flka7
	RET

;**************************************************************
; Aufruf der CONSOLAUSGABE
;**************************************************************

?conout:
	JMP	conout		; Aufruf Bildschirmausgabe

;**************************************************************
; UNTERPROGRAMM ZEICHENKETTENAUSGABE
;**************************************************************

PRMMSG:	MOV	A,M
	ORA	A
	RZ
	PUSH	H
	MOV	C,A
	CALL	?CONOUT
	POP	H
	INX	H
	JR	PRMMSG

;**************************************************************
; MOVE-FUNKTION
;**************************************************************

?move:
	xchg		; we are passed source in DE and dest in HL
	ldir		; use Z80 block move instruction
	xchg		; need next addresses in same regs
	ret

;**************************************************************
; DISKETTENSTEUERUNG
;**************************************************************

	; SELDSK
	;	Select Disk Drive.  Drive code in <C>.
	;		Invoke login procedure for drive
	;		if this is first select.  Return
	;		address of disk parameter header
	;		in <HL>

seldsk:
	mov a,c ! sta @adrv ! STA @RDRV		; save drive select code
	mov l,c ! mvi h,0 ! dad h		; create index from drive code
	lxi b,@dtbl ! dad b			; get pointer to dispatch table
	mov a,m ! inx h ! mov h,m ! mov l,a	; point at disk descriptor
	ora h ! rz 				; if no entry in table, no disk
	ret


	; HOME
	;	Home selected drive.  Treated as SETTRK(0).

home:
	lxi b,0		; same as set track zero


	; SETTRK
	;	Set Track. Saves track address from <BC> 
	;		in @TRK for further operations.

settrk:
	mov l,c ! mov h,b
	shld @trk
	ret


	; SETSEC
	;	Set Sector.  Saves sector number from <BC>
	;		in @sect for further operations.

setsec:
	mov l,c ! mov h,b
	shld @sect
	ret


	; SETDMA
	;	Set Disk Memory Address.  Saves DMA address
	;		from <BC> in @DMA and sets @DBNK to @CBNK
	;		so that further disk operations take place
	;		in current bank.

setdma:
	mov l,c ! mov h,b
	shld @dma
	ret


	; SECTRN
	;	Sector Translate.  Indexes skew table in <DE>
	;		with sector in <BC>.  Returns physical sector
	;		in <HL>.  If no skew table (<DE>=0) then
	;		returns physical=logical.

sectrn:
	mov l,c ! mov h,b
	mov a,d ! ora e ! rz
	xchg ! dad b ! mov l,m ! mvi h,0
	ret


	; READ
	;	Read physical record from currently selected drive.
	;		Finds address of proper read routine from
	;		extended disk parameter header (XDPH).

read:
	lhld @adrv ! mvi h,0 ! dad h	; get drive code and double it
	lxi d,@dtbl ! dad d		; make address of table entry
	mov a,m ! inx h ! mov h,m ! mov l,a	; fetch table entry
	push h				; save address of table
	lxi d,-8 ! dad d		; point to read routine address
	mov a,m ! inx h ! mov h,m ! mov l,a	; get address of routine
	pop d				; recover address of table
	dcx d ! dcx d			; point to relative drive
	ldax d ! sta @rdrv		; get relative drive code and post it
	inx d ! inx d			; point to DPH again
	pchl				; leap to driver


	; error message components
drive$msg	db	cr,lf,bell,'BIOS Error on ',0
track$msg	db	': T-',0
sector$msg	db	', S-',0


    ; disk communication data items

@adrv	ds	1		; currently selected disk drive
@rdrv	ds	1		; controller relative disk drive
@trk	ds	2		; current track number
@sect	ds	2		; current sector number
@dma	ds	2		; current DMA address


    ; common control characters

cr	equ 13
lf	equ 10
bell	equ 7


;**************************************************************
; VEREINBARUNGEN
;**************************************************************

    ; Extended Disk Parameter Headers (XPDHs)

	DW	0		;dw	fd$write
	dw	fd$read
	DW	0		;dw	fd$login
	DW	0		;dw	fd$init0
	db	0,0		; relative drive zero
fdsd0:
;	dph     TRANS,dpbsd,32,49
	DW	0
	DB	0,0,0,0,0,0,0,0,0
	DB	0
	DW	DPBSD
	DW	CHECK0
	DW	ALLOC0
	DW	DIRBCB
	DW	DTABCB
	DW	0
	DB	0

CHECK0:	DS	32
ALLOC0:	DS	49

	DW	0		;dw	fd$write
	dw	fd$read
	DW	0		;dw	fd$login
	DW	0		;dw	fd$init1
	db	1,0		; relative drive one
fdsd1:
;	dph     TRANS,dpbsd,32,49
	DW	0
	DB	0,0,0,0,0,0,0,0,0
	DB	0
	DW	DPBSD
	DW	CHECK1
	DW	ALLOC1
	DW	DIRBCB
	DW	DTABCB
	DW	0
	DB	0

CHECK1:	DS	32
ALLOC1:	DS	49

; FUER 40 SPUR-LW:
;DPBSD	DPB	1024,5,40,1024,64,2
; FUER 80 SPUR-LW:
DPBSD	DPB	1024,10,80,2048,128,2

    ; Disk I/O routines for standardized BIOS interface


; disk READ and WRITE entry points.

		; these entries are called with the following arguments:

			; relative drive number in @rdrv (8 bits)
			; absolute drive number in @adrv (8 bits)
			; disk transfer address in @dma (16 bits)
			; disk transfer bank	in @dbnk (8 bits)
			; disk track address	in @trk (16 bits)
			; disk sector address	in @sect (16 bits)
			; pointer to XDPH in <DE>

		; they transfer the appropriate data, perform retries
		; if necessary, then return an error code in <A>

;
; READ UNTER VERWENDUNG DES PHYSISCHEN FLOPYTREIBERS
; Write im LOADER nicht benoetigt / nicht implementiert
;
fd$read:		; EINEN SEKTOR LESEN

			» RECHNEÔ @SECÔ IÎ SEKTORBUFFERNÒ UM
	XRÁ	A
	MOÖ	B,Á	» SIDÅ SELEKÔ AUÆ 0
	STÁ	MSIDAKT
	LDA	@SECT	; 0..9 IST DER BEREICH
	INR	A	; 1..10 STARTSEKTOR DES GEBIETES (1K)
	STA	MSEKAKT
	STA	ASEKAKT	; ANZEIGE SEKTOR ZWISCHENSPEICHERN
	SUI	6	; PRUEFEN OB VORDERSEITE
	JC	CAL1
	INR	A	; RUECKSEITE SEKTOREN AB 1 (1K)
	STA	MSEKAKT
	MVI	A,1	; SIDE SELECT AUF 1
	STA	MSIDAKT
CAL1:	LDA	@RDRV	; LAUFWERK
	STA	MDRVAKT
	LDA	@TRK	; SPUR
	STA	MTRKAKT
	LHLD	@DMA
	SHLD	ADR

; PARAMETER FUER PHYSISCHES LESEN SIND GELADEN !

	call	phread
	ora	a
	rz		; --> kein Fehler
	mvi	a,1	; Fehler beim Lesen
	ret

; EINBINDEN PHYSISCHER FLOPPYROUTINE
;
PHREAD:
;	MVI	B,19H	; PFTKOM FUER LESEN 5,25" 40 Spuren MFM

	MVI	B,39H	; PFTKOM FUER LESEN 5,25" 80 Spuren MFM
	LDA	MSIDAKT
	ORA	A
	MOV	A,B
	JRZ	PH1
	ORI	80H
PH1:	STA	PFTKOM

; ANZEIGE LESE- / SCHREIBVORGANG

	BIT	2,A
	MVI	A,'R'
	JRZ	ANZREA
	MVI	A,'W'
ANZREA:	STA	ANZRW
	LDA	MDRVAKT
	ADI	41H
	STA	ANZDRV
	LDA	MTRKAKT
	CALL	HEXASC
	SHLD	ANZTRK
	LDA	ASEKAKT
	CALL	HEXASC
	SHLD	ANZSEK
	LXI	H,ANZEIG
	LXI	D,0FFC7H
	LXI	B,9
	mvi	a,07h
	out	40h
	LDIR				; ANZEIGE AUF BILDSCHIRM
	mvi	a,17h
	out	40h
	LXI	H,ADR
	LXI	D,PFTADR
	LXI	B,10
	LDIR
	jmp	floppy

; UNTERPROGRAMM FUR UMRECHNUNG HEX IN ASCII

HEXASC:
	MVI	L,'0'
HEXAS1:	CPI	10
	JRC	HEXAS2
	INR	L
	SBI	10
	JR	HEXAS1
HEXAS2:	ADI	'0'
	MOV	H,A
	RET

; ANZEIGEPUFFER LESE- / SCHREIBVORGANG

ANZEIG:
ANZDRV:	DB	' :'
ANZTRK:	DB	'  /'
ANZSEK:	DB	'   '
ANZRW:	DB	' '
;
; RAM - ZELLEN
;
ASEKAKT:
	DB	0	; SEKTOR 1..10 FUER ANZEIGE

; NACHFOLGENDE TABELLE ( BIS STI ) DARF IN IHREM AUFBAU NICHT
; VERAENDERT WERDEN, DA SIE MITTELS LDIR-BEFEHL DEM PHYSISCHEN
; DISKETTENTREIBER UEBERGEBEN WIRD

ADR:	DW	0	; ADRESSE DES BUFFERS FUER PHYSISCHE
			; FLOPPYROUTINE
MDRVAKT:
	DB	0	; DRIVE, DAS GELADEN IST
MTRKAKT:
	DB	0	; TRACK
MSIDAKT:
	DB	0	; SIDE
MSEKAKT:
	DB	0	; SEKTOR
LEN:	DB	3	; PHYSISCHE BLOCKLAENGE
ANZ:	DB	1	; ANZAHL ZU TRANSFERIERENDER SEKTOREN
STP:	DB	1	; ANZAHL STEPIMPULSE PRO SPUR
; FUER 40 SPUR-LW:
;STI:	DB	13*10	; SCHRITTZEIT FUER STEP
; FUER 80 SPUR-LW:
STI:	DB	4*10	; SCHRITTZEIT FUER STEP

DIRBCB:	DB	0FFH,0,0,0,0,0
	DW	0,0,DIRBUF
	DB	0,0,0

DTABCB:	DB	0FFH,0,0,0,0,0
	DW	0,0,DATBUF
	DB	0,0,0

DIRBUF:	DS	1024
DATBUF:	DS	1024

@dtbl	dw fdsd0,fdsd1
	dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0		; drives C-P non-existant


	end
