;
; General blocked disk handler
;  BASED IN PART ON MAGNET-SUPERBRAIN by epg
;
;   00.00 04/04/81 rlr - it begins
;   00.01 05/22/81 rlr - and we try again
;   00.02 06/01/81 RLR - release changes
;   00.03 06/11/81 rlr - fix release changes
;   00.04 06/18/81 KRS - FIX ERROR CODE PASS-THRU
;   00.05 08/20/81 hal - misc corrections
;   00.06 09/09/81 RLR - ADD GETBUF/MKEMTY AS ENTRIES
;   00.07 10/01/81 KRS - MASK OFF HIGH BITS OF UNIT
;   00.08 05/15/82 KRS - SD/DD TRACK LOGIC
;   00.09 06/14/82 SBW - NEW ALLOCATION LOGIC
;   00.10 10/26/82 blc - ROMable Version
;
;
; EACH ENTRY IS ENTERED WHEN DRIVER PROPER IS CALLED
;  BY:
;	PUSH	H
;	LXI	H,BKDCB	; BLOCKED DISK CONTROL BLOCK
;	JMP	--ROUTINE--
;
	NAM	BKDSK9
;
	ENT	BKDSPC	; SPECIAL CALL
	ENT	BKDSET	; SET HEAD
	ENT	BKDIO	; DO IO
	ENT	CBKDE	; CURRENT BKDCB (FOR DEBUGGING)
	ENT	GETBUF	; GET BUFFER PTR
	ENT	MKEMTY	; MAKE BUFFER EMPTY
;
	EXT	CSDTE,CDUCB,MOVE				;00.09
;
	EXT	WHREDK,GENBLK,GENBKX	;GENDVR HOOKUPS		;00.09
	EXT	NEWBLK			; DOS HOOKUP		;00.09
;
MAXRTY	EQU	4	;RETRIES FOR SEEK, READ + WRITE
;
;
RDCMD	EQU	0	; READ COMMAND TO DISK DRIVER
WRCMD	EQU	1	; WRITE CMD
VYCMD	EQU	2	; VERIFY CMD
;
 	ICL	DSKPARM
;
;  BKDCB - BUFFER DISK CONTROL BLOCK
;
	ORG	0
K.FLAG:	DS	1	; FLAG INFO
     	K.MOD:	EQU	80H	; BUFFER MODIFIED
K.SECF:	DS	1	; SECTOR FACTOR
K.UNIT:	DS	1	; UNIT  - CURRENT RESIDENT BUFFER 
K.SUR:	DS	1	;   SURFACE
K.TRK:	DS	2	;   TRACK
K.SEC:	DS	1	;   SECTOR (PHYSICAL)
K.USFT:	DS	2	; UNIT SECTOR FACTOR TABLE
K.BUFA:	DS	2	; BUFFER ADDRESS
K.NALLOC: DS	1	; # OF NEW ALLOC TABLE ENTRIES
K.NPTR:	DS	2	; ADDRESS OF NEW ALLOC TABLE
	DS	1	; SPARE
K.SPC:	DS	3	; JMP SPECIAL ROUTINE
K.DOIO:	DS	3	; JMP DOIO ROUTINE
;
; FORMAT OF NEW ALLOCATION TABLE ENTRIES - OFFSETS FROM @K.NPTR
;
	ORG	0
K.NSIZE: DS	1	; NEW ALLOC SIZE/NOT RESIDENT FLAG
	K.NRES:	EQU	80H	; NOT RESIDENT
K.NBLK:	DS	3	; NEW ALLOC LOGICAL BLOCK #
K.NUNIT: DS	1	; NEW ALLOC UNIT NUMBER
K.NATSZ:		; SIZE OF ENTRY
;
	ROG
;
;
	EJECT
;
GETDE	MAC
[	MOV	E,M
	INX	H
	MOV	D,M
]
;
;	GETBKD, GTBKD, AND CKNALC ADDED SBW 6/14/82 00.09
;
GETBKD	MAC
[	MVI	L,&1
	CALL	GTBKD
]
;
GTBKD:
	PUSH	D		; STANDARDIZED INDEX INTO BKD
	XCHG			; CONTROL BLOCK POINTED TO BY
	LHLD	CBKDE		; CBKDE
	MVI	D,0
	DAD	D
	POP	D
	RET
