DataMuseum.dk

Presents historical artifacts from the history of:

CP/M

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about CP/M

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦66063eaf4⟧ TextFile

    Length: 19968 (0x4e00)
    Types: TextFile
    Names: »BIOSKRNL.Z80«

Derivation

└─⟦7303e23ba⟧ Bits:30003507 JET80 System diskette
    └─ ⟦this⟧ »BIOSKRNL.Z80« 
└─⟦a844860b7⟧ Bits:30002858 CP/M Plus (tm) Version 3.0 for JET80
    └─ ⟦this⟧ »BIOSKRNL.Z80« 
└─⟦c10cc8855⟧ Bits:30002859 CP/M Plus med Hit & Dit filoverførsel for JET80
    └─ ⟦this⟧ »BIOSKRNL.Z80« 

TextFile

	TITLE	'BIOSKRNL.Z80   ROOT TO BIOS. CP/M 3.0'
;****************************************************************
;*      THE TOTAL SYSTEM CONSISTS OF:                           *
;*      BIOSKRNL.Z80    ROOT                                    *
;*      BOOT.Z80        BOOT-MODULE                             *
;*      CHARIO.Z80      CHARACTER-I/O-MODULE                    *
;*      DRIVES.ASM      DISK-DEFINITON-MODULE (WDRIVES/FDRIVES) *
;*      EXTMEM.Z80      EXTERNEL MEMORY-MODULE                  *
;*      SCB.REL         SYSTEM VARIABLES                        *
;*      IOS.Z80         PORT ADDRESSES                          *
;****************************************************************
; LATEST CHANGE: 1984-06-20.  PSW.
; BIOSREVISION D.
	.Z80
	PAGE	42
; EXTERNAL VARIABELS
	EXTRN	@COVEC,@CIVEC,@AOVEC	; I/O REDIRECTION VECTORS
	EXTRN	@AIVEC,@LOVEC		;       - " -
	EXTRN	@MXTPA			; MAX TPA IN USER BANK
	EXTRN	@BNKBF			; COMMON 128 BYTE BUFFER

; INIT
	EXTRN	?PATCH,?INIT			; 
	EXTRN	?LDCCP,?RLCCP		; LOAD & RELOAD CCP

; USER DEFINED CHARACTER I/O ROUTINS
	EXTRN	?CI,?CO,?CIST,?COST	; 
	EXTRN	?CINIT,INISTM		; 
	EXTRN	@CTBL			; 

; DISK 
	EXTRN	@DTBL			; POINTER TABLE
	ENTRY	@ADRV,@RDRV,@TRK,@SECT	; DISKPARAMETERS
	ENTRY	@DMA,@DBNK,@CNT		;     - " -	

; MEMORY MODULE
	ENTRY	@CBNK,BNKMSK		; CURRENT BANK
	ENTRY	?PMSG   		; WRITES MESSAGES

; EXTERNAL LABLES TO BIOS-CALLS
	ENTRY	?BOOT,?WBOOT,?CONST,?CONIN,?CONO,?LIST,?AUXO,?AUXI
	ENTRY	?HOME,?SLDSK,?STTRK,?STSEC,?STDMA,?READ,?WRITE
	ENTRY	?LISTS,?SCTRN
	ENTRY	?CONOS,?AUXIS,?AUXOS,?DVTBL,?DEVIN,?DRTBL
	ENTRY	?MLTIO,?FLUSH,?MOV,?TIM,?BNKSL,?STBNK,?XMOV

; EXTERNAL LABLE TO USERFUNCTION
	EXTRN	?USERF

; INTERRUPT-VECTORS
	ENTRY	SIO1IV,SIO2IV,DMAIRV,CTCIRV,PIOIRV
	ENTRY	INTVECT

; INTERRUPT-DRIVEN ROUTINES
	EXTRN	KBDIRQ,CLKIRQ,PIOGAI,PIOGBI,UNKINT
	PAGE	

TRUE	EQU	-1
FALSE	EQU	NOT TRUE
BIOSRV	EQU	8426H		; BIOS-REVISION.
BOTFLG	EQU	0C000H		; BOOT-FLAGG

DMA	EQU	18H		; DMA.
				; DMA-COMMANDS
DMRSET	EQU	0C3H		; SOFTWARE RESET
DMENAB	EQU	087H		; ENABLE DMA
DMDISA	EQU	083H		; DISABLE DMA

