 	title	'CP/M plus DISI-EPROM/RAM-Disk driver'

;	Letzte Aenderung am 07.12.1986 (Joachim)

ja	equ	-1		; nicht veraendern
nein	equ	not ja		;

; DISI-Konfiguration
;
; Der Index gibt an, ob sich die Daten auf das erste oder das
; zweite Laufwerk beziehen.

prof181	equ	ja		; PROF-181X = ja, Sonstige = nein

disia	equ	0b8h		; DISI 1 Basisadresse
disib	equ	0ffh		; DISI 2 Basisadresse
disic	equ	0ffh		; DISI 3 Basisadresse
disid	equ	0ffh		; DISI 4 Basisadresse
				; Werden weniger als 4 Karten eingesetzt,
				; so erhalten die nicht benutzten Karten
				; die Portadresse 0FFh

bkap0	equ	32		; Bausteinkapazitaet in KB
amsk0	equ	00h		; Odermaske fuer Sektorregister beim Lesen/Schreiben
nr0	equ	16		; Anzahl der Bausteine
rw0	equ	ja		; RAM = ja, EPROM = nein

offs1	equ	8		; zweites Laufwerk beginnt ab diesem Baustein
bkap1	equ	32		; Bausteinkapazitaet in KB
amsk1	equ	00h		; Odermaske fuer Sektorregister beim Lesen/Schreiben
nr1	equ	0		; Anzahl der Bausteine, wenn 0 nur ein Laufwerk
rw1	equ	ja		; RAM = ja, EPROM = nein

;
; Ende der Konfiguration, ab hier bleibt die Datei unveraendert
;
;------------------------------------------------------------------------------------

kap0	equ	bkap0*nr0	; Kapazitaet des ersten Laufwerks
kap1	equ	bkap1*nr1	; Kapazitaet des zweiten Laufwerks

bnks0	set	1		; bestimme Anzahl der EPROM Bank's
sf0	set	0		; und Shiftfaktor
	if	bkap0 gt 32	; Wenn EPROM groesser als 32 KB, dann
bnks0	set	bkap0/16	; dann muss es gebankt sein.
sf0	set	2		; hier 27513
	endif			;
	if	bkap0 gt 64	;
sf0	set	3		; hier 27011
	endif			;

	if	nr1 ne 0	;
bnks1	set	1		; bestimme Anzahl der EPROM Bank's
sf1	set	0		; und Shiftfaktor
	if	bkap1 gt 32	; Wenn EPROM groesser als 32 KB, dann
bnks1	set	bkap1/16	; dann muss es gebankt sein.
sf1	set	2		; hier 27513
	endif			;
	if	bkap1 gt 64	;
sf1	set	3		; hier 27011
	endif			;
	endif



nrcard	set	0		; bestimme anzahl der karten
	if	disia ne 0ffh	;
nrcard	set	nrcard+1	;
	endif			;
	if	disib ne 0ffh	;
nrcard	set	nrcard+1	;
	endif			;
	if	disic ne 0ffh	;
nrcard	set	nrcard+1	;
	endif			;
	if	disid ne 0ffh	;
nrcard	set	nrcard+1	;
	endif			;

	dseg

	maclib	cpm3

	maclib	psys

	if	prof181
	maclib	hd64180
	else
	maclib	z80
	endif

	public	fdisi0

	if	nr1 ne 0
	public	fdisi1
	endif

	extrn	@adrv,@rdrv,@dma,@trk,@sect,@dbnk,@cbnk,@dtbl
	extrn	?bank

; bestimme Blockgroesse und Dir-Eintraege aus Kapazitaet

block0	set	1024
dirs0	set	32
	if	kap0 gt 96
dirs0	set	64
	endif
	if	kap0 gt 256
block0	set	2048
dirs0	set	128
	endif
	if	kap0 gt 512
dirs0	set	256
	endif
	if	kap0 gt 1024
dirs0	set	512
	endif

	if	nr1 ne 0
block1	set	1024
dirs1	set	32
	if	kap1 gt 96
dirs1	set	64
	endif
	if	kap1 gt 256
block1	set	2048
dirs1	set	128
	endif
	if	kap1 gt 512
dirs1	set	256
	endif
	if	kap1 gt 1024
dirs1	set	512
	endif
	endif

	; extended disk parameter header

	if	rw0
	dw	fwrite
	else
	dw	wprot
	endif
	dw	fread
	dw	flogin
	dw	finit
	db	0,0			
fdisi0	dph	0,dpbr0,0,kap0/(block0/1024)/4

	if	nr1 ne 0
	if	rw1
	dw	fwrite
	else
	dw	wprot
	endif
	dw	fread
	dw	flogin
	dw	finit
	db	1,0
fdisi1	dph	0,dpbr1,0,kap1/(block1/1024)/4
	endif

	cseg

dpbr0	dpb	128,(bkap0*8)/bnks0,nr0*bnks0,block0,dirs0,1,8000h

	if	nr1 ne 0
dpbr1	dpb	128,(bkap1*8)/bnks1,nr1*bnks1,block1,dirs1,0,8000h
	endif


fread:	pushix			; save indexregister
	call	setadr		; berrechne adresse in disi-floppy
	call	?bank		;
	inir			;
	lda	@cbnk		;
	call	?bank		;
	xra	a		;
	ldx	c,0		;
	outp	a		;
	popix			;
	ret			;

fwrite:	pushix			;
	call	setadr		; berechne adresse in disi-floppy
	call	?bank		;
	outir			;
	lda	@cbnk		;
	call	?bank		;
	xra	a		;
	ldx	c,0		;
	outp	a		;
	popix			;
	ret			;


	dseg			; Rest kann gebankt sein