;
;	SUBROUTINE CKNALC CHECKS TO SEE WHETHER NEW ALLOCATION
;	LOGIC IS ACTIVE. RETURNS:
;
;	HL POINTS TO CBKDE->K.NAT->K.NSIZE
;	A CONTAINS  (CBKDE->K.NAT->K.NSIZE)
;	Z FLAG CLEAR IF CBKDE->K.NALLOC != 1
;
;	THUS THE Z FLAG MAY BE USED TO DETERMINE IF THE OLD
;	DEFBKD MACRO WAS USED BY THE DRIVER, AND SKIP ALL OF
;	THE NEW ALLOCATION LOGIC.
;
CKNALC:
	GETBKD	K.NALLOC	; POINT TO NEW ALLOCATION SIZE
	MOV	A,M
	DCR	A		; CURRENT MACROS?
	RNZ			; RETURN IF NOT
;
	INX	H		; ELSE POINT TO SIZE FIELD OF NAT
	MOV	A,M
	INX	H
	MOV	H,M
	MOV	L,A
	MOV	A,M		; RETURN CONTENTS IN A
	RET
;
	EJECT
;
; SPECIAL FUNCTIONS
;
BKDSPC:	SHLD	CBKDE	; SAVE THE CURRENT BKDCB ENTRY
	POP	H
;
	MOV	A,C
	CPI	9	; 9- FLUSH BUFFER
	JZ	FLUSH
	CPI	10	;10- GET SIZE
	JEQ	GETSIZE
	CPI	11	;11- MARK BUFFER FREE
	JEQ	FREBUF
	ORA	A
	JZ	DOHOME	; 0- HOME THE DISK
	JMP	DSKSPC	; ELSE LET THE DRIVER DO IT
;
FREBUF:	XRA	A	;NO ERRORS FOR REV 3 IOS
	JMP	MKEMTY	;MARK BUFFER EMPTY
;
; DO HOME
;
DOHOME:	PUSH	B	;SAVE UNIT
	CALL	FLUSH		;*** MUST ALLOW ERROR
	JNZ	POPBRT				;00.04
	POP	B
	MVI	C,0	;HOME CMD
	JMP	DSKSPC	;DO HOME
;
POPBRT:	POP	D	;DUMMY TO CLEAR STACK	 00.04
	RET					;00.04
;
	EJECT
;
; GET THE SIZE OF THE DISK AND SET UP BKDCB
;
GETSIZE:
	CALL	CKNALC		; MAKE NEW ALLOC INVALID.	;00.09
	JNZ	..1		; VALUE OF ZERO IN K.NALLOC	;00.09
	MVI	M,0		; INDICATES OLD MACROS USED	;00.09
..1:	;			; BY DRIVER, SO IGNORE IT	;00.09
;
	PUSH	B	; SAVE UNIT(B)
	CALL	FLUSH
	JNZ	POPBRT				;00.04
	POP	B
	PUSH	B
	CALL	MKEMTY	; GET BUFFER OF DRIVER'S USE
	CALL	GETBUF
	XCHG		; HL=BUFFER ADR
;
	POP	B	; GET UNIT AND CMD
	PUSH	B
	CALL	DSKSPC	; FIRST ASK DRIVER IT'S SIZE
	ORA	A	;00.02 TEST RETURN CODE
	JNZ	POPBRT				;00.04
	POP	B	;00.02
;
;  TABLE RTNED BY DRIVER IS:
;  DE->	SECTOR FACTOR (1)
;	CLUSTER SIZE (1)----!
;	DUB ADDR     (2)    !
;	DIR START    (2)    !--- 7 BYTES
;	DIR ENTRIES  (1)    !
;	DIR CLUSTERS (1)----!
;
	MOV	A,B	;00.03 GET UNIT FROM B SAVED
	CALL	GUSFT	; PT AT SECTOR FACTOR TABLE
	LDAX	D	; GET SECTOR FACTOR OF THIS UNIT
	MOV	M,A	; AND SAVE IT
	INX	D