BNKMUX	EQU	1BH		; BANK-DMA-MULTIPLEXER
DMBK11	EQU	00000000B	; BANK1 --> BANK1
DMBK00	EQU	00001000B	; BANK0 --> BANK0
DMBK10	EQU	00010000B	; BANK1 --> BANK0
DMBK01	EQU	00011000B	; BANK0 --> BANK1
BANK1	EQU	00000000B	; BANK1 (64K FOR CPU)
BANK0	EQU	00100000B	; BANK0 (48K FOR CPU)

CR	EQU	13
LF	EQU	10
BELL	EQU	7
CTLQ	EQU	'Q'-'@'
CTLS	EQU	'S'-'@'

MB$XONXOFF	EQU	00010000B	; XON/XOFF PROTOCOLL ON.

JPOP	EQU	0C3H		; Z80 JUMP INSTRUCTION

CCP	EQU	100H		; LOAD ADDRESS FOR CCP
	PAGE
	CSEG
;**********************************************************
;*              BIOS: JUMP VECTORS                        *
;**********************************************************

?BOOT:	JP	BOOT		; 
?WBOOT:	JP	WBOOT		; 

?CONST:	JP	CONST		; 
?CONIN:	JP	CONIN		; 
?CONO:	JP	CONOUT		; 
?LIST:	JP	LIST		; 
?AUXO:	JP	AUXOUT		; 
?AUXI:	JP	AUXIN		; 

?HOME:	JP	HOME		; 
?SLDSK:	JP	SELDSK		; 
?STTRK:	JP	SETTRK		; 
?STSEC:	JP	SETSEC		; 
?STDMA:	JP	SETDMA		; 
?READ:	JP	READ		; 
?WRITE:	JP	WRITE		; 

?LISTS:	JP	LISTST		; 
?SCTRN:	JP	SECTRN		; 

?CONOS:	JP	CONOST		; 
?AUXIS:	JP	AUXIST		; 
?AUXOS:	JP	AUXOST		; 
?DVTBL:	JP	DEVTBL		; 
?DEVIN:	JP	?CINIT		; IN CHARIO.Z80

?DRTBL:	JP	GETDRV		; 
?MLTIO:	JP	MULTIO		; 
?FLUSH:	JP	FLUSH		; 

?MOV:	JP	?MOVE		; 
?TIM:	JP	RETURN		; NOT INSTALLED
?BNKSL:	JP	BNKSEL		; 
?STBNK:	JP	SETBNK		; 
?XMOV:	JP	?XMOVE		; 

	JP	?USERF		; IN EXTMEM.Z80
	JP	RETURN		; 
	JP	RETURN		; 
	NOP			; GIVE CORRECT START FOR INT.VECTORS.
	PAGE
;**********************************************************
;*		  INTERRUPT VECTORS			  *
;**********************************************************
INTVECT	EQU	$			; INTERRUPT VECTOR ADDRESS

PIOIRV	EQU	$			; PIO BASE INTERRUPT VECTOR
	DEFW	PIOGAI			; GRAPHIC SCREEN READY
	DEFW	PIOGBI			; GRAPHIC KEY BOARD 

CTCIRV	EQU	$			; CTC BASE INTERRUPT VEKTOR
	DEFW	UNKINT			; 
	DEFW	UNKINT			; 
	DEFW	UNKINT			; 
	DEFW	CLKIRQ			; (10 Hz TICK)

SIO1IV	EQU	$			; SIO1 BASE INTERRUPT VECTOR
	DEFW	KBDIRQ			; KEYBOARD INT.
	DEFW	KBDIRQ			; 
	DEFW	KBDIRQ			; 
	DEFW	KBDIRQ			; 
	DEFW	KBDIRQ			; 
	DEFW	KBDIRQ			; 
	DEFW	KBDIRQ			; 
	DEFW	KBDIRQ			; 

SIO2IV	EQU	$			; SIO2 BASE INTERRUPT VECTOR
	DEFW	UNKINT			; 
	DEFW	UNKINT			; 
	DEFW	UNKINT			; 
	DEFW	UNKINT			; 
	DEFW	UNKINT			; 
	DEFW	UNKINT			; 
	DEFW	UNKINT			; 
	DEFW	UNKINT			; 

DMAIRV	EQU	$			; DMA BASE INTERRUPT VECTOR
	DEFW	UNKINT			; 
	DEFW	UNKINT			; 
	DEFW	UNKINT			; 
	DEFW	UNKINT			; 
	PAGE

; BOOT
	DSEG			;; CODE IN BANK0

BOOT:	DI			;; 
	LD	SP,BOOT$STACK
	CALL	?PATCH		;; PATCH IO-PART FROM LOADER.
	LD	C,0		;; INIT ALL 16 CHARACTER DEVICES