finit:	lda	diflag		; DISI ok?
	ora	a		; NULL = false
	rnz			; ok!
	lxi	h,0		; ansonsten loesche Eintrag in
	shld	@dtbl   	; drivetable
	ret

wprot:
	mvi	a,02h		; write routine bei EPROM's beschraenkt
				; sich auf fehlermeldung.

flogin:				; kein login notwendig
	ret


setadr:				; setze dmabank und disi-adresse
				; eingang: @trk,@sekt
				;
	if	nr1 ne 0	; wenn zwei laufwerke vorhanden sind
	lda	@rdrv		; dann erfolgt die adressberechnung
	ora	a		; abhaengig vom laufwerk
	jrz	setad3		;
				;
				; ADRESSBERRECHNUNG FUER LAUFWERK 1
				;
	lda	@trk		; lade spur nummer
				;
	if	sf1 ne 0	; code nur notwendig, wenn banking EPROM
	mvi	b,sf1		; teile spur durch anzahl
setad4:	srlr	a		; der EPROM Bank's
	djnz	setad4		;
	endif			;
				; ok, in Akku steht Bausteinnummer
	adi	offs1		; addiere offset des zweiten lw's dazu
	mov	e,a		; rette Bausteinnummer nach E
				;
	if	nrcard ne 1	; code nur notwendig wenn mehr als eine karte
	srlr	a		; teile durch 16
	srlr	a		; um kartennummer
	srlr	a		; zu ermitteln
	srlr	a		;
	mov	l,a		; setze ix
	mvi	h,0		; auf portliste
	dad	h		;
	dad	h		;
	lxix	portlist	;
	xchg			;
	dadx	d		;
	xchg			;
				;
	else			; code nur notwendig wenn genau eine karte
	lxix	portlist	;
	endif			;
				; ok, ix zeigt auf portliste
	ldx	c,1		; waehle baustein aus (einer von acht)
	outp	e		;
	mov	a,e		; ermittle port fuer datenuebertragung
	ani	00001000b	;
	ldx	a,2		;
	jrz	setad5		;
	ldx	a,3		; 
setad5:	mov	c,a		;
	push	b		; rette portadresse
				;
	if	sf1 ne 0	; code nur notwendig, wenn gebankte EPROM's
	lda	@trk		; setze Bank im EPROM
	outp	a		; *** Achtung die oberen Bits muessen fuer EPROM
	endif			;     bedeutungslos sein
				;
	ldx	c,0		; setze sektor (setze implizit Bytecounter auf 0)
	lda	@sect		;
	ori	amsk1		; setze ungueltige adressleitungen
	outp	a		;
	pop	b		; lade Datenportadresse
				;
	mvi	b,128		;
	lhld	@dma		;
	lda	@dbnk		;
	ret			;
	endif

				; ADRESSBERRECHNUNG FUER LAUFWERK 0
setad3:				;
	lda	@trk		; lade spur nummer
				;
	if	sf0 ne 0	; code nur notwendig, wenn banking EPROM
	mvi	b,sf0		; teile spur durch anzahl
setad1:	srlr	a		; der EPROM Bank's
	djnz	setad1		;
	endif			;
				; ok, in Akku steht Bausteinnummer
	mov	e,a		; rette Bausteinnummer nach E
				;
	if	nrcard ne 1	; code nur notwendig wenn mehr als eine karte
	srlr	a		; teile durch 16
	srlr	a		; um kartennummer
	srlr	a		; zu ermitteln
	srlr	a		;
	mov	l,a		; setze ix
	mvi	h,0		; auf portliste
	dad	h		;
	dad	h		;
	lxix	portlist	;
	xchg			;
	dadx	d		;
	xchg			;
				;
	else			; code nur notwendig wenn genau eine karte
	lxix	portlist	;
	endif			;
				; ok, ix zeigt auf portliste
	ldx	c,1		; waehle baustein aus (einer von acht)
	outp	e		;
	mov	a,e		; ermittle port fuer datenuebertragung
	ani	00001000b	;
	ldx	a,2		;
	jrz	setad2		;
	ldx	a,3		; 
setad2:	mov	c,a		;
	push	b		; rette portadresse
				;
	if	sf0 ne 0	; code nur notwendig, wenn gebankte EPROM's
	lda	@trk		; setze Bank im EPROM
	outp	a		; *** Achtung die oberen Bits muessen fuer EPROM
	endif			;     bedeutungslos sein
				;
	ldx	c,0		; setze sektor (setze implizit Bytecounter auf 0)
	lda	@sect		;
	ori	amsk0		; setze ungueltige adressleitungen
	outp	a		;
	pop	b		; lade Datenportadresse
				;
	mvi	b,128		;
	lhld	@dma		;
	lda	@dbnk		;
	ret			;

portlist:			; portadressen fuer 4 disi karten
	if	disia ne 0ffh	;
	db	disia		;
	db	disia+1		;
	db	disia+2		;
	db	disia+3		;
	endif			;
	if	disib ne 0ffh	;
	db	disib		;
	db	disib+1		;
	db	disib+2		;
	db	disib+3		;
	endif			;
	if	disic ne 0ffh	;
	db	disic		;
	db	disic+1		;
	db	disic+2		;
	db	disic+3		;
	endif			;
	if	disid ne 0ffh	;
	db	disid		;
	db	disid+1		;
	db	disid+2		;
	db	disid+3		;
	endif			;

	end