;
;  SETUP SDT AS REQUESTED BY DRIVER
;	DE -> CLUSTER SIZE, MOVE DIRECTLY TO SDT
;
	LHLD	CSDTE
	LXI	B,SDTCSZ
	DAD	B
	LXI	B,7
	CALL	MOVE
	XRA	A	; ALL OK
	RET
	EJECT
;
; SET HEAD B=UNIT, A=SURFACE, CD=TRK, E=SEC
;
BKDSET:	
	SHLD	CBKDE	; SAVE BLK DISK CTL BLK
	POP	H
;
	LXI	H,OSUNIT
	MOV	M,B	;OS UNIT
	INX	H
	MOV	M,A	;OS SURFACE
	INX	H
	MOV	M,D	;OS TRACK (LO)
	INX	H
	MOV	M,C	;OS TRACK (HI)
	MOV	A,E
	DCR	A
	STA	LOGSEC	;OS LOGICAL SECTOR (BASE 0)
;
	mov	a,c	; If requested track >=256		;00.09
	ora	a	; then no possibility of		;00.09
	jnz	noddsd	; single density			;00.09
;
	LHLD	CDUCB	; ADDRESS SDT			 00.08	;00.09
	LXI	B,DUBSEC ; BYTE WITH SD FACTOR		 00.08
	DAD	B					;00.08
	MOV	A,M	; GET IT			 00.08
	DCR	A					;00.08
	JZ	NODDSD	; IF A '1', NO SD TRACKS FLAGGED 00.08
	LXI	B,DUBSTK-DUBSEC				 00.08
	DAD	B	; ADDRESS # OF SD TRACKS	 00.08
	MOV	A,M					;00.08
	dcr	a						;00.09
	CMP	D	; TEST - IF A > D, IS SD	 00.08	;00.09
	JGE	SINGLR					;00.08
;
NODDSD:	LDA	OSUNIT
	CALL	GUSFT
	MOV	A,M	; CHECK SECTOR FACTOR ON DISK
	DCR	A
	JNZ	BLKDSK
;
; NON-BLOCKED DISK (128 BYTE SECTOR)
;
SINGLR:	MVI	A,-1
	STA	BLKPOS	; TELL DOIO THAT NO BUFFER IS TO BE USED
	LDA	LOGSEC
	INR	A
	STA	PHYSEC	; SET UP TRUE SECTOR (BASE 1)
	XRA	A
	RET		; NO ERR
	EJECT
;
; BLOCKED DISK - MUST BUFFER
;
BLKDSK:
	LDA	OSUNIT		;				;00.09
	CALL	GSECMA		; GET SECTOR MASK		;00.09
	MOV	E,A		; SAVE SECTOR FACTOR		;00.09
;
	LDA	LOGSEC	; GET MASK FOR BLK IN SECTOR
	ANA	M
	STA	BLKPOS	; SAVE BLOCK POSITION
;
	LDA	LOGSEC	; NOW GET PHYSICAL SECTOR BY SHIFTING
	DCR	E	; ONCE LESS THAN SECTOR FACTOR		;00.09
     .DO
	ORA	A
	RAR		; SHIFT ZERO IN AT MSB
	DCR	E
	JNZ	.DO
     .UNTIL
	INR	A	;  (RESTORE BASE 1)
	STA	PHYSEC	; AND SAVE THE TRUE PHYSCIAL SECTOR
;
; NOW CHECK FOR BUFFER RESIDENCE
;
	GETBKD	K.UNIT	; HL-> CURRENT BUFFER CONTENTS		;00.09
	LXI	D,OSUNIT
	MVI	B,5	; 5 IS UNIT, SUR, TRK(2), SEC
     .DO
	LDAX	D
	CMP	M
	JNE	NOTRES
	INX	D
	INX	H
	DCR	B
	JNZ	.DO
     .UNTIL
	XRA	A	; PROPER BLOCK IS RESIDENT
	RET