C$INIT$LOOP:
	PUSH	BC
	CALL	?CINIT		;; INIT CHARACTER DEV.
	POP	BC
	INC	C
	LD	A,C
	CP	16
	JR	NZ,C$INIT$LOOP
	CALL	?INIT		;; INIT THE OTHERS

	LD	A,(BOTFLG)	;; SHALL A: BE WINCHESTER ?
	AND	A
	JR	Z,GOON		;; NO...JUMP.
	LD	HL,(@DTBL+4)	;;  GET  C:
	LD	DE,(@DTBL+2)	;;       B:
	LD	BC,(@DTBL)	;;       A:
	LD	(@DTBL),DE	;; B: --> A:
	LD	(@DTBL+2),HL	;; C: --> B:
	LD	(@DTBL+4),BC	;; A: --> C:

; GO ON INIT 16 DISK UNITS.
 
GOON:	LD	BC,16*256+0	;; B=NUMBERS. C= LOG. DRIVE
	LD	HL,@DTBL	;; DRIVE-TABLE

D$IN$LOOP:
	PUSH	BC		;; SAVE NO. & DRIVE
	LD	E,(HL)
	INC	HL
	LD	D,(HL)		;; DE=ADDRESS TO DPH
	INC	HL
	LD	A,E		;; DOES DRIVE EXIST?
	OR	D
	JR	Z,D$IN$NEXT	;; NO...JUMP.
	PUSH	HL		;; SAVE HL 
	EX	DE,HL
	DEC	HL
	DEC	HL
	LD	A,(HL)		;; A=CONTROLLER RELATIVE ADDRESS
	LD	(@RDRV),A
	LD	A,C		;; LOGICAL ADDRESS.
	LD	(@ADRV),A
	DEC	HL
	LD	D,(HL)
	DEC	HL
	LD	E,(HL)		;; DE=INIT ADDRESS
	EX	DE,HL		;; 
	CALL	IPCHL		;; JUMP TO INIT.
	POP	HL		;; HL=DPH POINTER

D$IN$NEXT:
	POP	BC		;; B=NUMBERS. C=DRIVE
	INC	C		;; NEXT DRIVE #
	DJNZ	D$IN$LOOP	;; NEXT DPH-POINTER.
	JP	BOOT$1

	CSEG			; BANK 1.

BOOT$1:
	CALL	SET$JUMPS	; SET JUMPVECTORS
	CALL	?LDCCP		; READ CCP.COM FROM DISK
	JP	CCP		; 

	; WBOOT

WBOOT:
	LD	SP,BOOT$STACK
	CALL	SET$JUMPS	; INIT PAGE ZERO
	CALL	?RLCCP		; REREAD CCP.COM
	JP	CCP		; 

SET$JUMPS:
	LD	A,1		; SELECT BANK 1
	CALL	?BNKSL
	LD	A,JPOP		; Z80 JP OPCODE
	LD	HL,?WBOOT	; WARM BOOT ENTRY POINT
	LD	(0),A		; BIOS WARM START ENTRY
	LD	(1),HL
	LD	HL,(@MXTPA)	; BDOS ENTRY POINT
	LD	(5),A
	LD	(6),HL
RETURN:	RET			; 

	DS	64
BOOT$STACK	EQU	$

; DEVTBL --  RETURNS THE ADDRESS TO CHARACTER DEVICE TABLE

DEVTBL:	LD	HL,@CTBL
	RET

; GETDRV --  RETURNS THE ADDRESS TO DRIVE TABLE

GETDRV:	LD	HL,@DTBL
	RET
	PAGE
;**********************************************************
;*               CHARACTER I/O- ROUTINES                  *
;**********************************************************

; CONOUT -- CONSOLE OUTPUT.  SENDS CHAR IN (C) TO ALL
; 	    CHOOSEN DEVICES.

CONOUT:	LD	HL,(@COVEC)	; GET CONSOLE OUTPUT BIT VECTOR
	JR	OUT$SCAN


; AUXOUT --  AUXILLIARY OUTPUT.  SENS CHAR IN (C) TO ALL
; 	     CHOOSEN DEVICES.

AUXOUT:	LD	HL,(@AOVEC)	; GET AUX OUTPUT BIT VECTOR
	JR	OUT$SCAN


; LIST -- LIST OUTPUT.  SENDS CHAR IN (C) TO ALL
; 	  CHOOSEN DEVICES.

LIST:	LD	HL,(@LOVEC)	; GET LIST OUTPUT BIT VECTOR
				; AND DO OUT$SCAN

