forked from MirrorRepos/RomWBW
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2124 lines
62 KiB
2124 lines
62 KiB
;__________________________________________________________________________________________________
|
|
;
|
|
; CBIOS FOR N8VEM
|
|
;
|
|
; BY ANDREW LYNCH, WITH INPUT FROM MANY SOURCES
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; cbios.asm 6/04/2012 dwg - added BOOTLU
|
|
; cbios.asm 5/21/2012 dwg - added peek and poke for bank 1 frame 0
|
|
; cbios.asm 5/16/2012 dwg - new architecture for 2.0.0.0 Beta 3
|
|
;
|
|
|
|
; The std.asm file contains the majority of the standard equates
|
|
; that describe data sructures, magic values and bit fields used
|
|
; by the CBIOS.
|
|
|
|
#INCLUDE "std.asm"
|
|
;
|
|
#INCLUDE "syscfg.exp"
|
|
;
|
|
.ORG CBIOS_LOC ; DEFINED IN STD.ASM
|
|
;
|
|
;==================================================================================================
|
|
; CP/M JUMP VECTOR TABLE FOR INDIVIDUAL SUBROUTINES
|
|
;==================================================================================================
|
|
; These jumps are defined in the CP/M-80 v2.2 system guide and comprise
|
|
; the invariant part of the BIOS.
|
|
|
|
JP BOOT ; #0 - COLD START
|
|
WBOOTE JP WBOOT ; #1 - WARM START
|
|
JP CONST ; #2 - CONSOLE STATUS
|
|
JP CONIN ; #3 - CONSOLE CHARACTER IN
|
|
JP CONOUT ; #4 - CONSOLE CHARACTER OUT
|
|
JP LIST ; #5 - LIST CHARACTER OUT
|
|
JP PUNCH ; #6 - PUNCH CHARACTER OUT
|
|
JP READER ; #7 - READER CHARACTER OUT
|
|
JP HOME ; #8 - MOVE HEAD TO HOME POSITION
|
|
JP SELDSK ; #9 - SELECT DISK
|
|
JP SETTRK ; #10 - SET TRACK NUMBER
|
|
JP SETSEC ; #11 - SET SECTOR NUMBER
|
|
JP SETDMA ; #12 - SET DMA ADDRESS
|
|
JP READ ; #13 - READ DISK
|
|
JP WRITE ; #14 - WRITE DISK
|
|
JP LISTST ; #15 - RETURN LIST STATUS
|
|
JP SECTRN ; #16 - SECTOR TRANSLATE
|
|
;------------------------------------------------------------------------
|
|
; These jumps are enhancements, added for the benefit of the RomWBW BIOS
|
|
; and are located following the invariant jump table so they can be
|
|
; easily located by external programs. They transfger control to routines
|
|
; that are located somewhere within the main section of the CBIOS.
|
|
|
|
JP BNKSEL ; #17 - SEL. RAM BANK FOR LOW32K (obsolete, use HBIOS)
|
|
JP GETDSK ; #18 - Get Disk Info (device/unit/lu)
|
|
JP SETDSK ; #19 - Set Disk Into (device/unit/lu)
|
|
JP GETINFO ; #20 - Get BIOS Info Base Ptr
|
|
; Expansion area for future enhancements - In order not to shift the
|
|
; subsequent data and break local and external code, space is set aside for
|
|
; four additional jumps. Until implemented, an invocation will result in
|
|
; a system panic.
|
|
CALL PANIC ; #21 - reserved for JP <new function>
|
|
CALL PANIC ; #22 - reserved for JP <new function>
|
|
CALL PANIC ; #23 - reserved for JP <new function>
|
|
CALL PANIC ; #24 - reserved for JP <new function>
|
|
;
|
|
;==================================================================================================
|
|
; CONFIGURATION DATA
|
|
;==================================================================================================
|
|
;
|
|
; The following RomWBW specific configuration data is located at this
|
|
; offset so they can be located by code in the CBIOS. The declarations
|
|
; are based on the selected configuration file used at build-time. The
|
|
; data is included from an external file so as to not clutter the main
|
|
; BIOS code. The size of the configuration data is available by virtue
|
|
; of the SIZ_CNFGDATA equate (see below).
|
|
|
|
ORG_INFOLIST .EQU $
|
|
|
|
.DB RMJ
|
|
.DB RMN
|
|
.DB RUP
|
|
.DB RTP
|
|
|
|
#INCLUDE "infolist.inc"
|
|
|
|
SIZ_INFOLIST .EQU $ - ORG_INFOLIST ;
|
|
.ECHO "INFOLIST occupies "
|
|
.ECHO SIZ_INFOLIST
|
|
.ECHO " bytes.\n"
|
|
;
|
|
;==================================================================================================
|
|
; BIOS FUNCTIONS
|
|
;==================================================================================================
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
BOOT:
|
|
JP INIT ; GO TO COLD BOOT CODE
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
WBOOT:
|
|
DI
|
|
IM 1
|
|
|
|
LD SP,ISTACK ; STACK FOR INITIALIZATION
|
|
|
|
; RELOAD COMMAND PROCESSOR FROM CACHE
|
|
LD A,1
|
|
CALL RAMPG
|
|
LD HL,0800H ; LOCATION IN RAM1 OF COMMAND PROCESSOR CACHE
|
|
LD DE,CPM_LOC ; LOCATION OF ACTIVE COMMAND PROCESSOR
|
|
LD BC,CCPSIZ ; SIZE OF COMMAND PROCESSOR
|
|
LDIR
|
|
CALL RAMPGZ
|
|
|
|
; FALL THRU TO INVOKE CP/M
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
GOCPM:
|
|
; SETUP DISK XFR BUFFER LOCATION
|
|
LD HL,SECBUF
|
|
LD (BUFADR),HL
|
|
LD B,BF_DIOSBA
|
|
RST 08
|
|
|
|
LD A,0C3H ; LOAD A WITH 'JP' INSTRUCTION (USED BELOW)
|
|
|
|
; CPU RESET / RST 0 -> WARM START CP/M
|
|
LD (0000H),A
|
|
LD HL,WBOOTE
|
|
LD (0001H),HL
|
|
|
|
; ; INT / RST 38 -> INVOKE MONITOR
|
|
; LD (0038H),A
|
|
; LD HL,GOMON
|
|
; LD (0039H),HL
|
|
|
|
; ; INT / RST 38 -> PANIC
|
|
; LD (0038H),A
|
|
; LD HL,PANIC ; PANIC ROUTINE ADDRESS
|
|
; LD (0039H),HL ; POKE IT
|
|
|
|
; CALL 5 -> INVOKE BDOS
|
|
LD (0005H),A
|
|
LD HL,BDOS
|
|
LD (0006H),HL
|
|
|
|
; RESET (DE)BLOCKING ALGORITHM
|
|
CALL BLKRES
|
|
|
|
; DEFAULT DMA ADDRESS
|
|
LD BC,80H
|
|
CALL SETDMA
|
|
|
|
; ENSURE VALID DISK AND JUMP TO CCP
|
|
LD A,(CDISK) ; GET CURRENT USER/DISK
|
|
AND 0FH ; ISOLATE DISK PART
|
|
LD C,A ; SETUP C WITH CURRENT USER/DISK, ASSUME IT IS OK
|
|
CALL DSK_STATUS ; CHECK DISK STATUS
|
|
JR Z,CURDSK ; ZERO MEANS OK
|
|
LD A,(DEFDRIVE) ; CURRENT DRIVE NOT READY, USE DEFAULT
|
|
JR GOCCP
|
|
CURDSK:
|
|
LD A,(CDISK) ; GET CURRENT USER/DISK
|
|
GOCCP:
|
|
LD C,A ; SETUP C WITH CURRENT USER/DISK, ASSUME IT IS OK
|
|
JP CCP
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
GOMON:
|
|
CALL PANIC
|
|
;
|
|
; DI
|
|
; IM 1
|
|
;
|
|
; LD SP,STACK
|
|
;
|
|
; ; RELOAD MONITOR INTO RAM (IN CASE IT HAS BEEN OVERWRITTEN)
|
|
; CALL ROMPGZ
|
|
; LD HL,MON_IMG
|
|
; LD DE,MON_LOC
|
|
; LD BC,MON_SIZ
|
|
; LDIR
|
|
; CALL RAMPGZ
|
|
|
|
; ; JUMP TO MONITOR WARM ENTRY
|
|
; JP MON_UART
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
CONST:
|
|
; CONSOLE STATUS, RETURN 0FFH IF CHARACTER READY, 00H IF NOT
|
|
;
|
|
LD B,BF_CIOIST ; B = FUNCTION
|
|
LD HL,CIOST ; HL = ADDRESS OF COMPLETION ROUTINE
|
|
JR CONIO
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
CONIN:
|
|
; CONSOLE CHARACTER INTO REGISTER A
|
|
;
|
|
LD B,BF_CIOIN ; B = FUNCTION
|
|
LD HL,CIOIN ; HL = ADDRESS OF COMPLETION ROUTINE
|
|
JR CONIO
|
|
|
|
;__________________________________________________________________________________________________
|
|
CONOUT:
|
|
; CONSOLE CHARACTER OUTPUT FROM REGISTER C
|
|
;
|
|
LD B,BF_CIOOUT ; B = FUNCTION
|
|
LD HL,CIOOUT ; HL = ADDRESS OF COMPLETION ROUTINE
|
|
LD E,C ; E = CHARACTER TO SEND
|
|
; JR CONIO ; COMMENTED OUT, FALL THROUGH OK
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
CONIO:
|
|
;
|
|
LD A,(IOBYTE) ; GET IOBYTE
|
|
AND $03 ; ISOLATE RELEVANT IOBYTE BITS FOR CONSOLE
|
|
OR $00 ; PUT LOGICAL DEVICE IN BITS 2-3 (CON:=$00, RDR:=$04, PUN:=$08, LST:=$0C
|
|
JP CIO_DISP
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
LIST:
|
|
; LIST CHARACTER FROM REGISTER C
|
|
;
|
|
LD B,BF_CIOOUT ; B = FUNCTION
|
|
LD HL,CIOOUT ; HL = ADDRESS OF COMPLETION ROUTINE
|
|
LD E,C ; E = CHARACTER TO SEND
|
|
JR LISTIO
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
LISTST:
|
|
; RETURN LIST STATUS (0 IF NOT READY, 1 IF READY)
|
|
;
|
|
LD B,BF_CIOOST ; B = FUNCTION
|
|
LD HL,CIOST ; HL = ADDRESS OF COMPLETION ROUTINE
|
|
; JR LISTIO ; COMMENTED OUT, FALL THROUGH OK
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
LISTIO:
|
|
;
|
|
LD A,(IOBYTE) ; GET IOBYTE
|
|
RLCA ; SHIFT RELEVANT BITS TO BITS 0-1
|
|
RLCA
|
|
AND $03 ; ISOLATE RELEVANT IOBYTE BITS FOR LST:
|
|
OR $0C ; PUT LOGICAL DEVICE IN BITS 2-3 (CON:=$00, RDR:=$04, PUN:=$08, LST:=$0C
|
|
JP CIO_DISP
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
PUNCH:
|
|
; PUNCH CHARACTER FROM REGISTER C
|
|
;
|
|
LD B,BF_CIOOUT ; B = FUNCTION
|
|
LD HL,CIOOUT ; HL = ADDRESS OF COMPLETION ROUTINE
|
|
LD E,C ; E = CHARACTER TO SEND
|
|
; JR PUNCHIO ; COMMENTED OUT, FALL THROUGH OK
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
PUNCHIO:
|
|
;
|
|
LD A,(IOBYTE) ; GET IOBYTE
|
|
RLCA ; SHIFT RELEVANT BITS TO BITS 0-1
|
|
RLCA
|
|
RLCA
|
|
RLCA
|
|
AND $03 ; ISOLATE RELEVANT IOBYTE BITS FOR PUN:
|
|
OR $08 ; PUT LOGICAL DEVICE IN BITS 2-3 (CON:=$00, RDR:=$04, PUN:=$08, LST:=$0C
|
|
JP CIO_DISP
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
READER:
|
|
; READ CHARACTER INTO REGISTER A FROM READER DEVICE
|
|
;
|
|
LD B,BF_CIOIN ; B = FUNCTION
|
|
LD HL,CIOIN ; HL = ADDRESS OF COMPLETION ROUTINE
|
|
JR READERIO
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
READERST:
|
|
; RETURN READER STATUS (0 IF NOT READY, 1 IF READY)
|
|
;
|
|
LD B,BF_CIOIST ; B = FUNCTION
|
|
LD HL,CIOST ; HL = ADDRESS OF COMPLETION ROUTINE
|
|
; JR READERIO ; COMMENTED OUT, FALL THROUGH OK
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
READERIO:
|
|
;
|
|
LD A,(IOBYTE) ; GET IOBYTE
|
|
RRCA ; SHIFT RELEVANT BITS TO BITS 0-1
|
|
RRCA
|
|
AND $03 ; ISOLATE RELEVANT IOBYTE BITS FOR RDR:
|
|
OR $04 ; PUT LOGICAL DEVICE IN BITS 2-3 (CON:=$00, RDR:=$04, PUN:=$08, LST:=$0C
|
|
JP CIO_DISP
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
CIOIN:
|
|
; COMPLETION ROUTINE FOR CHARACTER INPUT FUNCTIONS
|
|
;
|
|
LD A,E ; MOVE CHARACTER RETURNED TO A
|
|
; RET ; FALL THRU
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
CIOOUT:
|
|
; COMPLETION ROUTINE FOR CHARACTER OUTPUT FUNCTIONS
|
|
;
|
|
RET
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
CIOST:
|
|
; COMPLETION ROUTINE FOR CHARACTER STATUS FUNCTIONS (IST/OST)
|
|
;
|
|
OR A ; SET FLAGS
|
|
RET Z ; NO CHARACTERS WAITING (IST) OR OUTPUT BUF FULL (OST)
|
|
OR 0FFH ; $FF SIGNALS READY TO READ (IST) OR WRITE (OST)
|
|
RET
|
|
;__________________________________________________________________________________________________
|
|
SELDSK:
|
|
; SELECT DISK NUMBER FOR SUBSEQUENT DISK OPS
|
|
#IF DSKTRACE
|
|
CALL PRTSELDSK ; *DEBUG*
|
|
#ENDIF
|
|
JP DSK_SELECT
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
HOME:
|
|
; SELECT TRACK 0 (BC = 0) AND FALL THRU TO SETTRK
|
|
#IF DSKTRACE
|
|
CALL PRTHOME ; *DEBUG*
|
|
#ENDIF
|
|
|
|
LD A,(HSTWRT) ; CHECK FOR PENDING WRITE
|
|
OR A
|
|
JR NZ,HOMED
|
|
LD (HSTACT),A ; CLEAR HOST ACTIVE FLAG
|
|
|
|
HOMED:
|
|
LD BC,0
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
SETTRK:
|
|
; SET TRACK GIVEN BY REGISTER BC
|
|
LD (SEKTRK),BC
|
|
RET
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
SETSEC:
|
|
; SET SECTOR GIVEN BY REGISTER BC
|
|
LD (SEKSEC),BC
|
|
RET
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
SECTRN:
|
|
; SECTOR TRANSLATION FOR SKEW, HARD CODED 1:1, NO SKEW IMPLEMENTED
|
|
LD H,B
|
|
LD L,C
|
|
RET
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
SETDMA:
|
|
LD (DMAADR),BC
|
|
RET
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
READ:
|
|
LD A,DOP_READ
|
|
JR READWRITE
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
WRITE:
|
|
LD A,C
|
|
LD (WRTYPE),A ; SAVE WRITE TYPE
|
|
LD A,DOP_WRITE
|
|
JR READWRITE
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
BNKSEL:
|
|
;
|
|
LD A,C
|
|
JP RAMPG
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
GETDSK:
|
|
;
|
|
; INPUT: C=DRIVE # (0=A, 1=B, ... P=16)
|
|
; OUTPUT: A=RESULT (0=OK, 1=INVALID DRIVE #)
|
|
; B=DEVICE/UNIT
|
|
; DE=CURRENT LU
|
|
; HL=LU COUNT SUPPORTED ON DEVICE/UNIT (0 = NO SUPPORT)
|
|
;
|
|
; C HAS CPM DRIVE, LOOKUP DPH (INCLUDES INVALID DRIVE CHECK)
|
|
CALL DSK_GETDPH ; HL = DPH (0 IF INVALID DRIVE)
|
|
RET NZ ; A=1 AND NZ SET IF INVALID DRIVE
|
|
|
|
; HL HAS DPH POINTER, LOOKUP LU INFO (ERROR IF NO LU SUPPORT)
|
|
CALL DSK_GETLU ; HL = ADDRESS OF START OF LU DATA
|
|
JR NZ,GETDSK1 ; NO LU SUPPORT, BAIL OUT
|
|
|
|
; HL POINTS TO START OF LU DATA, FILL IN LU VALUES
|
|
LD E,(HL)
|
|
INC HL
|
|
LD D,(HL) ; DE NOW HAS CURRENT SLICE NUMBER
|
|
INC HL
|
|
LD A,(HL)
|
|
INC HL
|
|
LD H,(HL)
|
|
LD L,A ; HL NOW HAS SLICE COUNT FOR DEVICE
|
|
|
|
GETDSK1:
|
|
XOR A ; A=0 FOR SUCCESS (EVEN IF NO LU SUPPORT)
|
|
RET
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
SETDSK:
|
|
;
|
|
; INPUT: C=DRIVE # (0=A, 1=B, ... P=16)
|
|
; B=DEVICE/UNIT
|
|
; DE=CURRENT LU
|
|
; HL=LU COUNT SUPPORTED ON DEVICE/UNIT
|
|
; OUTPUT: A=RESULT (0=OK, 1=INVALID DRIVE #)
|
|
; B=DEVICE/UNIT
|
|
; DE=CURRENT LU
|
|
; HL=LU COUNT SUPPORTED ON DEVICE/UNIT (0 = NO SUPPORT)
|
|
;
|
|
; NOTES:
|
|
; PARMS ARE NOT VALUE CHECKED. A NON-EXISTENT DEVICE/UNIT/LU COULD
|
|
; BE SET AS A RESULT. CALLER IS RESPONSIBLE FOR THIS.
|
|
;
|
|
; SAVE INCOMING LU VALUES FOR LATER
|
|
PUSH BC
|
|
PUSH HL
|
|
PUSH DE
|
|
|
|
; MAKE SURE NEW DEVICE/UNIT IS A MASS STORAGE DEVICE
|
|
LD A,B ; LOAD THE REQEUSTED DEVICE/UNIT
|
|
CP $20 ; MASS STORAGE DEVICES START AT DEV/UNIT $20
|
|
JR C,SETDSK2 ; IF NOT, BAIL OUT
|
|
|
|
; C HAS CPM DRIVE, LOOKUP DPH (INCLUDES INVALID DRIVE CHECK)
|
|
PUSH BC
|
|
CALL DSK_GETDPH ; HL = DPH (0 IF INVALID DRIVE)
|
|
POP BC
|
|
JR NZ,SETDSK2 ; A=1 AND NZ SET IF INVALID DRIVE
|
|
|
|
; UPDATE DEVICE/UNIT (CHECK NEW DEVICE IS VALID)
|
|
DEC HL ; POINT TO DEVICE/UNIT BYTE
|
|
LD A,(HL) ; LOAD CURRENT DEVICE/UNIT
|
|
CP $20 ; MASS STORAGE DEVICES START AT DEV/UNIT $20
|
|
JR C,SETDSK2 ; IF NOT, BAIL OUT
|
|
LD A,B ; LOAD NEW DEVICE/UNIT VALUE
|
|
LD (HL),A ; SAVE IT
|
|
INC HL ; POINT HL BACK TO START OF DPH
|
|
|
|
; HL HAS DPH POINTER, LOOKUP LU INFO (ERROR IF NO LU SUPPORT)
|
|
CALL DSK_GETLU ; HL = ADDRESS OF START OF LU DATA
|
|
|
|
; RECOVER THE NEW SLICE AND SLICE COUNT
|
|
POP DE ; DE = NEW SLICE
|
|
POP BC ; BC = NEW SLICE COUNT
|
|
|
|
; CHECK IF DRIVE IS LU CAPABLE, BYPASS LU SETTING IF NOT
|
|
JR NZ,SETDSK1
|
|
|
|
; PLUG IN THE NEW VALUES
|
|
LD (HL),E
|
|
INC HL
|
|
LD (HL),D ; CURRENT SLICE NOW SET TO DE
|
|
INC HL ; POINT TO SLICE COUNT
|
|
LD (HL),C
|
|
INC HL
|
|
LD (HL),B ; SLICE COUNT NOW SET TO HL
|
|
|
|
SETDSK1:
|
|
; SUCCESS EXIT (USE GETDSK TO RETURN DATA)
|
|
CALL BLKRES ; RESET (DE)BLOCKING ALGORITHM FOR SAFETY
|
|
POP BC
|
|
JR GETDSK
|
|
|
|
SETDSK2:
|
|
; ERROR EXIT
|
|
POP DE
|
|
POP HL
|
|
POP BC
|
|
XOR A
|
|
INC A
|
|
RET
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
GETINFO:
|
|
;
|
|
; The purpose of the GETINFO BIOS entry point is to return a
|
|
; base pointer to a table of pointers. These pointers are used
|
|
; by utility programs to locate BIOS internals that are not able
|
|
; to be located by normal means specified in the system guide.
|
|
;
|
|
; The pointers are defined in an included file so as to not clutter
|
|
; the main code. The contents are used by external utilties and are
|
|
; not used in any manner by the CBIOS code specifically.
|
|
;
|
|
LD HL,INFOLIST
|
|
RET
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
READWRITE:
|
|
LD (DSKOP),A ; SET THE ACTIVE DISK OPERATION
|
|
#IF DSKTRACE
|
|
CALL PRTDSKOP ; *DEBUG*
|
|
#ENDIF
|
|
LD A,(SEKDU) ; GET DEVICE/UNIT
|
|
AND 0F0H ; ISOLATE DEVICE NIBBLE
|
|
JR Z,DIRRW ; DEVICE = 0 = MD, SO DIRECT R/W
|
|
JP BLKRW ; OTHERWISE, (DE)BLOCKING R/W
|
|
|
|
;
|
|
;==================================================================================================
|
|
; DIRECT READ/WRITE (NO (DE)BLOCKING, NO BUFFERING, 128 BYTE SECTOR)
|
|
;==================================================================================================
|
|
;
|
|
DIRRW:
|
|
CALL BLKFLSH ; FLUSH ANY PENDING WRITES SO WE CAN USE SEC BUF
|
|
RET NZ ; RETURN ON ERROR
|
|
|
|
CALL BLKRES ; RESET (DE)BLOCKING ALG, BUF IS NO LONGER VALID
|
|
|
|
; AT THIS POINT THE ACCESS IS HARDCODED TO POINT TO MEMORY DISK DRIVER
|
|
; SINCE THERE IS NO OTHER DIRECT READ/WRITE DEVICE
|
|
|
|
LD A,(DSKOP)
|
|
|
|
CP DOP_READ
|
|
JP Z,MD_READ
|
|
|
|
CP DOP_WRITE
|
|
JP Z,MD_WRITE
|
|
|
|
CALL PANIC
|
|
;
|
|
;==================================================================================================
|
|
; BLOCKED READ/WRITE (BLOCK AND BUFFER FOR 512 BYTE SECTOR)
|
|
;==================================================================================================
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; RESET (DE)BLOCKING ALGORITHM - JUST MARK BUFFER INVALID
|
|
; NOTE: BUFFER CONTENTS INVALIDATED, BUT RETAIN ANY PENDING WRITE
|
|
;
|
|
BLKRES:
|
|
XOR A
|
|
LD (HSTACT),A ; BUFFER NO LONGER VALID
|
|
LD (UNACNT),A ; CLEAR UNALLOC COUNT
|
|
|
|
RET
|
|
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; FLUSH (DE)BLOCKING ALGORITHM - DO PENDING WRITES
|
|
;
|
|
BLKFLSH:
|
|
; CHECK FOR BUFFER WRITTEN (DIRTY)
|
|
LD A,(HSTWRT) ; GET BUFFER WRITTEN FLAG
|
|
OR A
|
|
RET Z ; NOT DIRTY, RETURN WITH A=0 AND Z SET
|
|
|
|
; CLEAR THE BUFFER WRITTEN FLAG (EVEN IF A WRITE ERROR OCCURS)
|
|
XOR A ; Z = 0
|
|
LD (HSTWRT),A ; SAVE IT
|
|
|
|
; DO THE WRITE AND RETURN RESULT
|
|
JP DSK_WRITE
|
|
|
|
#IF WRTCACHE
|
|
|
|
WRT_ALL .EQU 0 ; WRITE TO ALLOCATED
|
|
WRT_DIR .EQU 1 ; WRITE TO DIRECTORY
|
|
WRT_UAL .EQU 2 ; WRITE TO UNALLOCATED
|
|
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; (DE)BLOCKING READ/WRITE ROUTINE. MANAGES PHYSICAL DISK BUFFER AND CALLS
|
|
; PHYSICAL READ/WRITE ROUTINES APPROPRIATELY.
|
|
;
|
|
BLKRW:
|
|
; FIX!!! WE ABORT ON FIRST ERROR, DRI SEEMS TO PASS ERROR STATUS TO THE END!!!
|
|
|
|
; IF WRITE OPERATION, GO TO SPECIAL WRITE PROCESSING
|
|
LD A,(DSKOP) ; GET REQUESTED OPERATION
|
|
CP DOP_WRITE ; WRITE
|
|
JR Z,BLKRW1 ; GO TO WRITE PROCESSING
|
|
|
|
; OTHERWISE, CLEAR OUT ANY SEQUENTIAL, UNALLOC WRITE PROCESSING
|
|
; AND GO DIRECTLY TO MAIN I/O
|
|
XOR A ; ZERO TO A
|
|
LD (WRTYPE),A ; SET WRITE TYPE = 0 (WRT_ALL) TO ENSURE READ OCCURS
|
|
LD (UNACNT),A ; SET UNACNT TO ABORT SEQ WRITE PROCESSING
|
|
|
|
JR BLKRW4 ; GO TO I/O
|
|
|
|
BLKRW1:
|
|
; WRITE PROCESSING
|
|
; CHECK FOR FIRST WRITE TO UNALLOCATED BLOCK
|
|
LD A,(WRTYPE) ; GET WRITE TYPE
|
|
CP WRT_UAL ; IS IT WRITE TO UNALLOC?
|
|
JR NZ,BLKRW2 ; NOPE, BYPASS
|
|
|
|
; INITIALIZE START OF SEQUENTIAL WRITING TO UNALLOCATED BLOCK
|
|
; AND THEN TREAT SUBSEQUENT PROCESSING AS A NORMAL WRITE
|
|
CALL UNA_INI ; INITIALIZE SEQUENTIAL WRITE TRACKING
|
|
XOR A ; A = 0 = WRT_ALL
|
|
LD (WRTYPE),A ; NOW TREAT LIKE WRITE TO ALLOCATED
|
|
|
|
BLKRW2:
|
|
; IF WRTYPE = WRT_ALL AND SEQ WRITE, GOTO BLKRW7 (SKIP READ)
|
|
OR A ; NOTE: A WILL ALREADY HAVE THE WRITE TYPE HERE
|
|
JR NZ,BLKRW3 ; NOT TYPE = 0 = WRT_ALL, SO MOVE ON
|
|
|
|
CALL UNA_CHK ; CHECK FOR CONTINUATION OF SEQ WRITES TO UNALLOCATED BLOCK
|
|
JR NZ,BLKRW3 ; NOPE, ABORT
|
|
|
|
; WE MATCHED EVERYTHING, TREAT AS WRITE TO UNALLOCATED BLOCK
|
|
LD A,WRT_UAL ; WRITE TO UNALLOCATED
|
|
LD (WRTYPE),A ; SAVE WRITE TYPE
|
|
|
|
CALL UNA_INC ; INCREMENT SEQUENTIAL WRITE TRACKING
|
|
JR BLKRW4 ; PROCEED TO I/O PROCESSING
|
|
|
|
BLKRW3:
|
|
; NON-SEQUENTIAL WRITE DETECTED, STOP ANY FURTHER CHECKING
|
|
XOR A ; ZERO
|
|
LD (UNACNT),A ; CLEAR UNALLOCATED WRITE COUNT
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; IS A FLUSH NEEDED HERE???
|
|
; FLUSH CURRENT BUFFER CONTENTS IF NEEDED
|
|
;CALL BLKFLSH ; FLUSH PENDING WRITES
|
|
;RET NZ ; ABORT ON ERROR
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
BLKRW4:
|
|
; START OF ACTUAL I/O PROCESSING
|
|
CALL BLK_XLT ; DO THE LOGICAL TO PHYSICAL MAPPING: SEK... -> XLT...
|
|
CALL BLK_CMP ; IS THE DESIRED PHYSICAL BLOCK IN BUFFER?
|
|
JR Z,BLKRW6 ; BLOCK ALREADY IN ACTIVE BUFFER, NO READ REQUIRED
|
|
|
|
; AT THIS POINT, WE KNOW WE NEED TO READ THE TARGET PHYSICAL SECTOR
|
|
; IT MAY ACTUALLY BE A PREREAD FOR A SUBSEQUENT WRITE, BUT THAT IS OK
|
|
|
|
; FIRST, FLUSH CURRENT BUFFER CONTENTS
|
|
CALL BLKFLSH ; FLUSH PENDING WRITES
|
|
RET NZ ; ABORT ON ERROR
|
|
|
|
; IMPLEMENT THE TRANSLATED VALUES
|
|
CALL BLK_SAV ; SAVE XLAT VALUES: XLT... -> HST...
|
|
|
|
; IF WRITE TO UNALLOC BLOCK, BYPASS READ, LEAVES BUFFER UNDEFINED
|
|
LD A,(WRTYPE)
|
|
CP 2
|
|
JR Z,BLKRW6
|
|
|
|
; DO THE ACTUAL READ
|
|
CALL DSK_READ ; READ PHYSICAL SECTOR INTO BUFFER
|
|
JR Z,BLKRW6 ; GOOD READ, CONTINUE
|
|
|
|
; IF READ FAILED, RESET (DE)BLOCKING ALGORITHM AND RETURN ERROR
|
|
PUSH AF ; SAVE ERROR STATUS
|
|
CALL BLKRES ; INVALIDATE (DE)BLOCKING BUFFER
|
|
POP AF ; RECOVER ERROR STATUS
|
|
RET ; ERROR RETURN
|
|
|
|
BLKRW6:
|
|
; CHECK TYPE OF OPERATIONS, IF WRITE, THEN GO TO WRITE PROCESSING
|
|
LD A,(DSKOP) ; GET PENDING OPERATION
|
|
CP DOP_WRITE ; IS IT A WRITE?
|
|
JR Z,BLKRW7 ; YES, GO TO WRITE PROCESSING
|
|
|
|
; THIS IS A READ OPERATION, WE ALREADY DID THE I/O, NOW JUST DEBLOCK AND RETURN
|
|
CALL BLK_DEBLOCK ; EXTRACT DATA FROM BLOCK
|
|
XOR A ; NO ERROR
|
|
RET ; ALL DONE
|
|
|
|
BLKRW7:
|
|
; THIS IS A WRITE OPERATION, INSERT DATA INTO BLOCK
|
|
CALL BLK_BLOCK ; INSERT DATA INTO BLOCK
|
|
|
|
; MARK THE BUFFER AS WRITTEN
|
|
LD A,TRUE ; BUFFER DIRTY = TRUE
|
|
LD (HSTWRT),A ; SAVE IT
|
|
|
|
; CHECK WRITE TYPE, IF WRT_DIR, FORCE THE PHYSICAL WRITE
|
|
LD A,(WRTYPE) ; GET WRITE TYPE
|
|
CP WRT_DIR ; 1 = DIRECTORY WRITE
|
|
JP Z,BLKFLSH ; FLUSH PENDING WRITES AND RETURN STATUS
|
|
|
|
XOR A ; ALL IS WELL, SET RETURN CODE 0
|
|
RET ; RETURN
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; INITIALIZE TRACKING OF SEQUENTIAL WRITES INTO UNALLOCATED BLOCK
|
|
; SETUP UNA... VARIABLES
|
|
;
|
|
UNA_INI:
|
|
; COPY SEKDSK/TRK/SEC TO UNA...
|
|
LD HL,SEK
|
|
LD DE,UNA
|
|
LD BC,UNASIZ
|
|
LDIR
|
|
|
|
; SETUP UNACNT AND UNASPT
|
|
LD HL,(SEKDPH) ; HL POINTS TO DPH
|
|
LD DE,10 ; OFFSET OF DPB ADDRESS IN DPH
|
|
ADD HL,DE ; DPH POINTS TO DPB ADDRESS
|
|
LD A,(HL)
|
|
INC HL
|
|
LD H,(HL)
|
|
LD L,A ; HL POINTS TO DPB
|
|
LD C,(HL)
|
|
INC HL
|
|
LD B,(HL) ; BC HAS SPT
|
|
LD (UNASPT),BC ; SAVE SECTORS PER TRACK
|
|
DEC HL
|
|
DEC HL ; HL POINTS TO RECORDS PER BLOCK (BYTE IN FRONT OF DPB)
|
|
LD A,(HL) ; GET IT
|
|
LD (UNACNT),A ; SAVE IT
|
|
|
|
; CALL NEWLINE ; *DEBUG*
|
|
; CALL PRTHEXBYTE ; *DEBUG*
|
|
; CALL PC_SPACE ; *DEBUG*
|
|
; CALL PRTHEXWORD ; *DEBUG*
|
|
; CALL PC_SPACE ; *DEBUG*
|
|
; LD BC,(UNASPT) ; *DEBUG*
|
|
; CALL PRTHEXWORD ; *DEBUG*
|
|
|
|
RET
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; CHECK FOR CONTINUATION OF SEQUENTIAL WRITES TO UNALLOCATED BLOCK
|
|
; SEE IF UNACNT > 0 AND UNA... VARIABLES MATCH SEK... VARIABLES
|
|
;
|
|
UNA_CHK:
|
|
LD A,(UNACNT) ; GET THE COUNTER
|
|
OR A
|
|
JR NZ,UNA_CHK1 ; IF NOT DONE WITH BLOCK, KEEP CHECKING
|
|
|
|
; CNT IS NOW ZERO, EXHAUSTED RECORDS IN ONE BLOCK!
|
|
DEC A ; HACK TO SET NZ
|
|
RET ; RETURN WITH NZ
|
|
|
|
UNA_CHK1:
|
|
; COMPARE UNA... VARIABLES WITH SEK... VARIABLES
|
|
LD HL,SEK
|
|
LD DE,UNA
|
|
LD B,UNASIZ
|
|
JR BLK_CMPLOOP
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; INCREMENT THE SEQUENTIAL WRITE TRACKING VARIABLES
|
|
; TO REFLECT THE NEXT RECORD (TRK/SEC) WE EXPECT
|
|
;
|
|
UNA_INC:
|
|
; DECREMENT THE BLOCK RECORD COUNT
|
|
LD HL,UNACNT
|
|
DEC (HL)
|
|
|
|
; INCREMENT THE SECTOR
|
|
LD DE,(UNASEC)
|
|
INC DE
|
|
LD (UNASEC),DE
|
|
|
|
; CHECK FOR END OF TRACK
|
|
LD HL,(UNASPT)
|
|
XOR A
|
|
SBC HL,DE
|
|
RET NZ
|
|
|
|
; HANDLE END OF TRACK
|
|
LD (UNASEC),HL ; SECTOR BACK TO 0 (NOTE: HL=0 AT THIS POINT)
|
|
LD HL,(UNATRK) ; GET CURRENT TRACK
|
|
INC HL ; BUMP IT
|
|
LD (UNATRK),HL ; SAVE IT
|
|
|
|
RET
|
|
#ELSE
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; (DE)BLOCKING READ/WRITE ROUTINE. MANAGES PHYSICAL DISK BUFFER AND CALLS
|
|
; PHYSICAL READ/WRITE ROUTINES APPROPRIATELY.
|
|
;
|
|
BLKRW:
|
|
CALL BLK_XLT ; SECTOR XLAT: SEK... -> XLT...
|
|
CALL BLK_CMP ; IN BUFFER?
|
|
JR Z,BLKRW1 ; YES, BYPASS READ
|
|
CALL BLK_SAV ; SAVE XLAT VALUES: XLT... -> HST...
|
|
LD A,FALSE ; ASSUME FAILURE, INVALIDATE BUFFER
|
|
LD (HSTACT),A ; SAVE IT
|
|
CALL DSK_READ ; READ PHYSICAL SECTOR INTO BUFFER
|
|
RET NZ ; BAIL OUT ON ERROR
|
|
|
|
BLKRW1:
|
|
LD A,(DSKOP) ; GET PENDING OPERATION
|
|
CP DOP_WRITE ; IS IT A WRITE?
|
|
JR Z,BLKRW2 ; YES, GO TO WRITE ROUTINE
|
|
|
|
CALL BLK_DEBLOCK ; EXTRACT DATA FROM BLOCK
|
|
XOR A ; NO ERROR
|
|
RET ; ALL DONE
|
|
|
|
BLKRW2:
|
|
CALL BLK_BLOCK ; INSERT DATA INTO BLOCK
|
|
CALL DSK_WRITE ; WRITE PHYSICAL SECTOR FROM BUFFER
|
|
RET NZ ; BAIL OUT ON ERROR
|
|
|
|
LD A,TRUE ; BUFFER IS NOW VALID
|
|
LD (HSTACT),A ; SAVE IT
|
|
|
|
XOR A ; ALL IS WELL, SET RETURN CODE 0
|
|
RET ; RETURN
|
|
#ENDIF
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; TRANSLATE FROM CP/M DSK/TRK/SEC TO PHYSICAL
|
|
; SEK... -> XLT...
|
|
;
|
|
BLK_XLT:
|
|
; FIRST, DO A BYTE COPY OF SEK... TO XLT...
|
|
LD HL,SEK
|
|
LD DE,XLT
|
|
LD BC,XLTSIZ
|
|
LDIR
|
|
|
|
; NOW UPDATE XLTSEC BASED ON (DE)BLOCKING FACTOR (ALWAYS 4:1)
|
|
LD BC,(SEKSEC) ; SECTOR IS FACTORED DOWN (4:1) DUE TO BLOCKING
|
|
SRL B ; 16 BIT RIGHT SHIFT TWICE TO DIVIDE BY 4
|
|
RR C
|
|
SRL B
|
|
RR C
|
|
LD (XLTSEC),BC
|
|
|
|
RET
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; SAVE RESULTS OF TRANSLATION: XLT... -> HST...
|
|
; IMPLICITLY SETS HSTACT TO TRUE!
|
|
;
|
|
BLK_SAV:
|
|
LD HL,XLT
|
|
LD DE,HST
|
|
LD BC,XLTSIZ
|
|
LDIR
|
|
RET
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; COMPARE RESULTS OF TRANSLATION TO CURRENT BUF (XLT... TO HST...)
|
|
; NOTE THAT HSTACT IS COMPARED TO XLTACT IMPLICITLY! XLTACT IS ALWAYS TRUE, SO
|
|
; HSTACT MUST BE TRUE FOR COMPARE TO SUCCEED.
|
|
;
|
|
BLK_CMP:
|
|
LD HL,XLT
|
|
LD DE,HST
|
|
LD B,XLTSIZ
|
|
BLK_CMPLOOP:
|
|
LD A,(DE)
|
|
CP (HL)
|
|
RET NZ ; BAD COMPARE, RETURN WITH NZ
|
|
INC HL
|
|
INC DE
|
|
DJNZ BLK_CMPLOOP
|
|
RET ; RETURN WITH Z
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; BLOCK DATA - INSERT CPM DMA BUF INTO PROPER PART OF PHYSICAL SECTOR BUFFER
|
|
;
|
|
BLK_BLOCK:
|
|
CALL BLK_SETUP ; SETUP SOURCE AND DESTINATION
|
|
EX DE,HL ; SWAP HL/DE FOR BLOCK OPERATION
|
|
LD BC,128 ; DMA BUFFER SIZE
|
|
LDIR ; COPY THE DATA
|
|
RET
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; DEBLOCK DATA - EXTRACT DESIRED CPM DMA BUF FROM PHYSICAL SECTOR BUFFER
|
|
;
|
|
BLK_DEBLOCK:
|
|
CALL BLK_SETUP ; SETUP SOURCE AND DESTINATION
|
|
LD BC,128 ; DMA BUFFER SIZE
|
|
LDIR ; COPY THE DATA
|
|
RET
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; SETUP SOURCE AND DESTINATION POINTERS FOR BLOCK COPY OPERATION
|
|
; AT EXIT, HL = ADDRESS OF DESIRED BLOCK IN SECTOR BUFFER, DE = DMA
|
|
;
|
|
BLK_SETUP:
|
|
LD BC,(SEKSEC)
|
|
LD A,C
|
|
AND 3 ; A = INDEX OF CPM BUF IN SEC BUF
|
|
RRCA ; MULTIPLY BY 64
|
|
RRCA
|
|
LD E,A ; INTO LOW ORDER BYTE OF DESTINATION
|
|
LD D,0 ; HIGH ORDER BYTE IS ZERO
|
|
LD HL,(BUFADR) ; HL = START OF SEC BUF
|
|
ADD HL,DE ; ADD IN COMPUTED OFFSET
|
|
ADD HL,DE ; HL NOW = INDEX * 128 (SOURCE)
|
|
LD DE,(DMAADR) ; DE = DESTINATION = DMA BUF
|
|
RET
|
|
;
|
|
;==================================================================================================
|
|
; CHARACTER DEVICE INTERFACE
|
|
;==================================================================================================
|
|
;
|
|
; ROUTING FOR CHARACTER DEVICE FUNCTIONS
|
|
; A = INDEX INTO CIO_MAP BASED ON IOBYTE BIOS REQUEST
|
|
; B = FUNCTION REQUESTED: BF_CIO(IN/OUT/IST/OST)
|
|
; E = CHARACTER (IF APPLICABLE TO FUNCTION)
|
|
; HL = ADDRESS OF COMPLETION ROUTINE
|
|
;
|
|
CIO_DISP:
|
|
PUSH HL ; PUT COMPLETION ROUTINE ON STACK
|
|
|
|
; LOOKUP IOBYTE MAPPED DEVICE CODE
|
|
; WARNING: CIO_MAP MUST NOT CROSS PAGE BOUNDARY!!!
|
|
AND 0FH ; ISOLATE INDEX INTO CIO_MAP
|
|
|
|
LD HL,CIO_MAP ; HL = ADDRESS OF CIO_MAP
|
|
ADD A,L ; ADD LOW BYTE TO OFFSET
|
|
LD L,A ; GET RESULT BACK TO L
|
|
|
|
LD A,(HL) ; LOOKUP DEVICE CODE
|
|
LD C,A ; SAVE IN C FOR BIOS USAGE
|
|
|
|
CP CIODEV_BAT ; CHECK FOR SPECIAL DEVICE (BAT, NUL)
|
|
JR NC,CIO_DISP1 ; HANDLE SPECIAL DEVICE
|
|
RST 08 ; OTHERWISE HANDLE VIA HBIOS
|
|
RET ; RETURN VIA COMPLETION ROUTINE SET AT START
|
|
|
|
CIO_DISP1:
|
|
; HANDLE SPECIAL DEVICES
|
|
AND 0F0H ; ISOLATE DEVICE
|
|
CP CIODEV_BAT ; BAT: ?
|
|
JR Z,CIO_BAT ; YES, GO TO BAT DEVICE HANDLER
|
|
CP CIODEV_NUL ; NUL: ?
|
|
JR Z,CIO_NUL ; YES, GO TO NUL DEVICE HANDLER
|
|
CALL PANIC ; SOMETHING BAD HAPPENED
|
|
;
|
|
; BAT: IS A PSEUDO DEVICE REDIRECTING INPUT TO READER AND OUTPUT TO LIST
|
|
;
|
|
CIO_BAT:
|
|
LD C,E ; PUT CHAR BACK IN C
|
|
LD A,B ; GET REQUESTED FUNCTION
|
|
CP BF_CIOIN ; INPUT?
|
|
JP Z,READER ; -> READER
|
|
CP BF_CIOIST ; INPUT STATUS?
|
|
JP Z,READERST ; -> READER
|
|
CP BF_CIOOUT ; OUTPUT?
|
|
JP Z,LIST ; -> LIST
|
|
CP BF_CIOOST ; OUTPUT STATUS?
|
|
JP Z,LISTST ; -> LIST
|
|
CALL PANIC
|
|
;
|
|
; NUL: IS A DUMMY DEVICE THAT DOES NOTHING
|
|
;
|
|
CIO_NUL:
|
|
LD A,B ; FUNCTION
|
|
CP BF_CIOIN
|
|
JR Z,NUL_IN
|
|
CP BF_CIOIST
|
|
JR Z,NUL_IST
|
|
CP BF_CIOOUT
|
|
JR Z,NUL_OUT
|
|
CP BF_CIOOST
|
|
JR Z,NUL_OST
|
|
CALL PANIC
|
|
;
|
|
NUL_IN:
|
|
LD E,$1B ; RETURN EOF
|
|
NUL_OUT:
|
|
RET
|
|
;
|
|
NUL_IST:
|
|
NUL_OST:
|
|
OR $FF ; A=$FF & NZ SET
|
|
RET
|
|
;
|
|
;==================================================================================================
|
|
; PHYSICAL DISK INTERFACE
|
|
;==================================================================================================
|
|
;
|
|
DSK_DISP:
|
|
LD A,C ; GET DEVICE/UNIT TO A
|
|
AND 0F0H ; ISOLATE DEVICE
|
|
CP DIODEV_MD ; MEMORY DISK? (RAM/ROM)
|
|
JP Z,MD_DISPATCH ; YES, GO TO MEMORY DISK DISPATCH
|
|
|
|
RST 08 ; OTHERWISE, HANDLE IN HBIOS
|
|
RET ; AND RETURN
|
|
;
|
|
; LOOKUP DPH BASED ON DPM DRIVE NUMBER
|
|
; ENTER WITH C=CPM DRIVE NUMBER
|
|
; RETURNS WITH HL = DPH ADDRESS (0 ON ERROR)
|
|
; A=0 ON SUCCESS, A=1 ON ERROR
|
|
; NOTE: DE IS NOT MODIFIED!!!
|
|
;
|
|
DSK_GETDPH:
|
|
; CHECK FOR INVALID DRIVE NUMBER
|
|
LD A,C ; A = CPM DRIVE NUMBER
|
|
CP DPH_CNT ; COMPARE TO NUMBER OF DRIVES CONFIGURED
|
|
JR C,DSK_GETDPH1 ; IN RANGE, CONTINUE
|
|
XOR A ; ZERO ACCUMULATOR
|
|
LD H,A ; HL = 0 FOR FAILURE
|
|
LD L,A ; HL = 0 FOR FAILURE
|
|
INC A ; A = 1, NZ SET FOR INVALID DRIVE
|
|
RET ; FAILURE RETURN
|
|
|
|
; LOOKUP DPH FOR CPM DRIVE
|
|
; WARNING: DPH_MAP MUST NOT CROSS PAGE BOUNDARY!!!
|
|
DSK_GETDPH1:
|
|
LD A,C ; GET CPM DRIVE NUMBER BACK
|
|
LD HL,DPH_MAP ; POINT TO START OF DPH_MAP
|
|
RLCA ; DOUBLE A TO USE AS OFFSET INTO DPH_MAP
|
|
ADD A,L ; ADD LOW BYTE TO OFFSET
|
|
LD L,A ; HL = ADDRESS OF DESIRED ENTRY IN DPH_MAP
|
|
LD A,(HL) ; DEREFERENCE
|
|
INC HL ; HL
|
|
LD H,(HL) ; TO GET
|
|
LD L,A ; DPHADR IN HL
|
|
|
|
; FILL IN DEVICE/UNIT
|
|
DEC HL ; POINT TO DEVICE CODE (BYTE IN FRONT OF DPH)
|
|
LD B,(HL) ; B = DEVICE/UNIT
|
|
INC HL ; HL = DPH AGAIN
|
|
|
|
; RETURN SUCCESS
|
|
XOR A ; A=0, Z SET
|
|
RET ; SUCCESS RETURN
|
|
;
|
|
; SET HL TO START OF LU DATA FOR DRIVE GIVEN DRIVE DPH POINTER IN HL
|
|
; ENTER WITH HL=POINTER TO DPH OF DRIVE
|
|
; RETURNS WITH HL = LU DATA ADDRESS (0 ON NO SUPPORT)
|
|
; Z SET IF LU SUPPORT, NZ IF NOT
|
|
;
|
|
DSK_GETLU:
|
|
; CHECK FOR LU SUPPORT
|
|
LD DE,16 ; DPH + 16 IS "LU' MARKER LOCATION
|
|
ADD HL,DE ; HL POINTS TO MARKER LOCATION NOW
|
|
LD A,(HL) ; LOAD FIRST BYTE
|
|
INC HL ; POINT TO NEXT BYTE
|
|
CP 'L' ; IS IT 'L'
|
|
JR NZ,DSK_GETLU1 ; NOPE, BAIL OUT
|
|
LD A,(HL) ; LOAD SECOND BYTE
|
|
INC HL ; POINT TO NEXT BYTE
|
|
CP 'U' ; IS SECOND BYTE 'U'?
|
|
JR NZ,DSK_GETLU1 ; NOPE, BAIL OUT
|
|
RET ; SUCCESS, EXIT WITH Z SET
|
|
|
|
DSK_GETLU1:
|
|
LD HL,0 ; OTHERWISE, HL=0
|
|
RET ; AND RETURN WITH NZ SET
|
|
;
|
|
;
|
|
;
|
|
DSK_SELECT:
|
|
; C HAS CPM DRIVE, SAVE IT
|
|
LD A,C
|
|
LD (SEKDSK),A
|
|
|
|
; LOOKUP DPH (INCLUDES INVALID DRIVE CHECK)
|
|
CALL DSK_GETDPH ; HL = DPH (0 IF INVALID DRIVE)
|
|
RET NZ ; A=1 AND NZ SET IF INVALID DRIVE
|
|
|
|
; FIX: WE COULD RETURN DUE TO INVALID DRIVE WITH ALL OF THE
|
|
; REMAINING SEK... VARS SET TO PREVIOUS DRIVE?
|
|
|
|
; SAVE CURRENT DEVICE/UNIT AND DPH ADDRESS
|
|
LD A,B ; A = DEVIE/UNIT
|
|
LD (SEKDU),A ; SAVE DEVICE/UNIT
|
|
LD (SEKDPH),HL ; SAVE DPH POINTER
|
|
|
|
; SETUP IX AS INDEX INTO DPH
|
|
PUSH IX ; SAVE IX
|
|
LD IX,(SEKDPH) ; IX=DPH ADDRESS
|
|
|
|
; CHECK IF THIS IS LOGIN, IF NOT, BYPASS MEDIA DETECTION
|
|
; FIX: WHAT IF PREVIOUS MEDIA DETECTION FAILED???
|
|
BIT 0,E ; TEST DRIVE LOGIN BIT
|
|
JR NZ,DSK_SELECT2 ; BYPASS MEDIA DETECTION
|
|
;
|
|
DSK_SELECT1:
|
|
; DETERMINE MEDIA IN DRIVE
|
|
LD A,(SEKDU) ; GET DEVICE/UNIT
|
|
LD C,A ; STORE IN C
|
|
LD B,BF_DIOMED ; DRIVER FUNCTION = DISK MEDIA
|
|
CALL DSK_DISP ; CALL DRIVER, RETURNS WITH A=MEDIA ID
|
|
|
|
; CHECK FOR NO MEDIA
|
|
LD HL,0 ; ASSUME NO MEDIA FAILURE, HL = 0
|
|
OR A ; SET FLAGS
|
|
JR Z,DSK_SELECT4 ; IF Z, NO MEDIA, BAIL OUT WITH HL=0
|
|
|
|
; A HAS MEDIA ID, SET HL TO CORRESPONDING DPB_MAP ENTRY
|
|
LD HL,DPB_MAP ; HL = DPB_MAP
|
|
RLCA ; DPB_MAP ENTRIES ARE 2 BYTES EACH
|
|
ADD A,L ; ADD LOW BYTE TO OFFSET
|
|
LD L,A ; GET RESULT BACK TO L
|
|
|
|
; LOOKUP THE ACTUAL DPB ADDRESS NOW
|
|
LD E,(HL) ; DEREFERENCE HL...
|
|
INC HL ; INTO DE...
|
|
LD D,(HL) ; DE = ADDRESS OF DESIRED DPB
|
|
|
|
; PLUG APPROPRIATE DPB INTO THE ACTIVE DPH
|
|
LD (IX+10),E ; DPH.DPB := DPB ADDRESS (LSB)
|
|
LD (IX+11),D ; DPH.DPB := DPB ADDRESS (MSB)
|
|
|
|
DSK_SELECT2:
|
|
; CHECK FOR SLICE SUPPORT, BYPASS LU OFFSET CALC IF NOT
|
|
LD HL,(SEKDPH) ; LOAD DPH
|
|
CALL DSK_GETLU ; CHECK FOR LU SUPPORT
|
|
JR NZ,DSK_SELECT3 ; IF NOT (NZ), BYPASS LU OFFSET CALC
|
|
|
|
; RECOMPUTE TRACK OFFSET BASED ON SLICE NUMBER
|
|
LD E,65 ; FIX: FIXME!!! HARDCODED!!! E = TRACKS PER SLICE
|
|
LD H,(IX+18) ; H = SLICE VALUE
|
|
CALL MULT8 ; HL = TOTAL OFFSET
|
|
|
|
DSK_SELECT3:
|
|
LD (SEKOFF),HL ; SAVE LU TRACK OFFSET
|
|
LD HL,(SEKDPH) ; HL = DPH ADDRESS FOR CP/M
|
|
|
|
DSK_SELECT4:
|
|
POP IX ; RESTORE IX
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
DSK_STATUS:
|
|
; C HAS CPM DRIVE, LOOKUP DEVICE/UNIT AND CHECK FOR INVLAID DRIVE
|
|
CALL DSK_GETDPH ; B = DEVICE/UNIT
|
|
RET NZ ; INVALID DRIVE ERROR
|
|
|
|
; VALID DRIVE, DISPATCH TO DRIVER
|
|
LD C,B ; C=DEVICE/UNIT
|
|
LD B,BF_DIOST ; SET B = FUNCTION: STATUS
|
|
JP DSK_DISP ; DISPATCH
|
|
;
|
|
;
|
|
;
|
|
DSK_READ:
|
|
; SET B = FUNCTION: READ
|
|
LD B,BF_DIORD
|
|
JR DSK_IO
|
|
;
|
|
;
|
|
;
|
|
DSK_WRITE:
|
|
; SET B = FUNCTION: WRITE
|
|
LD B,BF_DIOWR
|
|
JR DSK_IO
|
|
;
|
|
;
|
|
;
|
|
DSK_IO:
|
|
; SET HL=TRACK (ADD IN TRACK OFFSET)
|
|
LD DE,(HSTOFF) ; DE = TRACK OFFSET FOR LU SUPPORT
|
|
LD HL,(HSTTRK) ; HL = TRACK #
|
|
ADD HL,DE ; HL = TRACK # TO READ TAKING LU SUPPORT INTO ACCOUNT
|
|
; SET DE=SECTOR
|
|
LD DE,(HSTSEC) ; DE = SECTOR #
|
|
; SET C = DEVICE/UNIT
|
|
LD A,(HSTDU) ; LOAD DEVICE/UNIT VALUE
|
|
LD C,A ; SAVE IN C
|
|
; DISPATCH TO DRIVER
|
|
CALL DSK_DISP ; CALL DRIVER
|
|
OR A ; SET FLAGS BASED ON RESULT
|
|
RET
|
|
;
|
|
;==================================================================================================
|
|
; IN MEMORY DISK DRIVERS (ROM/RAM)
|
|
;==================================================================================================
|
|
;
|
|
; USES ROM/RAM STORAGE NOT USED BY SYSTEM/OS FOR DISK STORAGE
|
|
; ROM DRIVE:
|
|
; FIRST 32KB OF ROM RESERVED FOR SYSTEM BOOT AREA. REMAINDER IS ALLOCATED
|
|
; AS READ-ONLY DISK STORAGE.
|
|
; RAM DRIVE:
|
|
; FIRST AND LAST 32KB OF RAM IS RESERVED AND MAPPED TO FIRST AND LAST 32KB
|
|
; OF CPU MEMORY SPACE (FOR 64KB TOTAL). EVERYTHING ELSE IS ALLOCATED AS
|
|
; READ/WRITE DISK STORAGE.
|
|
; ROUTINES BELOW TRANSLATE REQUESTS FOR RAM/ROM STORAGE ACCESS BY CP/M BY
|
|
; TEMPORARILY MAPPING RAM/ROM INTO LOWER 32KB OF CPU MEMORY SPACE AND COPYING
|
|
; THE REQUESTED 128 BYTE BLOCK INTO THE CP/M DMA BUFFER.
|
|
;
|
|
MD_DISPATCH:
|
|
LD A,B ; GET REQUESTED FUNCTION
|
|
AND $0F
|
|
JR Z,MD_READ
|
|
DEC A
|
|
JR Z,MD_WRITE
|
|
DEC A
|
|
JR Z,MD_READY
|
|
DEC A
|
|
JR Z,MD_SELECT
|
|
CALL PANIC
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
MD_INIT:
|
|
;
|
|
; INITIALIZE RAM DISK BY FILLING DIRECTORY WITH 'E5' BYTES
|
|
; FILL FIRST 8K OF RAM DISK TRACK 1 WITH 'E5'
|
|
;
|
|
#IF (CLRRAMDISK != CLR_NEVER)
|
|
LD A,2 ; START OF RAM DISK (SECOND 32KB)
|
|
CALL RAMPG ; SELECT RAM DISK
|
|
|
|
#IF (CLRRAMDISK == CLR_AUTO)
|
|
; CHECK FIRST 32 DIRECTORY ENTRIES. IF ANY START WITH AN INVALID
|
|
; VALUE, INIT THE RAM DISK. VALID ENTRIES ARE E5 (EMPTY ENTRY) OR
|
|
; 0-15 (USER NUMBER).
|
|
LD HL,0
|
|
LD DE,32
|
|
LD B,32
|
|
CLRRAM0:
|
|
LD A,(HL)
|
|
CP 0E5H
|
|
JR Z,CLRRAM1 ; E5 IS VALID
|
|
CP 16
|
|
JR C,CLRRAM1 ; 0-15 IS ALSO VALID
|
|
JR CLRRAM2 ; INVALID ENTRY! JUMP TO INIT
|
|
CLRRAM1:
|
|
ADD HL,DE ; LOOP FOR 32 ENTRIES
|
|
DJNZ CLRRAM0
|
|
; JR CLRRAM2 ; *DEBUG*
|
|
JR CLRRAM3 ; ALL ENTRIES VALID, BYPASS INIT
|
|
CLRRAM2:
|
|
#ENDIF
|
|
CALL RAMPGZ
|
|
LD DE,STR_INITRAMDISK
|
|
CALL WRITESTR
|
|
LD A,2
|
|
CALL RAMPG
|
|
|
|
LD HL,0 ; SOURCE OF FILL IN HL
|
|
LD BC,2000H - 1 ; LENGTH OF FILL - 1
|
|
LD A,0E5H ; FILL VALUE IN A
|
|
LD E,L ; DE = HL
|
|
LD D,H ; "
|
|
INC DE ; THEN OFFSET BY ONE
|
|
LD (HL),A ; FILL INITIAL BYTE
|
|
LDIR ; COMPLETE THE FILL
|
|
CLRRAM3:
|
|
CALL RAMPGZ
|
|
#ENDIF
|
|
RET
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
MD_READY:
|
|
LD A,TRUE
|
|
RET
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
MD_SELECT:
|
|
LD A,C
|
|
AND 0FH
|
|
ADD A,MID_MDROM
|
|
RET
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
MD_READ:
|
|
CALL MD_PGSEL ; SET PAGER BASED ON DRIVE AND TRACK
|
|
LD DE,(BUFADR) ; SETUP SECTOR BUF AS DESTINATION
|
|
CALL MD_SECADR ; SETUP RAM/ROM PAGE ADDRESS IN HL
|
|
CALL MD_DMACPY ; MOVE SECTOR TO SECBUF
|
|
CALL RAMPGZ ; RESTORE NORMAL 32K LOWER CPU RAM
|
|
LD DE,(DMAADR) ; SETUP FOR COPY TO DMA ADDRESS
|
|
LD HL,(BUFADR) ; FROM BUFFER
|
|
CALL MD_DMACPY ; COPY FROM BUF TO DMA
|
|
LD A,00H ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
MD_WRITE:
|
|
; CHECK FOR WRITE ACCESS TO ROM
|
|
LD A,(SEKDU) ; GET DRIVE
|
|
OR A ; DEVICE = 0, UNIT = 0 MEANS ROM DISK (READ ONLY!)
|
|
JR Z,MD_RDONLY
|
|
|
|
LD DE,(BUFADR) ; GET SECTOR BUF ADDRESS
|
|
LD HL,(DMAADR) ; GET DMA BUF ADDRESS
|
|
CALL MD_DMACPY ; MOVE FROM DMA BUF TO SECTOR BUF
|
|
CALL MD_PGSEL ; SET PAGER BASED ON DRIVE AND TRACK
|
|
CALL MD_SECADR ; SETUP PAGE ADDRESS IN HL
|
|
LD DE,(BUFADR) ; SECTOR BUF ADDRESS IN DE
|
|
EX DE,HL ; REVERSE THEM TO...
|
|
CALL MD_DMACPY ; COPY FROM SECTOR BUF TO RAM PAGE
|
|
CALL RAMPGZ ; RESTORE NORMAL 32K LOWER CPU RAM
|
|
LD A,00H ; SIGNAL SUCCESS
|
|
RET
|
|
|
|
MD_RDONLY:
|
|
LD DE,STR_READONLY ; SET DE TO START OF ERROR MESSAGE
|
|
CALL WRITESTR ; PRINT ERROR MESSAGE
|
|
LD A,1 ; SEND BAD SECTOR ERROR BACK
|
|
RET ; BDOS WILL ALSO PRINT ITS OWN ERROR MESSAGE
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
MD_SECADR:
|
|
; DETERMINE MEMORY ADDRESS CORRESPONDING TO CURRENT SECTOR
|
|
; SECTOR SIZE = 128, SO JUST MULTIPLY BY 128
|
|
; RETURNS ADDRESS IN HL
|
|
LD HL,(SEKSEC) ; GET SECTOR INTO HL
|
|
LD B,7
|
|
MD_SECADR1:
|
|
ADD HL,HL
|
|
DJNZ MD_SECADR1
|
|
RET
|
|
;__________________________________________________________________________________________________
|
|
MD_PGSEL:
|
|
; SELECT MEMORY PAGE BASED ON DRIVE AND TRACK
|
|
; DRIVE UNIT 0 = ROM, OTHERWISE RAM
|
|
|
|
LD A,(SEKTRK)
|
|
INC A ; OFFSET PAST RESERVED 32KB SYSTEM AREA OF RAM/ROM!
|
|
INC A ; OFFSET ANOTHER 32K PAST DRIVER BANK
|
|
LD C,A
|
|
LD A,(SEKDU)
|
|
OR A
|
|
LD A,C
|
|
JP Z,ROMPG ; DEVICE/UNIT = 0? YES, ROM PAGE
|
|
JP RAMPG ; ELSE RAM PAGE
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
MD_DMACPY:
|
|
; COPIES ONE CPM SECTOR FROM ONE MEMORY ADDRESS TO ANOTHER
|
|
; INPUT DE=SOURCE ADDRESS, HL=TARGET ADDRESS, USES BC
|
|
LD BC,128 ; BC IS COUNTER FOR FIXED SIZE TRANSFER (128 BYTES)
|
|
LDIR ; TRANSFER
|
|
RET
|
|
;
|
|
#INCLUDE "memmgr.asm"
|
|
;
|
|
;==================================================================================================
|
|
; UTILITY FUNCTIONS
|
|
;==================================================================================================
|
|
;
|
|
#DEFINE CIOMODE_CBIOS
|
|
ORG_UTIL .EQU $
|
|
#INCLUDE "util.asm"
|
|
SIZ_UTIL .EQU $ - ORG_UTIL
|
|
.ECHO "UTIL occupies "
|
|
.ECHO SIZ_UTIL
|
|
.ECHO " bytes.\n"
|
|
;
|
|
;==================================================================================================
|
|
; DIAGNOSTICS
|
|
;==================================================================================================
|
|
;
|
|
#IF DSKTRACE
|
|
;__________________________________________________________________________________________________
|
|
PRTSELDSK:
|
|
CALL NEWLINE
|
|
PUSH BC
|
|
PUSH DE
|
|
LD B,E
|
|
LD DE,STR_SELDSK
|
|
CALL WRITESTR
|
|
CALL PC_SPACE
|
|
LD DE,STR_DSK
|
|
LD A,C
|
|
CALL PRTHEXBYTE
|
|
CALL PC_SPACE
|
|
CALL PC_LBKT
|
|
LD A,B
|
|
CALL PRTHEXBYTE
|
|
CALL PC_RBKT
|
|
POP DE
|
|
POP BC
|
|
RET
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
PRTHOME:
|
|
CALL NEWLINE
|
|
LD DE,STR_HOME
|
|
CALL WRITESTR
|
|
RET
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
PRTDSKOP:
|
|
|
|
LD (XSTKSAV),SP
|
|
LD SP,XSTK
|
|
|
|
CALL NEWLINE
|
|
LD A,(DSKOP)
|
|
LD DE,STR_READ
|
|
CP DOP_READ
|
|
CALL Z,WRITESTR
|
|
LD DE,STR_WRITE
|
|
CP DOP_WRITE
|
|
CALL Z,WRITESTR
|
|
LD A,C
|
|
CALL Z,PRTHEXBYTE
|
|
LD DE,STR_DSK
|
|
CALL WRITESTR
|
|
LD A,(SEKDSK)
|
|
CALL PRTHEXBYTE
|
|
LD DE,STR_TRK
|
|
CALL WRITESTR
|
|
LD BC,(SEKTRK)
|
|
CALL PRTHEXWORD
|
|
LD DE,STR_SEC
|
|
CALL WRITESTR
|
|
LD BC,(SEKSEC)
|
|
CALL PRTHEXWORD
|
|
|
|
LD SP,(XSTKSAV)
|
|
|
|
RET
|
|
|
|
RET
|
|
|
|
XSTKSAV .DW 0
|
|
.FILL $20
|
|
XSTK .EQU $
|
|
;
|
|
STR_SELDSK .DB "SELDSK$"
|
|
STR_HOME .DB "HOME$"
|
|
STR_READ .DB "READ$"
|
|
STR_WRITE .DB "WRITE$"
|
|
STR_DSK .DB " DSK=$"
|
|
STR_TRK .DB " TRK=$"
|
|
STR_SEC .DB " SEC=$"
|
|
;
|
|
#ENDIF
|
|
;
|
|
;==================================================================================================
|
|
; DATA
|
|
;==================================================================================================
|
|
;
|
|
STR_BANNER .DB OSLBL, " for ", PLATFORM_NAME, " (CBIOS v", BIOSVER, ")$"
|
|
VAR_LOC .DB VARIANT
|
|
TST_LOC .DB TIMESTAMP
|
|
;
|
|
STR_INITRAMDISK .DB "\r\nFormatting RAMDISK...$"
|
|
STR_READONLY .DB "\r\nCBIOS Err: Read Only Drive$"
|
|
STR_STALE .DB "\r\nCBIOS Err: Stale Drive$"
|
|
;
|
|
SECADR: .DW 0 ; ADDRESS OF SECTOR IN ROM/RAM PAGE
|
|
DEFDRIVE .DB 0 ; DEFAULT DRIVE
|
|
;
|
|
; DOS DISK VARIABLES
|
|
;
|
|
DSKOP: .DB 0 ; DISK OPERATION (DOP_READ/DOP_WRITE)
|
|
WRTYPE: .DB 0 ; WRITE TYPE (0=NORMAL, 1=DIR (FORCE), 2=FIRST RECORD OF BLOCK)
|
|
DMAADR: .DW 0 ; DIRECT MEMORY ADDRESS
|
|
HSTWRT: .DB 0 ; TRUE = BUFFER IS DIRTY
|
|
BUFADR: .DW $8000 ; ADDRESS OF PHYSICAL SECTOR BUFFER (DEFAULT MATCHES HBIOS)
|
|
;
|
|
; DISK I/O REQUEST PENDING
|
|
;
|
|
SEK:
|
|
SEKDSK: .DB 0 ; DISK NUMBER 0-15
|
|
SEKTRK: .DW 0 ; TWO BYTES FOR TRACK # (LOGICAL)
|
|
SEKSEC: .DW 0 ; TWO BYTES FOR SECTOR # (LOGICAL)
|
|
SEKDU: .DB 0 ; DEVICE/UNIT
|
|
SEKDPH: .DW 0 ; ADDRESS OF ACTIVE (SELECTED) DPH
|
|
SEKOFF: .DW 0 ; TRACK OFFSET IN EFFECT FOR LU
|
|
SEKACT: .DB TRUE ; ALWAYS TRUE!
|
|
;
|
|
; RESULT OF TRANSLATION CPM TO PHYSICAL TRANSLATION
|
|
;
|
|
XLT:
|
|
XLTDSK .DB 0
|
|
XLTTRK .DW 0
|
|
XLTSEC .DW 0
|
|
XLTDU .DB 0
|
|
XLTDPH .DW 0
|
|
XLTOFF: .DW 0
|
|
XLTACT .DB TRUE ; ALWAYS TRUE!
|
|
;
|
|
XLTSIZ .EQU $ - XLT
|
|
;
|
|
; DSK/TRK/SEC IN BUFFER (VALID WHEN HSTACT=TRUE)
|
|
;
|
|
HST:
|
|
HSTDSK .DB 0 ; DISK IN BUFFER
|
|
HSTTRK .DW 0 ; TRACK IN BUFFER
|
|
HSTSEC .DW 0 ; SECTOR IN BUFFER
|
|
HSTDU .DB 0 ; DEVICE/UNIT IN BUFFER
|
|
HSTDPH .DW 0 ; CURRENT DPH ADDRESS
|
|
HSTOFF .DW 0 ; TRACK OFFSET IN EFFECT FOR LU
|
|
HSTACT .DB 0 ; TRUE = BUFFER HAS VALID DATA
|
|
;
|
|
; SEQUENTIAL WRITE TRACKING FOR UNALLOCATED BLOCK
|
|
;
|
|
UNA:
|
|
UNADSK: .DB 0 ; DISK NUMBER 0-15
|
|
UNATRK: .DW 0 ; TWO BYTES FOR TRACK # (LOGICAL)
|
|
UNASEC: .DW 0 ; TWO BYTES FOR SECTOR # (LOGICAL)
|
|
;
|
|
UNASIZ .EQU $ - UNA
|
|
;
|
|
UNACNT: .DB 0 ; COUNT DOWN UNALLOCATED RECORDS IN BLOCK
|
|
UNASPT: .DW 0 ; SECTORS PER TRACK
|
|
;
|
|
DIRBF: .FILL 128,00H ; SCRATCH DIRECTORY AREA
|
|
;
|
|
; DRIVER STORAGE
|
|
;
|
|
; MEMORY DISK 00: ROM DISK
|
|
;
|
|
ROMBLKS .EQU ((ROMSIZE - 64) / 2)
|
|
;
|
|
.DB DIODEV_MD + 0
|
|
MDDPH0 .DW 0000,0000
|
|
.DW 0000,0000
|
|
.DW DIRBF,DPB_ROM
|
|
.DW MDCSV0,MDALV0
|
|
;
|
|
CKS_ROM .EQU 0 ; CKS: 0 FOR NON-REMOVABLE MEDIA
|
|
ALS_ROM .EQU ((ROMBLKS + 7) / 8) ; ALS: BLKS / 8 (ROUNDED UP)
|
|
;
|
|
; MEMORY DISK 01: RAM DISK
|
|
;
|
|
RAMBLKS .EQU ((RAMSIZE - 96) / 2)
|
|
;
|
|
.DB DIODEV_MD + 1
|
|
MDDPH1 .DW 0000,0000
|
|
.DW 0000,0000
|
|
.DW DIRBF,DPB_RAM
|
|
.DW MDCSV1,MDALV1
|
|
;
|
|
CKS_RAM .EQU 0 ; CKS: 0 FOR NON-REMOVABLE MEDIA
|
|
ALS_RAM .EQU ((RAMBLKS + 7) / 8) ; ALS: BLKS / 8 (ROUNDED UP)
|
|
;
|
|
MDCSV0: .FILL 0 ; NO DIRECTORY CHECKSUM, NON-REMOVABLE DRIVE
|
|
MDALV0: .FILL ALS_ROM,00H ; MAX OF 512 DATA BLOCKS
|
|
MDCSV1: .FILL 0 ; NO DIRECTORY CHECKSUM, NON-REMOVABLE DRIVE
|
|
MDALV1: .FILL ALS_RAM,00H ; MAX OF 256 DATA BLOCKS
|
|
;
|
|
#IF (FDENABLE)
|
|
ORG_FD_DATA .EQU $
|
|
#INCLUDE "fd_data.asm"
|
|
SIZ_FD_DATA .EQU $ - ORG_FD_DATA
|
|
.ECHO "FD_DATA occupies "
|
|
.ECHO SIZ_FD_DATA
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
|
|
#IF (IDEENABLE)
|
|
ORG_IDE_DATA .EQU $
|
|
#INCLUDE "ide_data.asm"
|
|
SIZ_IDE_DATA .EQU $ - ORG_IDE_DATA
|
|
.ECHO "IDE_DATA occupies "
|
|
.ECHO SIZ_IDE_DATA
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
|
|
#IF (PPIDEENABLE)
|
|
ORG_PPIDE_DATA .EQU $
|
|
#INCLUDE "ppide_data.asm"
|
|
SIZ_PPIDE_DATA .EQU $ - ORG_PPIDE_DATA
|
|
.ECHO "PPIDE_DATA occupies "
|
|
.ECHO SIZ_PPIDE_DATA
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
|
|
#IF (SDENABLE)
|
|
ORG_SD_DATA .EQU $
|
|
#INCLUDE "sd_data.asm"
|
|
SIZ_SD_DATA .EQU $ - ORG_SD_DATA
|
|
.ECHO "SD_DATA occupies "
|
|
.ECHO SIZ_SD_DATA
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
|
|
#IF (PRPENABLE & PRPSDENABLE)
|
|
ORG_PRPSD_DATA .EQU $
|
|
#INCLUDE "prp_data.asm"
|
|
SIZ_PRPSD_DATA .EQU $ - ORG_PRPSD_DATA
|
|
.ECHO "PRPSD_DATA occupies "
|
|
.ECHO SIZ_PRPSD_DATA
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
#IF (PPPENABLE & PPPSDENABLE)
|
|
ORG_PPPSD_DATA .EQU $
|
|
#INCLUDE "ppp_data.asm"
|
|
SIZ_PPPSD_DATA .EQU $ - ORG_PPPSD_DATA
|
|
.ECHO "PPPSD_DATA occupies "
|
|
.ECHO SIZ_PPPSD_DATA
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
#IF (HDSKENABLE)
|
|
ORG_HDSK_DATA .EQU $
|
|
#INCLUDE "hdsk_data.asm"
|
|
SIZ_HDSK_DATA .EQU $ - ORG_HDSK_DATA
|
|
.ECHO "HDSK_DATA occupies "
|
|
.ECHO SIZ_HDSK_DATA
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
; DISK PARAMETER BLOCKS
|
|
;
|
|
; BLS BSH BLM EXM (DSM<256) EXM (DSM>255)
|
|
; ---------- --- --- ------------- -------------
|
|
; 1,024 3 7 0 N/A
|
|
; 2,048 4 15 1 0
|
|
; 4,096 5 31 3 1
|
|
; 8,192 6 63 7 3
|
|
; 16,384 7 127 15 7
|
|
;
|
|
; AL0/1: EACH BIT SET ALLOCATES A BLOCK OF DIR ENTRIES. EACH DIR ENTRY
|
|
; IS 32 BYTES. BIT COUNT = (((DRM + 1) * 32) / BLS)
|
|
;
|
|
; CKS = (DIR ENT / 4), ZERO FOR NON-REMOVABLE MEDIA
|
|
;
|
|
; ALS = TOTAL BLKS (DSM + 1) / 8
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; ROM DISK: 256 SECS/TRK, 128 BYTES/SEC
|
|
; BLOCKSIZE (BLS) = 2K, DIRECTORY ENTRIES = 256
|
|
; ROM DISK SIZE = TOTAL ROM - 32K RESERVED FOR SYSTEM USE
|
|
;
|
|
.DB (2048 / 128) ; RECORDS PER BLOCK (BLS / 128)
|
|
DPB_ROM:
|
|
.DW 256 ; SPT: SECTORS PER TRACK
|
|
.DB 4 ; BSH: BLOCK SHIFT FACTOR
|
|
.DB 15 ; BLM: BLOCK MASK
|
|
#IF (ROMBLKS < 256)
|
|
.DB 1 ; EXM: EXTENT MASK
|
|
#ELSE
|
|
.DB 0 ; EXM: EXTENT MASK
|
|
#ENDIF
|
|
.DW ROMBLKS - 1 ; DSM: TOTAL STORAGE IN BLOCKS - 1
|
|
.DW 255 ; DRM: DIR ENTRIES - 1 = 255
|
|
.DB 11110000B ; AL0: DIR BLK BIT MAP, FIRST BYTE
|
|
.DB 00000000B ; AL1: DIR BLK BIT MAP, SECOND BYTE
|
|
.DW 0 ; CKS: ZERO FOR NON-REMOVABLE MEDIA
|
|
.DW 0 ; OFF: ROM DISK HAS NO SYSTEM AREA
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; RAM DISK: 256 SECS/TRK, 128 BYTES/SEC
|
|
; BLOCKSIZE (BLS) = 2K, DIRECTORY ENTRIES = 256
|
|
; RAM DISK SIZE = TOTAL RAM - 64K RESERVED FOR SYSTEM USE
|
|
;
|
|
.DB (2048 / 128) ; RECORDS PER BLOCK (BLS / 128)
|
|
DPB_RAM:
|
|
.DW 256 ; SPT: SECTORS PER TRACK
|
|
.DB 4 ; BSH: BLOCK SHIFT FACTOR
|
|
.DB 15 ; BLM: BLOCK MASK
|
|
#IF (RAMBLKS < 256)
|
|
.DB 1 ; EXM: EXTENT MASK
|
|
#ELSE
|
|
.DB 0 ; EXM: EXTENT MASK
|
|
#ENDIF
|
|
.DW RAMBLKS - 1 ; DSM: TOTAL STORAGE IN BLOCKS - 1
|
|
.DW 255 ; DRM: DIR ENTRIES - 1 = 255
|
|
.DB 11110000B ; AL0: DIR BLK BIT MAP, FIRST BYTE
|
|
.DB 00000000B ; AL1: DIR BLK BIT MAP, SECOND BYTE
|
|
.DW 0 ; CKS: ZERO FOR NON-REMOVABLE MEDIA
|
|
.DW 0 ; OFF: RESERVED TRACKS = 0 TRK
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; 8MB HARD DISK DRIVE, 65 TRKS, 1024 SECS/TRK, 128 BYTES/SEC
|
|
; BLOCKSIZE (BLS) = 4K, DIRECTORY ENTRIES = 128
|
|
; SEC/TRK ENGINEERED SO THAT AFTER DEBLOCKING, SECTOR NUMBER OCCUPIES 1 BYTE (0-255)
|
|
;
|
|
.DB (4096 / 128) ; RECORDS PER BLOCK (BLS / 128)
|
|
DPB_HD:
|
|
.DW 1024 ; SPT: SECTORS PER TRACK
|
|
.DB 5 ; BSH: BLOCK SHIFT FACTOR
|
|
.DB 31 ; BLM: BLOCK MASK
|
|
.DB 1 ; EXM: EXTENT MASK
|
|
.DW 2047 ; DSM: TOTAL STORAGE IN BLOCKS - 1 BLK = ((8MB - 128K OFF) / 4K BLS) - 1 = 2047
|
|
.DW 511 ; DRM: DIR ENTRIES - 1 = 512 - 1 = 511
|
|
.DB 11110000B ; AL0: DIR BLK BIT MAP, FIRST BYTE
|
|
.DB 00000000B ; AL1: DIR BLK BIT MAP, SECOND BYTE
|
|
.DW 0 ; CKS: DIRECTORY CHECK VECTOR SIZE = 256 / 4
|
|
.DW 1 ; OFF: RESERVED TRACKS = 1 TRKS * (512 B/SEC * 1024 SEC/TRK) = 128K
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; IBM 720KB 3.5" FLOPPY DRIVE, 80 TRKS, 36 SECS/TRK, 512 BYTES/SEC
|
|
; BLOCKSIZE (BLS) = 2K, DIRECTORY ENTRIES = 128
|
|
;
|
|
.DB (2048 / 128) ; RECORDS PER BLOCK (BLS / 128)
|
|
DPB_FD720:
|
|
.DW 36 ; SPT: SECTORS PER TRACK
|
|
.DB 4 ; BSH: BLOCK SHIFT FACTOR
|
|
.DB 15 ; BLM: BLOCK MASK
|
|
.DB 0 ; EXM: EXTENT MASK
|
|
.DW 350 ; DSM: TOTAL STORAGE IN BLOCKS - 1 BLK = ((720K - 18K OFF) / 2K BLS) - 1 = 350
|
|
.DW 127 ; DRM: DIR ENTRIES - 1 = 128 - 1 = 127
|
|
.DB 11000000B ; AL0: DIR BLK BIT MAP, FIRST BYTE
|
|
.DB 00000000B ; AL1: DIR BLK BIT MAP, SECOND BYTE
|
|
.DW 32 ; CKS: DIRECTORY CHECK VECTOR SIZE = 128 / 4
|
|
.DW 4 ; OFF: RESERVED TRACKS = 4 TRKS * (512 B/SEC * 36 SEC/TRK) = 18K
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; IBM 1.44MB 3.5" FLOPPY DRIVE, 80 TRKS, 72 SECS/TRK, 512 BYTES/SEC
|
|
; BLOCKSIZE (BLS) = 2K, DIRECTORY ENTRIES = 256
|
|
;
|
|
.DB (2048 / 128) ; RECORDS PER BLOCK (BLS / 128)
|
|
DPB_FD144:
|
|
.DW 72 ; SPT: SECTORS PER TRACK
|
|
.DB 4 ; BSH: BLOCK SHIFT FACTOR
|
|
.DB 15 ; BLM: BLOCK MASK
|
|
.DB 0 ; EXM: EXTENT MASK
|
|
.DW 710 ; DSM: TOTAL STORAGE IN BLOCKS - 1 BLK = ((1,440K - 18K OFF) / 2K BLS) - 1 = 710
|
|
.DW 255 ; DRM: DIR ENTRIES - 1 = 256 - 1 = 255
|
|
.DB 11110000B ; AL0: DIR BLK BIT MAP, FIRST BYTE
|
|
.DB 00000000B ; AL1: DIR BLK BIT MAP, SECOND BYTE
|
|
.DW 64 ; CKS: DIRECTORY CHECK VECTOR SIZE = 256 / 4
|
|
.DW 2 ; OFF: RESERVED TRACKS = 2 TRKS * (512 B/SEC * 72 SEC/TRK) = 18K
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; IBM 360KB 5.25" FLOPPY DRIVE, 40 TRKS, 9 SECS/TRK, 512 BYTES/SEC
|
|
; BLOCKSIZE (BLS) = 2K, DIRECTORY ENTRIES = 128
|
|
;
|
|
.DB (2048 / 128) ; RECORDS PER BLOCK (BLS / 128)
|
|
DPB_FD360:
|
|
.DW 36 ; SPT: SECTORS PER TRACK
|
|
.DB 4 ; BSH: BLOCK SHIFT FACTOR
|
|
.DB 15 ; BLM: BLOCK MASK
|
|
.DB 0 ; EXM: EXTENT MASK
|
|
.DW 170 ; DSM: TOTAL STORAGE IN BLOCKS - 1 BLK = ((360K - 18K OFF) / 2K BLS) - 1 = 170
|
|
.DW 127 ; DRM: DIR ENTRIES - 1 = 128 - 1 = 127
|
|
.DB 11110000B ; AL0: DIR BLK BIT MAP, FIRST BYTE
|
|
.DB 00000000B ; AL1: DIR BLK BIT MAP, SECOND BYTE
|
|
.DW 32 ; CKS: DIRECTORY CHECK VECTOR SIZE = 128 / 4
|
|
.DW 4 ; OFF: RESERVED TRACKS = 4 TRKS * (512 B/SEC * 36 SEC/TRK) = 18K
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; IBM 1.20MB 5.25" FLOPPY DRIVE, 80 TRKS, 60 SECS/TRK, 512 BYTES/SEC
|
|
; BLOCKSIZE (BLS) = 2K, DIRECTORY ENTRIES = 256
|
|
;
|
|
.DB (2048 / 128) ; RECORDS PER BLOCK (BLS / 128)
|
|
DPB_FD120:
|
|
.DW 60 ; SPT: SECTORS PER TRACK
|
|
.DB 4 ; BSH: BLOCK SHIFT FACTOR
|
|
.DB 15 ; BLM: BLOCK MASK
|
|
.DB 0 ; EXM: EXTENT MASK
|
|
.DW 591 ; DSM: TOTAL STORAGE IN BLOCKS - 1 BLK = ((1,200K - 15K OFF) / 2K BLS) - 1 = 591
|
|
.DW 255 ; DRM: DIR ENTRIES - 1 = 256 - 1 = 255
|
|
.DB 11110000B ; AL0: DIR BLK BIT MAP, FIRST BYTE
|
|
.DB 00000000B ; AL1: DIR BLK BIT MAP, SECOND BYTE
|
|
.DW 64 ; CKS: DIRECTORY CHECK VECTOR SIZE = 256 / 4
|
|
.DW 2 ; OFF: RESERVED TRACKS = 2 TRKS * (512 B/SEC * 60 SEC/TRK) = 15K
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; IBM 1.11MB 8" FLOPPY DRIVE, 74 TRKS, 60 SECS/TRK, 512 BYTES/SEC
|
|
; BLOCKSIZE (BLS) = 2K, DIRECTORY ENTRIES = 256
|
|
;
|
|
.DB (2048 / 128) ; RECORDS PER BLOCK (BLS / 128)
|
|
DPB_FD111:
|
|
.DW 60 ; SPT: SECTORS PER TRACK
|
|
.DB 4 ; BSH: BLOCK SHIFT FACTOR
|
|
.DB 15 ; BLM: BLOCK MASK
|
|
.DB 0 ; EXM: EXTENT MASK
|
|
.DW 546 ; DSM: TOTAL STORAGE IN BLOCKS - 1 BLK = ((1,110K - 15K OFF) / 2K BLS) - 1 = 546
|
|
.DW 255 ; DRM: DIR ENTRIES - 1 = 256 - 1 = 255
|
|
.DB 11110000B ; AL0: DIR BLK BIT MAP, FIRST BYTE
|
|
.DB 00000000B ; AL1: DIR BLK BIT MAP, SECOND BYTE
|
|
.DW 64 ; CKS: DIRECTORY CHECK VECTOR SIZE = 256 / 4
|
|
.DW 2 ; OFF: RESERVED TRACKS = 2 TRKS * (512 B/SEC * 60 SEC/TRK) = 15K
|
|
;
|
|
;==================================================================================================
|
|
; START OF HIMEM AREA
|
|
;==================================================================================================
|
|
;
|
|
; THE FOLLOWING DATA STRUCTURES MUST NOT CROSS A PAGE BOUNDARY DUE TO OPTIMIZATION OF
|
|
; LOOKUP CODE. SO, HERE WE ORG SO THAT THERE IS JUST ENOUGH SPACE AT THE TOP OF THE
|
|
; CBIOS FOR THE DATA STRUCTURES. OBVIOUSLY, FOR THIS TO WORK, CBIOS MUST BE SET TO
|
|
; END AT A PAGE BOUNDARY, WHICH IS INTENDED
|
|
;
|
|
SLACK .EQU (CBIOS_END - $ - 32 - 32 - 16 - 512)
|
|
.FILL SLACK,00H
|
|
;
|
|
.ECHO "CBIOS space remaining: "
|
|
.ECHO SLACK
|
|
.ECHO " bytes.\n"
|
|
;
|
|
;==================================================================================================
|
|
; DPB MAPPING TABLE
|
|
;==================================================================================================
|
|
;
|
|
; MAP MEDIA ID'S TO APPROPRIATE DPB ADDRESSEES
|
|
; THE ENTRIES IN THIS TABLE MUST CONCIDE WITH THE VALUES
|
|
; OF THE MEDIA ID'S (SAME SEQUENCE, NO GAPS)
|
|
;
|
|
DPB_MAP:
|
|
.DW 0 ; MID_NONE (NO MEDIA)
|
|
.DW DPB_ROM ; MID_MDROM
|
|
.DW DPB_RAM ; MID_MDRAM
|
|
.DW DPB_HD ; MID_HD
|
|
.DW DPB_FD720 ; MID_FD720
|
|
.DW DPB_FD144 ; MID_FD144
|
|
.DW DPB_FD360 ; MID_FD360
|
|
.DW DPB_FD120 ; MID_FD120
|
|
.DW DPB_FD111 ; MID_FD111
|
|
;
|
|
DPB_CNT .EQU ($ - DPB_MAP) / 2
|
|
;
|
|
;==================================================================================================
|
|
; DRIVE LETTER MAPPING TABLE
|
|
;==================================================================================================
|
|
;
|
|
; THE DISK MAP TABLE BELOW MAPS DRIVE LETTERS TO PHYSICAL STORAGE DEVICES.
|
|
; CP/M DRIVE LETTERS ARE ASSIGNED BASED ON THE ORDER OF ENTRIES IN THE TABLE,
|
|
; SO THE FIRST ENTRY IS A:, THE SECOND ENTRY IS B:, ETC.
|
|
; EACH ENTRY IS A COMBINATION (OR) OF THE DEVICE AND THE UNIT.
|
|
; DIODEV_MD = MEMORY DISKS (ROM/RAM) (UNIT 0 = ROM, UNIT 1 = RAM)
|
|
; DIODEV_FD = FLOPPY DISKS (TWO UNITS (0/1) SUPPORTED)
|
|
; DIODEV_IDE = IDE DISKS (TWO UNITS (0/1) MASTER/SLAVE SUPPORTED)
|
|
; DIODEV_PPIDE = PPIDE DISKS (TWO UNITS (0/1) MASTER/SLAVE SUPPORTED)
|
|
; DIODEV_SD = SD CARD (ONE UNIT SUPPORTED)
|
|
; DIODEV_PRPSD = PROPIO SD CARD (ONE UNIT SUPPORTED)
|
|
; DIODEV_PPPSD = PROPIO SD CARD (ONE UNIT SUPPORTED)
|
|
; DIODEV_HDDSK = SIMH HARD DISK (TWO UNITS SUPPORTED)
|
|
;
|
|
; DRIVE LETTERS ARE ASSIGNED SEQUENTIALLY.
|
|
;
|
|
; ALTERNATIVELY, YOU CAN DEFINE A MACRO CALLED CUSTOM_DPHMAP THAT
|
|
; DEFINES AN ENTIRELY CUSTOM MAPPING
|
|
;
|
|
DPH_MAP:
|
|
#IFDEF CUSTOM_DPHMAP
|
|
CUSTOM_DPHMAP
|
|
#ELSE
|
|
#IF (DSKMAP == DM_ROM)
|
|
.DW MDDPH0
|
|
#ENDIF
|
|
#IF (DSKMAP == DM_RAM)
|
|
.DW MDDPH1
|
|
#ENDIF
|
|
#IF (DSKMAP == DM_FD)
|
|
.DW FDDPH0
|
|
.DW FDDPH1
|
|
#ENDIF
|
|
#IF (DSKMAP == DM_IDE)
|
|
.DW IDEDPH0
|
|
.DW IDEDPH1
|
|
.DW IDEDPH2
|
|
.DW IDEDPH3
|
|
#ENDIF
|
|
#IF (DSKMAP == DM_PPIDE)
|
|
.DW PPIDEDPH0
|
|
.DW PPIDEDPH1
|
|
.DW PPIDEDPH2
|
|
.DW PPIDEDPH3
|
|
#ENDIF
|
|
#IF (DSKMAP == DM_SD)
|
|
.DW SDDPH0
|
|
.DW SDDPH1
|
|
.DW SDDPH2
|
|
.DW SDDPH3
|
|
#ENDIF
|
|
#IF (DSKMAP == DM_PRPSD)
|
|
.DW PRPSDDPH0
|
|
.DW PRPSDDPH1
|
|
.DW PRPSDDPH2
|
|
.DW PRPSDDPH3
|
|
#ENDIF
|
|
#IF (DSKMAP == DM_PPPSD)
|
|
.DW PPPSDDPH0
|
|
.DW PPPSDDPH1
|
|
.DW PPPSDDPH2
|
|
.DW PPPSDDPH3
|
|
#ENDIF
|
|
#IF (DSKMAP == DM_HDSK)
|
|
.DW HDSKDPH0
|
|
.DW HDSKDPH1
|
|
.DW HDSKDPH2
|
|
.DW HDSKDPH3
|
|
#ENDIF
|
|
#IF (DSKMAP != DM_ROM)
|
|
.DW MDDPH0
|
|
#ENDIF
|
|
#IF (DSKMAP != DM_RAM)
|
|
.DW MDDPH1 ; was MDDHP1
|
|
#ENDIF
|
|
#IF ((DSKMAP != DM_FD) & FDENABLE)
|
|
.DW FDDPH0
|
|
.DW FDDPH1
|
|
#ENDIF
|
|
#IF ((DSKMAP != DM_IDE) & IDEENABLE)
|
|
.DW IDEDPH0
|
|
.DW IDEDPH1
|
|
.DW IDEDPH2
|
|
.DW IDEDPH3
|
|
#ENDIF
|
|
#IF ((DSKMAP != DM_PPIDE) & PPIDEENABLE)
|
|
.DW PPIDEDPH0
|
|
.DW PPIDEDPH1
|
|
.DW PPIDEDPH2
|
|
.DW PPIDEDPH3
|
|
#ENDIF
|
|
#IF ((DSKMAP != DM_SD) & SDENABLE)
|
|
.DW SDDPH0
|
|
.DW SDDPH1
|
|
.DW SDDPH2
|
|
.DW SDDPH3
|
|
#ENDIF
|
|
#IF ((DSKMAP != DM_PRPSD) & PRPENABLE & PRPSDENABLE)
|
|
.DW PRPSDDPH0
|
|
.DW PRPSDDPH1
|
|
.DW PRPSDDPH2
|
|
.DW PRPSDDPH3
|
|
#ENDIF
|
|
#IF ((DSKMAP != DM_PPPSD) & PPPENABLE & PPPSDENABLE)
|
|
.DW PPPSDDPH0
|
|
.DW PPPSDDPH1
|
|
.DW PPPSDDPH2
|
|
.DW PPPSDDPH3
|
|
#ENDIF
|
|
#IF ((DSKMAP != DM_HDSK) & HDSKENABLE)
|
|
.DW HDSKDPH0
|
|
.DW HDSKDPH1
|
|
.DW HDSKDPH2
|
|
.DW HDSKDPH3
|
|
#ENDIF
|
|
#ENDIF ; CUSTOM_DPHMAP
|
|
;
|
|
DPH_CNT .EQU ($ - DPH_MAP) / 2
|
|
.FILL (16 - DPH_CNT) * 2,0FFH
|
|
DSK_CNT .EQU DPH_CNT
|
|
;
|
|
;==================================================================================================
|
|
; CHARACTER DEVICE MAPPING
|
|
;==================================================================================================
|
|
;
|
|
; MAP LOGICAL TO PHYSICAL DEVICES
|
|
;
|
|
LD_TTY .EQU CIODEV_UART
|
|
LD_CRT .EQU CIODEV_VDU
|
|
LD_BAT .EQU CIODEV_BAT
|
|
LD_UC1 .EQU CIODEV_UART
|
|
LD_PTR .EQU CIODEV_UART
|
|
LD_UR1 .EQU CIODEV_UART
|
|
LD_UR2 .EQU CIODEV_UART
|
|
LD_PTP .EQU CIODEV_UART
|
|
LD_UP1 .EQU CIODEV_UART
|
|
LD_UP2 .EQU CIODEV_UART
|
|
LD_LPT .EQU CIODEV_UART
|
|
LD_UL1 .EQU CIODEV_UART
|
|
;
|
|
#IF (PLATFORM == PLT_N8)
|
|
LD_UC1 .SET CIODEV_UART + 1
|
|
#ENDIF
|
|
;
|
|
#IF (VDUENABLE)
|
|
LD_CRT .SET CIODEV_VDU
|
|
#ENDIF
|
|
#IF (PRPENABLE & PRPCONENABLE)
|
|
LD_CRT .SET CIODEV_PRPCON
|
|
#ENDIF
|
|
#IF (PPPENABLE & PPPCONENABLE)
|
|
LD_CRT .SET CIODEV_PPPCON
|
|
#ENDIF
|
|
;
|
|
CIO_MAP:
|
|
;
|
|
; CONSOLE
|
|
.DB LD_TTY ; CON:=TTY: (IOBYTE XXXXXX00)
|
|
.DB LD_CRT ; CON:=CRT: (IOBYTE XXXXXX01)
|
|
.DB LD_BAT ; CON:=BAT: (IOBYTE XXXXXX10)
|
|
.DB LD_UC1 ; CON:=UC1: (IOBYTE XXXXXX11)
|
|
; READER
|
|
.DB LD_TTY ; RDR:=TTY: (IOBYTE XXXX00XX)
|
|
.DB LD_PTR ; RDR:=PTR: (IOBYTE XXXX01XX)
|
|
.DB LD_UR1 ; RDR:=UR1: (IOBYTE XXXX10XX)
|
|
.DB LD_UR2 ; RDR:=UR2: (IOBYTE XXXX11XX)
|
|
; PUNCH
|
|
.DB LD_TTY ; PUN:=TTY: (IOBYTE XX00XXXX)
|
|
.DB LD_PTP ; PUN:=PTP: (IOBYTE XX01XXXX)
|
|
.DB LD_UP1 ; PUN:=UP1: (IOBYTE XX10XXXX)
|
|
.DB LD_UP2 ; PUN:=UP2: (IOBYTE XX11XXXX)
|
|
; LIST
|
|
.DB LD_TTY ; LST:=TTY: (IOBYTE 00XXXXXX)
|
|
.DB LD_CRT ; LST:=CRT: (IOBYTE 01XXXXXX)
|
|
.DB LD_LPT ; LST:=LPT: (IOBYTE 10XXXXXX)
|
|
.DB LD_UL1 ; LST:=UL1: (IOBYTE 11XXXXXX)
|
|
;
|
|
;==================================================================================================
|
|
; SECTOR AND CONFIG BUFFER;
|
|
;==================================================================================================
|
|
;
|
|
; A 512 AREA IS ALLOCATED AT FD00 AND IS USED FOR TWO PURPOSES:
|
|
; 1) AS THE DISK SECTOR BUFFER AFTER CBIOS COLD INIT IS DONE
|
|
; 2) FOR CBIOS INIT CODE THAT CAN BE DISCARDED AFTER INITIALIZTION:
|
|
; A) SYSTEM CONFIGURATION DATA BUFFER
|
|
; B) CBIOS INIT CODE THAT CAN BE DISCARDED AFTER INIT
|
|
;
|
|
.FILL 0FD00H - $,00H ; MAKE SURE SEC/CFGBUF STARTS AT FD00
|
|
;
|
|
SECBUF: ; START OF 512 BYTE DISK SECTOR
|
|
CFGBUF: ; START OF 256 BYTE CONFIG BUFFER
|
|
.FILL 256,0
|
|
;
|
|
INIT:
|
|
DI
|
|
IM 1
|
|
|
|
; SETUP A TEMP STACK IN UPPER 32K
|
|
LD SP,ISTACK ; STACK FOR INITIALIZATION
|
|
|
|
; ENSURE RAM PAGE ZERO ACTIVE
|
|
CALL RAMPGZ
|
|
|
|
; THIS INIT CODE WILL BE OVERLAID, SO WE ARE GOING
|
|
; TO MODIFY THE BOOT ENTRY POINT TO CAUSE A PANIC
|
|
; TO EASILY IDENTIFY IF SOMETHING TRIES TO INVOKE
|
|
; THE BOOT ENTRY POINT AFTER INIT IS DONE.
|
|
LD A,0CDH ; "CALL" INSTRUCTION
|
|
LD (BOOT),A ; STORE IT BOOT ENTRY POINT
|
|
LD HL,PANIC ; ADDRESS OF PANIC ROUTINE
|
|
LD (BOOT+1),HL ; STORE IT AT BOOT ENTRY + 1
|
|
|
|
; PARAMETER INITIALIZATION
|
|
LD A,DEFIOBYTE ; LOAD DEFAULT IOBYTE
|
|
LD (IOBYTE),A ; STORE IT
|
|
|
|
#IF (PLATFORM != PLT_N8)
|
|
IN A,(RTC) ; RTC PORT, BIT 6 HAS STATE OF CONFIG JUMPER
|
|
; LD A,40H ; *DEBUG* SIMULATE JUMPER OPEN
|
|
; LD A,00H ; *DEBUG* SIMULATE JUMPER SHORTED
|
|
AND 40H ; ISOLATE BIT 6
|
|
JR Z,INIT1 ; IF BIT6=0, SHORTED, USE ALT IOBYTE
|
|
LD A,DEFIOBYTE ; LOAD DEF IOBYTE VALUE
|
|
JR INIT2 ; CONTINUE
|
|
INIT1:
|
|
LD A,ALTIOBYTE ; LOAD ALT IOBYTE VALUE
|
|
INIT2:
|
|
LD (IOBYTE),A ; SET THE ACTIVE IOBYTE
|
|
#ENDIF
|
|
|
|
; DEFAULT DRIVE
|
|
CALL DEFDRV ; DETERMINE DEFAULT DRIVE
|
|
LD A,(DEFDRIVE) ; GET DEFAULT DRIVE
|
|
LD (CDISK),A ; SETUP CDISK
|
|
|
|
; STARTUP MESSAGE
|
|
CALL NEWLINE
|
|
LD DE,STR_BANNER
|
|
CALL WRITESTR
|
|
CALL NEWLINE
|
|
|
|
; SAVE COMMAND PROCESSOR TO CACHE IN RAM1
|
|
LD A,1
|
|
CALL RAMPG
|
|
LD HL,CPM_LOC ; LOCATION OF ACTIVE COMMAND PROCESSOR
|
|
LD DE,0800H ; LOCATION IN RAM 1 OF COMMAND PROCESSOR CACHE
|
|
LD BC,CCPSIZ ; SIZE OF COMMAND PROCESSOR
|
|
LDIR
|
|
CALL RAMPGZ
|
|
|
|
; SYSTEM INITIALIZATION
|
|
CALL BLKRES ; RESET DISK (DE)BLOCKING ALGORITHM
|
|
CALL MD_INIT ; INITIALIZE MEMORY DISK DRIVER (RAM/ROM)
|
|
|
|
CALL NEWLINE
|
|
|
|
; STARTUP CPM
|
|
JP GOCPM
|
|
;
|
|
DEFDRV:
|
|
; START BY ASSUMING DRIVE 0 IS DEFAULT
|
|
XOR A ; ZERO
|
|
LD (DEFDRIVE),A ; STORE IT
|
|
|
|
; GET CONFIG INFO (STORE IN CFGBUF)
|
|
LD BC,$F000
|
|
LD DE,CFGBUF
|
|
RST 08
|
|
|
|
; IF NOT A DISK DEVICE BOOT, BAIL OUT, NOTHING MORE TO DO
|
|
LD A,(CFGBUF+DISKBOOT) ; DID WE BOOT FROM A DISK DEVICE?
|
|
OR A ; SET FLAGS
|
|
RET Z
|
|
|
|
; SCAN DRIVES TO MATCH BOOTDEVICE/LU AND STORE DEFDRIVE
|
|
LD C,-1 ; INIT CURRENT DRIVE FOR LOOP
|
|
DEFDRV1:
|
|
INC C ; NEXT DRIVE
|
|
LD A,C ; A = C
|
|
CP 16 ; MAX DRIVE IS 15, PAST IT?
|
|
RET Z ; NO MATCHES, BAIL OUT
|
|
CALL DSK_GETDPH ; GET POINTER TO DPH INTO HL
|
|
OR A ; SET FLAGS
|
|
JR NZ,DEFDRV1 ; INVALID DRIVE, BYPASS IT
|
|
DEC HL ; POINT TO DEVICE/UNIT
|
|
LD E,(HL) ; E = DEVICE/UNIT BYTE
|
|
LD A,(CFGBUF+BOOTDEVICE) ; A = BOOTDEVICE
|
|
CP E ; MATCH BOOTDEVICE?
|
|
JR NZ,DEFDRV1 ; NOPE, NEXT DRIVE
|
|
INC HL ; POINT HL BACK TO START OF DPH
|
|
CALL DSK_GETLU ; GET POINTER TO LU DATA IN HL
|
|
JR NZ,DEFDRV2 ; NO LU SUPPORT, DEVICE ALREADY MATCHED, WE ARE DONE
|
|
LD E,(HL) ; E = LU LSB
|
|
LD A,(CFGBUF+BOOTLU) ; A = BOOT LU LSB
|
|
CP E ; MATCH LSB?
|
|
JR NZ,DEFDRV1 ; NOPE, NEXT DRIVE
|
|
INC HL ; POINT TO LU MSB
|
|
LD E,(HL) ; E = LU MSB
|
|
LD A,(CFGBUF+BOOTLU+1) ; A = BOOT LU MSB
|
|
CP E ; MATCH MSB?
|
|
JR NZ,DEFDRV1 ; NOPE, NEXT DRIVE
|
|
|
|
DEFDRV2:
|
|
; WE HAVE A MATCH MATCHED, RECORD NEW DEFAULT DRIVE
|
|
LD A,C ; C HAS MATCHING DRIVE, MOVE TO A
|
|
LD (DEFDRIVE),A ; SAVE IT
|
|
;
|
|
RET
|
|
;
|
|
.FILL (256 - ($ - INIT)),0 ; FILL REMAINDER OF PAGE
|
|
;
|
|
ISTACK .EQU $ ; TEMP STACK SPACE
|
|
;
|
|
.END
|
|
|