;
; GSECM ADDED 6/16/82 SBW 00.09
;
; SUBROUTINE TO GET THE SECTOR FACTOR AND SECTOR MASK.
;
; RETURNS:	SECTOR FACTOR IN A
;		POINTER TO SECTOR MASK IN HL
;		D DESTROYED
;
; ENTER AT GSECMA, IF DESIRED, WITH UNIT NUMBER IN A
;
GSECM:				;
	GETBKD	K.UNIT		; GET THE UNIT FROM CBKDE
	MOV	A,M		;
GSECMA:				; (ENTER HERE WITH UNIT IN A)
	CALL	GUSFT		; POINT INTO USER SECTOR
	MOV	E,M		;     FACTOR TABLE
	MOV	A,E		; RETURN SECTOR FACTOR IN A
	MVI	D,0		;
	LXI	H,SECMASK-2	; INDEX INTO SECTOR MASK TBL
	DAD	D		;
	RET			;RETURN POINTER
;
SECMASK:			; PHYSICAL SECTOR MASK
	DB	1,3,7		;				;00.09
;
; SETNBLK added 6/17/82 SBW 00.09
;
; Subroutine to check if driver used current macros, and if so, to set
; K.NBLK to the block number of the first block of the sector containing
; the requested block.
;
; Returns:	If Z flag clear: Old macros used by driver.
;		If Z flag set:   HL points to K.NSIZE field,
;				 A contains block offset of requested
;				   block in the sector.
;
SETNBLK:
	CALL	CKNALC		; Current macros?
	RNZ			; Return if not
	PUSH	H
;
	XCHG			; Else K.NBLK = GENBLK, adjusted to
	LHLD	GENBLK		; refer to the first block in the cluster
	XCHG
;
	LDA	BLKPOS		; Get block offset into cluster
	MOV	C,A
	MOV	A,E
	SUB	C		; Subtract offset from GENBLK
	INX	H
	MOV	M,A		; and store in K.NBLK
	INX	H
	MOV	A,D
	SBI	0
	MOV	M,A
	INX	H
	LDA	GENBKX		; High order byte of 24 bits GENBLK
	SBI	0
	MOV	M,A
	POP	H		; point back to K.NSIZE
	MOV	A,C		; Get block offset to return
	CMP	A		; Set Z to say "NEW MACROS!"
	RET
;
	EJECT
;
; DATA NOT RESIDENT, ISSUE FLUSH AND SEEK TO NEW DATA
;
NOTRES:	CALL	FLUSH
	RNZ		;ERROR
;
; Set buffer to indicate requested block current, not modified	;00.09
;
	LHLD	CBKDE
	MOV	A,M
	ANI	^K.MOD	;  MARK BUFFER NOT MODIFED
	MOV	M,A	; AND SAVE IT
;
	LXI	D,K.UNIT	; HL-> CURRENT BUFFER CONTENTS	;00.09
	DAD	D						;00.09
	LXI	D,OSUNIT
	LXI	B,5	; 5 IS UNIT, SUR, TRK(2), SEC
	CALL	MOVE	; MOVE SECTOR INFO TO BKDCB
;
;	NEW ALLOCATION LOGIC ADDED SBW 6/13/82 00.09
;
	LDA	NEWBLK		; NEW ALLOCATION FLAG?
	ORA	A
	JZ	OLDCLUS
;
	CALL	SETNBLK		; YES: CHECK IF NEW ALLOC LOGIC
	;			;      IS ACTIVE
	;			; IF NALLOC FIELD IS ZERO, THEN OLD
	;			; MACROS WERE USED BY DRIVER, SO
	JNZ	PREREAD		; DON'T DO NEW ALLOC LOGIC
;
;				; else SETNBLK also set the NBLK field to the
;				; block number of the first block in the
;				; sector.
;
	XCHG			; SET SIZE FIELD TO
	LHLD	CSDTE		; BLOCKS PER CLUSTER FROM
	LXI	B,SDTCSZ	; SDT TABLE
	DAD	B
	MOV	A,M
	ORI	K.NRES		; SET NOT RESIDENT YET
	STAX	D