OUT$SCAN:
	LD	B,0		; START WITH DEVICE 0.
CO$NEXT:
	ADD	HL,HL		; SHIFT NEXT BIT BIT
	JR	NC,NO$OUT$DEV	; JUMP IF NO CARRY
	PUSH	HL		; SAVE THE VECTOR AND
	PUSH	BC		; COUNTER AND CHAR.
CO$OUT$RDY:
	CALL	COSTER
	OR	A		; READY ?
	JR	Z,CO$OUT$RDY	; NO...JUMP
	POP	BC		; B=COUNTER C=CHAR
	PUSH	BC		; SAVE
	CALL	?CO		; SEND CHAR IF DEVICE IS CHOOSEN
	POP	BC		; B=COUNTER C=CHAR
	POP	HL		; BIT VECTOR
NO$OUT$DEV:
	INC	B		; NEXT DEVICE #
	LD	A,H		; TEST IF ANY DEVICES LEFT
	OR	L
	JR	NZ,CO$NEXT	; YES...JUMP
	RET


; CONOST -- CONSOLE OUTPUT STATUS. RETURNS TRUE IF ALL
; 	    CHOOSEN CONSOLE OUTPUT DEVICES ARE READY.

CONOST:	LD	HL,(@COVEC)	; GET CONSOLE OUTPUT BIT VECTOR
	JR	OST$SCAN


; AUXOST -- AUXILIARY OUTPUT STATUS. RETURNS TRUE IF ALL
; 	    CHOOSEN AUX OUTPUT DEVICES ARE READY.

AUXOST:	LD	HL,(@AOVEC)	; GET AUX OUTPUT BIT VECTOR
	JR	OST$SCAN


; LISTST -- LIST OUTPUT STATUS. RETURNS TRUE IF ALL
; 	    CHOOSEN LIST OUTPUT DEVICES ARE READY.

LISTST:	LD	HL,(@LOVEC)	; GET LIST OUTPUT BIT VECTOR.


OST$SCAN:
	LD	B,0		; START WITH DEVICE 0
COS$NEXT:
	ADD	HL,HL		; SHIFT OUT NEXT BIT
	PUSH	HL		; SAVE THE VECTOR
	PUSH	BC		; B=COUNTER C=CHAR
	LD	A,-1		; SET DEVICE READY
	CALL	C,COSTER	; GET STATUS IF DEVICE CHOOSEN
	POP	BC		; B=COUNTER C=CHAR
	POP	HL		; HL=VECTOR
	OR	A		; TEST IF DEVICE READY.
	RET	Z		; IF ALL NOT READY, RETURN FALSE.
	INC	B		; NEXT DEVICE
	LD	A,H		; CHECK IF MORE CHOOSEN DEVICES
	OR	L
	JR	NZ,COS$NEXT	; YES...JUMP
	OR	0FFH		; ALL CHOOSEN DEVICES READY
	RET			; RETURN TRUE

; CHECK IF OUTPUT DEVICE READY (XON/XOFF SUPPORT).

COSTER:	LD	L,B		; CHANGE DEVICE # TO 16 BITS
	LD	H,0		; HL=DEV#
	PUSH	HL		; 
	ADD	HL,HL		; OFFSET IN DEVICE-TABLE
	ADD	HL,HL
	ADD	HL,HL		; HL=HL*8
	LD	DE,@CTBL+6	; DE= MODE BYTE FØR DEV 0
	ADD	HL,DE		; HL=RÆTT MODE BYTE
	LD	A,(HL)		; GET MODE BYTE
	AND	MB$XONXOFF	; XON/XOFF PROTOCOLL?
	POP	HL		; HL=DEVICE #
	JP	Z,?COST		; NO XON/XOFF...JUMP
	LD	DE,XOFFLIST
	ADD	HL,DE		; HL=PLACE IN XOFFLIST
	LD	C,0		; FLAGSTATUS FOR ^C, ^S, ^Q ONLY
	CALL	CISTL
	LD	A,(HL)
	CALL	NZ,CIL
	CP	CTLQ
	JR	NZ,NOT$Q
	LD	A,-1		; SET READY-FLAG
NOT$Q:	CP	CTLS		; CTL-S?
	JR	NZ,NOT$S	; NO...JUMP
	LD	A,0		; CLEAR FLAG
NOT$S:	LD	(HL),A		; SAVE FLAG
	CALL	COST1		; GET OUTPUT STATUS
	AND	(HL)		; AND MASK WITH XON/XOFF FLAG
	RET			; AND RETURN IT AS STATUS

CISTL:	PUSH	BC		; GET INPUT STATUS WITH (BC) & (HL)
	PUSH	HL
	CALL	?CIST
	POP	HL
	POP	BC
	OR	A
	RET

COST1:	PUSH	BC		; GET OUTPUT STATUS, SAVE (BC) & (HL)
	PUSH	HL
	CALL	?COST
	POP	HL
	POP	BC
	OR	A
	RET

CIL:	PUSH	BC		; GET INPUT AND SAVE (BC) & (HL)
	PUSH	HL
	CALL	?CI
	POP	HL
	POP	BC
	RET

; CONST -- CONSOLE INPUT STATUS. RETURNS TRUE IF ANY CHOOSEN
; 	   CONSOLE INPUT DEVICE HAS A CHAR AVAILABLE.

CONST:	LD	HL,(@CIVEC)	; GET CONSOLE INPUT BIT VECTOR
	JR	IST$SCAN

; AUXIST -- AUXILIARY INPUT STATUS. RETURNS TRUE IF ANY CHOOSEN
; 	    AUX INPUT DEVICE HAS A CHAR AVAILABLE.

AUXIST:	LD	HL,(@AIVEC)	; GET AUX INPUT BIT VECTOR

IST$SCAN:
	LD	BC,0		; START WITH DEVICE 0
				; CREG = 0 = FLAG, STATUS CALL ONLY
CIS$NEXT:
	XOR	A		; SET DEVICE NOT READY
	ADD	HL,HL		; SHIFT OUT ONE BIT
	CALL	C,CISTL		; CHECK STATUS ON THIS DEVICE
	OR	A		; IF ANY READY RETURN TRUE.
	RET	NZ
	INC	B		; NEXT DEVICE #
	LD	A,H		; CHECK IF ANY MORE DEV.
	OR	L
	JR	NZ,CIS$NEXT
	XOR	A		; ALL CHOOSEN NOT READY. FALSE
	RET

; CONIN -- CONSOLE INPUT. RETURNS  CHAR FROM FIRST READY
; 	   CONSOLE DEVICE.

CONIN:	LD	HL,(@CIVEC)	; GET CONSOLE BIT VECTOR
	JR	IN$SCAN

; AUXIN -- AUXILIARY INPUT. RETURNS CHAR FROM FIRST READY
; 	   AUX INPUT DEVICE.

AUXIN:	LD	HL,(@AIVEC)	; GET AUX BIT VECTOR

IN$SCAN:
	PUSH	HL		; SAVE BIT VECTOR
	LD	B,0		; START WITH DEVICE 0
	LD	C,-1		; CREG = FF = STATUS CALL FOR INPUT
CI$NEXT:
	XOR	A		; SET NO CHAR
	ADD	HL,HL		; SHIFT OUT ONE BIT
	CALL	C,CISTL		; CHECK IF DEVICE HAS A CHAR
	OR	A		; CHAR?
	JR	NZ,CI$RDY	; YES...JUMP
	INC	B		; TEST NEXT DEVICE
	LD	A,H
	OR	L
	JR	NZ,CI$NEXT	; 
	POP	HL		; HL=BIT VECTOR
	JR	IN$SCAN		; LOOP UNTIL GOT A CHAR
CI$RDY:	POP	HL		; HL=BIT VECTOR
	JP	?CI		; GET INPUT FROM DEVICE # IN B.
	PAGE
;**********************************************************
;*                    SUBROUTINES                         *
;**********************************************************

IPCHL:	JP	(HL)		; VECTOR-CALL

?PMSG:				; WRITES MESSAGE @(HL) DETERM.
				; WITH DEFB 0.
	LD	A,(HL)		; GET NEXT BYTE
	OR	A		; IS IT 0 ?
	RET	Z		; YES...RETURN
	PUSH	HL		; SAVE REGISTERS
	PUSH	DE
	PUSH	BC
	LD	C,A		; CHAR IN (C)
	CALL	?CONO		; WRITE
	POP	BC
	POP	DE
	POP	HL
	INC	HL		; HL-->NEXT BYTE
	JR	?PMSG		; START OVER AGAIN

; ?MOVE -- BLOCKMOVE MEMORY --> MEMORY
; IN:			HL = TO ADDRESS
;			DE = FROM ADDRES
;			BC = COUNTER.
; OUT:			HL & DE POINTING TO THE NEXT BYTES
;                               THAT FOLLOWS THE MOVE.