;
	LXI	H,K.NUNIT-K.NSIZE
	DAD	D		; SET UNIT TO UNIT WITHIN CONTROLLER
	LDA	OSUNIT
	MOV	M,A
;
OLDCLUS:
	CALL	CKNALC		; IF OLD MACROS USED BY DRIVER,
	JNZ	PREREAD		; OR IF NO NEW ALLOC ACTIVE,
	ANI	^K.NRES
	JZ	PREREAD		; THEN PREREAD THE PHYSEC
;
;				; ELSE SAVE THE SIZE OF THE UNWRITTEN
	MOV	B,A		; PART OF THE CLUSTER
;
	XCHG			; CHECK LOGICAL BLOCK
	LHLD	GENBLK		; IS IT IN NEW ALLOC RANGE?
	XCHG
;
	INX	H
	MOV	A,E
	SUB	M
	JM	PREREAD		; NO: PREREAD
	MOV	C,A		; (SAVE LOGICAL BLOCK - K.NBLK)
	INX	H
	MOV	A,D
	SBB	M
	JNZ	PREREAD		; NO AGAIN: PREREAD
	INX	H
	LDA	GENBKX
	SBB	M
	JNZ	PREREAD		; NO AGAIN: PREREAD
;
	INX	H		; ELSE COMPARE UNITS
	LDA	OSUNIT		; REQUEST SAME AS NEW ALLOC?
	CMP	M
	JNZ	PREREAD		; NO: PREREAD
;
;	else at this point, B contains the K.NSIZE field, with the K.NRES
;	bit stripped. C contains GENBLK-K.NBLK, which is the number of
;	blocks between the beginning of the unwritten part of the new
;	cluster and the block being accessed.
;
	MOV	A,C		; Is the requested block in the unwritten
	CMP	B		; part of the new cluster?
	JGE	PREREAD		; no: preread
;
	PUSH	B
	CALL	SETNBLK		; K.NBLK gets the block number of the
	POP	B		; first block of the sector, and A gets
;				; the block offset from the beginning
;				; of the sector.
;
;	Adjust K.NSIZE to indicate that the unwritten part of the cluster
;	extends from the beginning of the sector containing the requested
;	block to the end of the cluster. This is done by:
;
;	K.NSIZE = K.NSIZE - (GENBLK-K.NBLK) + block offset
;
	ADD	B
	SUB	C
	MOV	M,A
;
	CALL	GSECM		; SECTOR MASK CAN DOUBLE AS
	MOV	B,M		; NUMBER OF BLOCKS PER CLUSTER
	INR	B
	CALL	GETBUF		; POINT TO BUFFER
	XCHG
  .DO
	MVI	A,128		; BYTES PER BLOCK
    .DO
	MVI	M,0		; ZERO THE BUFFER
	INX	H
	DCR	A
	JNZ	.DO
    .UNTIL
	DCR	B
	JNZ	.DO
  .UNTIL
;
;	XRA	A		; RETURN NO ERROR
	RET
;
PREREAD:
	MVI	A,RDCMD
	CALL	MAGNET
	ORA	A	;00.02
	JNZ	MKEMTY	;ERROR
;
	XRA	A
	RET		;OK
;
	EJECT
;
;  FLUSH CURRENT BUFFER CONTENTS TO DISK (IF MODIFED)
;
FLUSH:	LHLD	CBKDE
	MOV	A,M
	ANI	K.MOD
	RZ		;BUFFER EMPTY
;
;	NEW ALLOCATION LOGIC ADDED SBW 6/13/82 00.09
;
	CALL	CKNALC		; CHECK IF NEW ALLOC LOGIC ACTIVE
	;			; OLD MACROS USED BY DRIVER?
	JNZ	PHFLUSH		; YES: NO NEW ALLOC LOGIC