?MOVE:	LD	A,B		; IS IT ZERO-MOVE?
	OR	C
	RET	Z		; YES...QUIT
	LD	A,(BNKFLG)	; IS ?XMOVE INVOLVED?
	AND	A
	JR	NZ,MOVE1	; YES...JUMP
	EX	DE,HL		; EXCHANGE ADDRESSES TO FIT
	LDIR			; THIS INSTRUCTION.
	EX	DE,HL		; GET THEM BACK.
	RET
MOVE1:	XOR	A		; ZERO ?XMOVE-FLAG
	LD	(BNKFLG),A
	LD	(SRCADR),DE	; SET SOURCE-ADDRESS IN DMA-TABLE
	LD	(DSTADR),HL	; SET DEST-ADDRESS IN DMA-TABLE
	ADD	HL,BC		; HL= END-DEST-ADDRESS.
	PUSH	HL		;     SAVED.
	EX	DE,HL		;
	ADD	HL,BC		; HL= END-SOURCE-ADDRESS
	PUSH	HL		;      SAVED.
	DEC	BC		; REDUCE BLOCK LENGTH WITH 1
	LD	(LENGTH),BC	; CHECK FOR THE DMA COMMAND
	LD	A,B
	OR	C
	LD	A,11001101B	; IF NOT ONE BYTE SET BURST MODE
	JR	NZ,MOVE2
	LD	A,10001101B	; ELSE SET BYTE MODE.
MOVE2:	LD	(MODE),A	; SAVE THE MODE
	LD	HL,(DSTBNK)	;
	LD	A,H		; DEST-BANK IN A.
	RLA			; SHIFT OUT LEFT
	OR	L		; ADD ON SOURCE-BANK.
	AND	00000011B	; MASK ANY FAULTS.
	LD	L,A		; 
	LD	H,0		; PUT THE CODE I HL
	LD	DE,BNKTBL	; OFFSET IN THE TABLE
	ADD	HL,DE		; POINT TO THE RIGHT BYTE
	LD	A,(HL)		; GET IT.
	LD	HL,BNKMSK	; ADD ON BANKMASK
	OR	(HL)
	LD	HL,DMATBL	; POINT TO THE DMA-TABLE.
	DI			; SHUT UP FOR A MOMENT.
	OUT	(BNKMUX),A	; START THE DMA
	CALL	INISTM
	LD	A,B		;
	OR	C
	JR	Z,MOVE4
MOVE3:	IN	A,(DMA)		; READ STATUS
	AND	00100000B	; IS IT READY?
	JR	NZ,MOVE3
MOVE4:	LD	A,DMDISA	; DISABLE DMA
	OUT	(DMA),A
	EI			; SPEAK AGAIN
	POP	DE		; GET THE PARAMETERS BACK
	POP	HL
	LD	BC,0		; COUNTER=0
	RET

; ?XMOVE -- SETS CORRECT BANKS FOR DATA TRANSFERES.
; IN:			B = TO-BANK
;			C = FROM-BANK
; OUT:			NONE.
;

?XMOVE:
	LD	A,TRUE
	LD	(BNKFLG),A	; MARK ?XMOVE
	LD	(DSTBNK),BC	; GIVES (C) IN TO-BANK
				; AND (B) IN FROM-BANK.
	RET

; BNKSEL -- BANKSELECT.
; IN:			A = MEMORY BANK.
;
                                
BNKSEL:	LD	(@CBNK),A	; SAVE CURRENT BANK
	AND	1		; MASK 
	PUSH	HL		; SAVE 
	LD	HL,BNKMSK	; 
	LD	A,BANK0		; START WITH BANK 0.
	JR	Z,BNK1		; BANK0 ?  YES...JUMP
	LD	A,BANK1		; SET BANK 1.
BNK1:	DI			; NOTHING CRAZY MAY HAPPEN NOW
	LD	(HL),A
	OUT	(BNKMUX),A	; SEND TO BANK SELECT PORT
	POP	HL
	EI			; IT WORKED.
	RET
                                
       	PAGE
	DSEG			;; BANK 0.
;***********************************************************
;*	            DISK-DRIVE-ROUTINES                    *
;***********************************************************

; SELDSK -- SELECT DISK DRIVE. DOES THE LOGIN-PROCEDURE FOR 
;           THE DRIVE IF IT IS THE FIRST TIME SELECT.
; IN:			C = SELECTED DRIVE.
;			E = BIT0 IS 0 IF NOT SELECTED BEFORE
; OUT:			HL = 0 IF SELECTED DRIVE DOES NOT EXIST
;			HL = @DPH IF SELECTED DRIVE EXISTS

SELDSK:	LD	A,C
	LD	(@ADRV),A	;; SAVE #
	LD	L,C		;; CREATE INDEX
	LD	H,0
	ADD	HL,HL		;; HL=2*DRIVE #TO OFFSET
	LD	BC,@DTBL	;; POINT TO DRIVE-TABLE-HEAD
	ADD	HL,BC		;; HL=CORRECT VECTOR IN @DTBL
	LD	A,(HL)		;; GET DPH-POINTER
	INC	HL
	LD	H,(HL)
	LD	L,A		;; HL=DPH-POINTER
	OR	H		;; SET Z-FLAG AND
	RET	Z		;; RETURN IF NO DRIVE
	LD	A,E
	AND	1		;; FIRST SELECT?
	RET	NZ		;; NO...RETURN
	PUSH	HL		;; SAVE DPH-POINTER
	EX	DE,HL
	LD	HL,-2		;; GET (DPH-2)
	ADD	HL,DE
	LD	A,(HL)
	LD	(@RDRV),A	;; SAVE THE CONTROLLER RELATIVE DRIVE#
	LD	HL,-6		;; GET THE LOGIN-VECTOR
	ADD	HL,DE
	LD	A,(HL)
	INC	HL
	LD	H,(HL)
	LD	L,A
	CALL	IPCHL		;; DO LOGIN
	POP	HL		;; HL=DPH-POINTER
	RET
	PAGE
; HOME -- HOME SELECTED DRIVE.  DO SETTRK (0).

HOME:	LD	BC,0		;; TRACK=0

; SETTRK --  SET TRACK ADDRESS.
; IN:			BC = TRACK ADDRESS
; OUT:			@TRK = TRACK ADDRESS

SETTRK:	LD	(@TRK),BC	;; SAVE TRACK ADDRESS
	RET


; SETSEC -- SET SECTOR ADDRESS.
; IN:			BC = SECTOR ADDRESS
; OUT:			@SECT = SECTOR ADDRESS

SETSEC:	LD	(@SECT),BC	;; SAVE SECTOR ADDRESS
	RET

; SETDMA -- SET DIRECT MEMORY ACCESS DISK ADDRESS.
; IN:			BD = DMA ADDRESS
; OUT:			@DMA = DMA ADDRESS
;			@DBNK = @CBNK

SETDMA:	LD	(@DMA),BC	;; SET GLOBAL DMA ADDRESS
	LD	A,(@CBNK)	;; DEFAULT DMA BANK IS CURRENT BANK
				;; GET CURRENT BANK & DO SETBNK

; SETBNK -- SET DISK I/O MEMORY BANK.
; IN:			A = DISK BANK #
; OUT:			@DBNK = DISK BANK #

SETBNK:
	LD	(@DBNK),A	;; SET DISK DMA BANK
	RET

; SECTRN -- SECTOR TRANSLATE. TRANSLATE LOGICAL SECTOR NUMBER TO
; PHYSICAL SECTOR NUMBER.
; IN:			BC = LOGICAL SECTOR #
;			DE = POINTING TO TRANS TABLE
;			     (0 IF NONE)
; OUT:			HL = PHYSICAL SECTOR #.

SECTRN:	LD	L,C		;; 
	LD	H,B		;; HL=CP/M SECTOR # (RELATIVE 0)
	INC	HL		;; HL=   -"-        (RELATIVE 1)
	LD	A,D		;; IS DE=0
	OR	E
	RET	Z		;; YES...RETURN, NO TRANS TABLE
	DEC	HL		;; HL= CP/M SECTOR # (RELATIVE 0)
	ADD	HL,DE		;; HL=INDEX IN TRANS TABLE
	LD	L,(HL)		;; TRANSLATE TO SECTOR # FROM TABLE
	LD	H,0		;; 8 BITS VALUE
	RET

; READ -- READS PHYSICAL SECTOR FROM SELECTED DISK.
; IN:			NONE
; OUT:			A = 0 NO ERROR.
;			A = 1 IF ERROR.
;			A = 0FFH IF MEDIA CHANGE.

READ:	LD	DE,-8		;; INDEX OFFSET TO READ-ROUTINE
	PUSH	DE		;; ON THE STACK
	JR	RW$COMMON	;; READ-WRITE-GEMENSAM.


; WRITE -- WRITES PHYSICAL SECTOR ON SELECTED DISK.
; IN:			C = DEBLOCKING-CODE
; OUT:			A = 0 NO ERRORS.
;			A = 1 PHYSICAL ERROR.
;			A = 2 DISK READ-ONLY
;			A = 0FFH IF MEDIA CHANGE.