;
	ORA	A		; NEW ALLOC ACTIVE?
	JZ	PHFLUSH		; NO: NO NEW ALLOC LOGIC
;
;				; NEW ALLOC RESIDENT?
	JM	PHFLUSH		; NO: NO NEW ALLOC LOGIC
;
	PUSH	H
	CALL	GSECM		; GET BLOCKS PER SECTOR
	MOV	C,M
	INR	C
	POP	H
;
	MOV	A,M		; REDUCE NEW ALLOC SIZE BY
	SUB	C		; BLOCKS PER SECTOR
	MOV	M,A		; IF REDUCED TO ZERO THEN
	;			; TURN OFF NEW ALLOC LOGIC
	JZ	PHFLUSH		; AND PHYSICAL FLUSH
;
	INX	H
	MOV	A,M		; ELSE INCREASE NEW ALLOC BLOCK BY
	ADD	C		; BLOCKS PER SECTOR
	MOV	M,A
	INX	H
	MOV	A,M
	ACI	0
	MOV	M,A
	INX	H
	MOV	A,M
	ACI	0
	MOV	M,A
;
PHFLUSH:
	MVI	A,2*MAXRTY
	STA	RTYCTR
;
FLUSH4:
	MVI	A,WRCMD	;WRITE BUFFER
	CALL	MAGNET
	ORA	A	;00.02
	JZ	FLUSH6	;OK, DO VERIFY
;
	LXI	H,RTYCTR
	DCR	M
	JNZ	FLUSH4	;RETRY WRITE
	JMP	FLUSH7	; JUST CAN'T CUT IT
;
FLUSH6:	MVI	A,VYCMD	;VERIFY BUFFER
	CALL	MAGNET	;DO VERIFY
	ORA	A	;00.02
	JZ	FLSXIT	;OK
;
	LXI	H,RTYCTR
	DCR	M
	JNZ	FLUSH4	;VERIFY ERROR, RETRY WRITE
;
; GIVE UP - CAN'T WRITE OR VERIFY
;
FLUSH7:	MVI	A,-2   ;00.02 WRITE ERROR
	ORA	A
	RET		;RETURN W/ERROR
;
; EXIT FLUSH WITH NO ERRORS
;
FLSXIT:			;*** LEAVES BUFFER NOT VALID ***

;
; MARK BUFFER EMPTY AND EXIT WITH ERROR CODE IN A
;
MKEMTY:	PUSH	PSW
	LHLD	CBKDE
	MOV	A,M	; MARK AS NOT MODIFED
	ANI	^K.MOD
	MOV	M,A
;
	LXI	D,K.UNIT
	DAD	D
	MVI	M,-1	; MAKE AN INVALID UNIT
;
	CALL	CKNALC		; MARK NEW ALLOCATION		;00.09
	JNZ	..1						;00.09
	ORI	K.NRES		; NOT RESIDENT			;00.09
	MOV	M,A		;				;00.09
..1:
;
	POP	PSW
	RET		;RETURN WITH ERROR
	EJECT
;
; EXECUTE SYSTEM DATA REQUEST FOR LOGICAL SECTORS
; @HL=BUFFER, C=0 READ, C=1 WRITE
;
BKDIO:	SHLD	CBKDE	; SAVE BKDCB
	POP	H	; AND RECOVER BUFFER
     .IF
	LDA	BLKPOS	; GET BLOCK POSITION
	INR	A	; 1..9
	JNZ	.ELSE	;  (-1 SAYS NO BUFFERING)
;
; 128 BYTE SECTOR IO (NO BUFFERING)
;	DEAL DIRECT WITH USER'S BUFFER
			; HL=BUFFER TO USE
			; C =COMMAND (RDCMD, WRCMD)
	LXI	D,OSUNIT ; DE-> SECTOR POSN
	JMP	DSKIO
     .ENDIF
;
	PUSH	H	;SAVE RAM REQ
	CALL	GETBUF
	XCHG		; HL=RESIDENT BUFFER
	LXI	D,128	;STEP SIZE
    .DO
	DCR	A
	JZ	.BREAK
	DAD	D
    .LOOP
	XCHG		;DE=BUFFER
	POP	H	;OS RAM REQ
	EJECT
;
;  NOW HL= SYSTEM REQ ADDR, AND DE=DRIVER BUFFER
;
     .IF
	MOV	A,C	;OS REQ FUNCTION
	CPI	WRCMD
	LXI	B,128	;  AND SET UP MOVE LENGTH
	JEQ	.ELSE
     .THEN		;READ, MOVE DATA TO OS AND DONE
	CALL	MOVE
	XRA	A
	RET		; ALL OK
     .ENDIF
;
; WRITE, MOVE DATA AND UPDATE STATUS
;
	XCHG		;WRITE, SWAP OPERANDS
	CALL	MOVE	;MOVE TO RESIDENT BUFFER
;
	LHLD	CBKDE
	MOV	A,M
	ORI	K.MOD
	MOV	M,A	;BUFFER MODIFIED
;
	XRA	A
	RET		;RET WITH STATUS OK
	EJECT
;
; THIS IS THE MEDIA ACCESS ROUTINE TO R/W DATA FROM/TO THE DISK
;   *** ACCESSES 1 PHYSICAL SECTOR ***
; A= CMD:  0=READ, 1=WRITE, 2=VERIFY
;
MAGNET:	STA	IOCMD	; SAVE CMD
	CALL	GETBUF	; GET BUFFER ADDRESS
;
	GETBKD	K.UNIT	; GET SECTOR DESC.			;00.09
;
	XCHG		; HL=BUFFER ADR, DE-> SECTOR DESC.
	LDA	IOCMD
	MOV	C,A	; C=CMD
			; DO THE SECOR REQUESTED
;
;  GO TO DISK IO ROUTINE
;   HL= BUFFER
;   ON SPECIAL CALLS PUT BUFFER ADR IN HL + CLEAR USE
;   DE->SECTOR DESCRIPTOR (UNIT, SUR, TRK(2), SEC)
;   C = CMD (0=RD, 1=WR)
;
DSKIO:	PUSH	H
	MVI	L,K.DOIO	;				;00.09
;
DSKDO:
	CALL	GTBKD	; HL=ROUTINE ENTRY IN BKDCB		;00.09
	XTHL		; REPLACE ROUTINE ON TOP
	RET		; AND HL AS PREV
;
;  GO TO DISK SPECIAL ROUTINE
;   B=UNIT, C=COMMAND
;
DSKSPC:	PUSH	H
	MVI	L,K.SPC		;				;00.09
	JMP	DSKDO
;
;  GET BUFFER ADRESS -> DE
;
GETBUF:
	GETBKD	K.BUFA		;				;00.09
	GETDE
	INX	D	; SKIP CONTROL WORD
	INX	D
	RET
	EJECT
;
;  GET ADDRESS OF UNIT IN SECTOR FACTOR TABLE
;    ENTR: A=UNIT
;    RNTS: HL-> UNIT,  SAVES DE, BC, A
;
GUSFT:	PUSH	D
	GETBKD	K.USFT		; K.SECFACTOR			;00.09
	GETDE		; DE = UNIT SECTOR FACTOR TABLE		;00.09
	ANI	0FH	; CLEAR TOP BITS	 00.07
	MOV	L,A						;00.09
	MVI	H,0						;00.09
	DAD	D
	POP	D
	RET
;
;
; DATA AREAS
;
        ram                                  ; 00.10
CBKDE:	DW	0	;CURRENT BUFF DISK CTL BLK
IOCMD:	DB	0	;DRIVER FUNCTION, 0=READ, 1=WRITE, 2=VERIFY
RTYCTR:	DB	0	;LOCAL RETRY COUNT
BLKPOS:	DB	0	;WHICH POSN IN LOCAL BUFFER
;
OSUNIT:	DB	0
OSSUR:	DB	0
OSTRK:	DW	0
PHYSEC:	DB	0	;PHYSICAL SECTOR
;
LOGSEC:	DB	0	;OS REQUESTED SECTOR (BASE 0)
;