WRITE:	LD	DE,-10		;; INDEX OFFSET TO WRITE-ROUTINE
	PUSH	DE		;; ON THE STACK

RW$COMMON:
	LD	HL,(@ADRV)	;; GET DRIVE #
	LD	H,0
	ADD	HL,HL		;; HL=2*DRIVE#
	LD	DE,@DTBL
	ADD	HL,DE
	LD	A,(HL)
	INC	HL
	LD	H,(HL)
	LD	L,A		;; HL=DPH
	POP	DE		;; DE=READ/WRITE
	PUSH	HL		;; SAVE DPH-ADDRESS 
	ADD	HL,DE		;; HL=READ/WRITE IN DPH
	LD	A,(HL)
	INC	HL
	LD	H,(HL)
	LD	L,A		;; HL=READ/WRITE-VECTOR
	POP	DE		;; DE=DPH
	DEC	DE
	DEC	DE
	LD	A,(DE)
	LD	(@RDRV),A	;; A=CONTROLLER RELATIVE DRIVE#
	INC	DE		;; BACK TO DPH
	INC	DE
	JP	(HL)		;; DO THE ROUTINE IN EXTMEM.Z80

; MULTIO -- SET MULTIPLE SECTOR COUNT.
; IN:			A = SECTOR COUNT.
; OUT:			@CNT = MULTIPLE SECTOR COUNT

MULTIO:	LD	(@CNT),A	;; SAVE THE COUNTER.
	RET

; FLUSH --
; NOT INSTALLED.

FLUSH:	XOR	A		;; RETURN NO ERRORS.
	RET
	PAGE
;********************************************************
;*                     VARIABLES                        *
;********************************************************


	CSEG			; MUST BE IN BANK1

@ADRV:	DEFS	1		; SELECTED DISK DRIVE #
@RDRV:	DEFS	1		; CONTROLLER RELATIVE DISK DRIVE#
@TRK:	DEFS	2		; TRACK #
@SECT:	DEFS	2		; SECTOR #
@DMA:	DEFS	2		; DMA ADDRESS
@CNT:	DEFB	0		; RECORD COUNT FOR MULTISECTOR I/O
@DBNK:	DEFB	0		; BANK FOR DMA OPERATIONS
@CBNK:	DEFB	0		; BANK FOR PROCESSOR OPERATIONS
BNKMSK:	DEFB	BANK0		; MASK FOR PROC-/DMA-OPERATIONS.

BNKFLG:	DEFB	0		; FLAG FOR ?XMOV
DSTBNK:	DEFS	1		; DEST-BANK FOR ?XMOVE-?MOVE
SRCBNK:	DEFS	1		; SOURCE-BANK FOR ?XMOVE-?MOVE

BNKTBL:	DEFB	DMBK00		; BANK0 --> BANK0
	DEFB	DMBK10		; BANK1 --> BANK0
	DEFB	DMBK01		; BANK0 --> BANK1
	DEFB	DMBK11		; BANK1 --> BANK1

DMATBL:	DEFB	17,DMA		; 17 BYTES TO DMA
	DEFB	DMDISA		; DISABLE DMA
	DEFB	01111101B	; CR1A: BLOCKLENGTH LOW o. HI FOLLOWS,
				; PORT A START ADDRESS LOW  o. HI
				; FOLLOWS A->B, TRANSFER.
SRCADR:	DEFS	2		; SORCE-ADDRESS (PORT A)
LENGTH:	DEFS	2		; BLOCKLENGTH - 1.
	DEFB	00010100B	; CR1B: PORT ADDR. INC. PORT A-MEMORY.
	DEFB	00010000B	; CR1B: PORT ADDR. INC. PORT B-MEMORY
MODE:	DEFS	1		; CR2B:   BURST/BYTE-MODE
DSTADR:	DEFS	2		; DEST-ADDRESS (PORT B)
	DEFB	10000010B	; CR2A: STOP END-OF-BLOCK
	DEFB	11001111B	; CR2D: LOAD STARTADRESSES FOR BOTH
				; PORTS AND ZERO THE COUNTER.
	DEFB	10001011B	; CR2D: ZERO STATUS-BITS
	DEFB	10110011B	; CR2D: FORCE READY.
	DEFB	DMENAB		; ENABLE DMA
	DEFB	10111111B	; CR2D: SET NEXT READ STATUS.

	DEFB	0		; TABLE END.

XOFFLIST:	DEFB	-1,-1,-1,-1,-1,-1,-1,-1
		DEFB	-1,-1,-1,-1,-1,-1,-1,-1

	END
«eof»