mirror of https://github.com/wwarthen/RomWBW.git
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.
2446 lines
70 KiB
2446 lines
70 KiB
;__________________________________________________________________________________________________
|
|
;
|
|
; CBIOS FOR N8VEM
|
|
;
|
|
; BY ANDREW LYNCH, WITH INPUT FROM MANY SOURCES
|
|
; ROMWBW ADAPTATION BY WAYNE WARTHEN
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; The std.asm file contains the majority of the standard equates
|
|
; that describe data structures, magic values and bit fields used
|
|
; by the CBIOS.
|
|
;
|
|
#INCLUDE "std.asm"
|
|
;
|
|
.ORG CBIOS_LOC ; DEFINED IN STD.ASM
|
|
;
|
|
STACK .EQU CBIOS_END ; USE SLACK SPACE FOR STACK AS NEEDED
|
|
;
|
|
;==================================================================================================
|
|
; 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 IN
|
|
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
|
|
;
|
|
;==================================================================================================
|
|
; CBIOS STAMP FOR ROMWBW
|
|
;==================================================================================================
|
|
;
|
|
; RomWBW CBIOS places the following stamp data into page zero
|
|
; at address $40. The address range $40-$4F is reserved by CP/M
|
|
; as a scratch area for CBIOS. This data below is copied there at
|
|
; every warm start. It allows applications to identify RomWBW CBIOS.
|
|
; Additionally, it contains a pointer to additional CBIOS extension
|
|
; data (CBX) specific to RomWBW CBIOS.
|
|
;
|
|
; RomWBW CBIOS page zero stamp starts at $40
|
|
; $40-$41: Marker ('W', ~'W')
|
|
; $42-$43: Version bytes: major/minor, update/patch
|
|
; $44-$45: CBIOS Extension Info address
|
|
;
|
|
STPLOC .EQU $40
|
|
STPIMG: .DB 'W',~'W' ; MARKER
|
|
.DB RMJ << 4 | RMN ; FIRST BYTE OF VERSION INFO
|
|
.DB RUP << 4 | RTP ; SECOND BYTE OF VERSION INFO
|
|
.DW CBX ; ADDRESS OF CBIOS EXT DATA
|
|
STPSIZ .EQU $ - STPIMG
|
|
;
|
|
; The following section contains key information and addresses for the
|
|
; RomWBW CBIOS. A pointer to the start of this section is stored with
|
|
; with the ZPX data in page zero at $44 (see above).
|
|
;
|
|
CBX:
|
|
DEVMAPADR .DW DEVMAP ; DEVICE MAP ADDRESS
|
|
DRVMAPADR .DW 0 ; DRIVE MAP ADDRESS (FILLED IN LATER)
|
|
DPBMAPADR .DW DPBMAP ; DPB MAP ADDRESS
|
|
;
|
|
CBXSIZ .EQU $ - CBX
|
|
.ECHO "CBIOS extension info occupies "
|
|
.ECHO CBXSIZ
|
|
.ECHO " bytes.\n"
|
|
;
|
|
;==================================================================================================
|
|
; CHARACTER DEVICE MAPPING
|
|
;==================================================================================================
|
|
;
|
|
; MAP LOGICAL CHARACTER DEVICES TO PHYSICAL CHARACTER DEVICES
|
|
;
|
|
#IF (PLATFORM == PLT_UNA)
|
|
|
|
LD_TTY .EQU 0
|
|
LD_CRT .EQU 0
|
|
LD_BAT .EQU CIODEV_BAT
|
|
LD_UC1 .EQU 0
|
|
LD_PTR .EQU 0
|
|
LD_UR1 .EQU 0
|
|
LD_UR2 .EQU 0
|
|
LD_PTP .EQU 0
|
|
LD_UP1 .EQU 0
|
|
LD_UP2 .EQU 0
|
|
LD_LPT .EQU 0
|
|
LD_UL1 .EQU 0
|
|
|
|
#ELSE
|
|
|
|
#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4))
|
|
TTYDEV .EQU CIODEV_ASCI
|
|
#ELSE
|
|
TTYDEV .EQU CIODEV_UART
|
|
#ENDIF
|
|
;
|
|
LD_TTY .EQU TTYDEV
|
|
LD_CRT .EQU TTYDEV
|
|
LD_BAT .EQU CIODEV_BAT
|
|
LD_UC1 .EQU TTYDEV
|
|
LD_PTR .EQU TTYDEV
|
|
LD_UR1 .EQU TTYDEV
|
|
LD_UR2 .EQU TTYDEV
|
|
LD_PTP .EQU TTYDEV
|
|
LD_UP1 .EQU TTYDEV
|
|
LD_UP2 .EQU TTYDEV
|
|
LD_LPT .EQU TTYDEV
|
|
LD_UL1 .EQU TTYDEV
|
|
;
|
|
#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4))
|
|
LD_UC1 .SET CIODEV_ASCI + 1
|
|
LD_PTR .SET CIODEV_ASCI + 1
|
|
LD_PTP .SET CIODEV_ASCI + 1
|
|
#ENDIF
|
|
;
|
|
#IF (UARTENABLE & (UARTCNT >= 2))
|
|
LD_UC1 .SET CIODEV_UART + 1
|
|
LD_PTR .SET CIODEV_UART + 1
|
|
LD_PTP .SET CIODEV_UART + 1
|
|
#ENDIF
|
|
;
|
|
#IF (VDUENABLE | CVDUENABLE | N8VENABLE)
|
|
LD_CRT .SET CIODEV_CRT
|
|
#ENDIF
|
|
#IF (PRPENABLE & PRPCONENABLE)
|
|
LD_CRT .SET CIODEV_PRPCON
|
|
#ENDIF
|
|
#IF (PPPENABLE & PPPCONENABLE)
|
|
LD_CRT .SET CIODEV_PPPCON
|
|
#ENDIF
|
|
|
|
#ENDIF
|
|
;
|
|
.DB DEVCNT
|
|
DEVMAP:
|
|
;
|
|
; 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)
|
|
;
|
|
DEVCNT .EQU ($ - DEVMAP)
|
|
.ECHO DEVCNT
|
|
.ECHO " Input/Output devices defined.\n"
|
|
;
|
|
;==================================================================================================
|
|
; DRIVE MAPPING TABLE
|
|
;==================================================================================================
|
|
;
|
|
; Disk mapping is done using a drive map table (DRVMAP) which is built
|
|
; dynamically at cold boot. See the DRV_INIT routine. This table is
|
|
; made up of entries as documented below. The table is prefixed with one
|
|
; byte indicating the number of entries. The index of the entry indicates
|
|
; the drive letter, so the first entry is A:, the second entry is B:, etc.
|
|
;
|
|
; BYTE: DEVICE/UNIT (OR JUST UNIT FOR UNA)
|
|
; BYTE: SLICE
|
|
; WORD: ADDRESS OF DPH FOR THE DRIVE
|
|
;
|
|
;==================================================================================================
|
|
; 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)
|
|
;
|
|
.DB DPBCNT
|
|
;
|
|
DPBMAP:
|
|
.DW 0 ; MID_NONE (NO MEDIA)
|
|
.DW DPB_ROM ; MID_MDROM
|
|
.DW DPB_RAM ; MID_MDRAM
|
|
.DW DPB_RF ; MID_RF
|
|
.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
|
|
;
|
|
DPBCNT .EQU ($ - DPBMAP) / 2
|
|
;
|
|
;==================================================================================================
|
|
; BIOS FUNCTIONS
|
|
;==================================================================================================
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
|
|
BOOT:
|
|
; STANDARD BOOT INVOCATION
|
|
DI
|
|
IM 1
|
|
LD SP,STACK ; STACK FOR INITIALIZATION
|
|
;
|
|
CALL INIT ; EXECUTE COLD BOOT CODE ROUTINE
|
|
;
|
|
LD SP,$100 ; MOVE STACK SO WE CAN INIT BUFFER AREA
|
|
; LD HL,BUFFERS ; INIT BUFFERS AREA
|
|
LD HL,INIT ; INIT BUFFERS AREA
|
|
; LD BC,CBIOS_END - BUFFERS ; SIZE OF BUFFER SPACE
|
|
LD BC,CBIOS_END - INIT ; SIZE OF BUFFER SPACE
|
|
CALL FILL ; DO IT
|
|
;
|
|
LD SP,STACK ; PUT STACK BACK WHERE IT BELONGS
|
|
JR GOCPM ; THEN OFF TO CP/M WE GO...
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
WBOOT:
|
|
DI
|
|
IM 1
|
|
;
|
|
LD SP,STACK ; STACK FOR INITIALIZATION
|
|
;
|
|
#IF (PLATFORM == PLT_UNA)
|
|
; RESTORE COMMAND PROCESSOR FROM UNA BIOS CACHE
|
|
LD BC,$01FB ; UNA FUNC = SET BANK
|
|
LD DE,$800D ; UBIOS_PAGE (SEE PAGES.INC)
|
|
RST 08 ; DO IT
|
|
PUSH DE ; SAVE PREVIOUS BANK
|
|
|
|
LD HL,(CCPBUF) ; ADDRESS OF CCP BUF IN BIOS MEM
|
|
LD DE,CPM_LOC ; ADDRESS IN HI MEM OF CCP
|
|
LD BC,CCPSIZ ; SIZE OF CCP
|
|
LDIR ; DO IT
|
|
|
|
LD BC,$01FB ; UNA FUNC = SET BANK
|
|
POP DE ; RECOVER OPERATING BANK
|
|
RST 08 ; DO IT
|
|
#ELSE
|
|
; RESTORE COMMAND PROCESSOR FROM CACHE IN HB BANK
|
|
LD B,BID_USR ; B = DEST BANK = USR BANK = TPA
|
|
LD C,BID_HB ; C = SRC BANK = HB BANK
|
|
CALL HB_XCOPY ; SET BANKS FOR INTERBANK COPY
|
|
LD HL,$800 ; COPY FROM FIXED LOCATION IN HB BANK
|
|
LD DE,CPM_LOC ; TO CCP LOCATION IN USR BANK
|
|
LD BC,CCPSIZ ; COPY CONTENTS OF COMMAND PROCESSOR
|
|
CALL HB_COPY ; DO IT
|
|
#ENDIF
|
|
;
|
|
; FALL THRU TO INVOKE CP/M
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
GOCPM:
|
|
#IF (PLATFORM == PLT_UNA)
|
|
; USE A DEDICATED BUFFER FOR UNA PHYSICAL DISK I/O
|
|
LD HL,SECBUF ; ADDRESS OF PHYSICAL SECTOR BUFFER
|
|
LD (BUFADR),HL ; SAVE IT IN BUFADR FOR LATER
|
|
#ELSE
|
|
; GET AND SAVE PHYSICAL DISK XFR BUFFER LOCATION
|
|
; ASSUMED TO BE IN HBIOS BANK (BID_HB)
|
|
LD B,BF_DIOGETBUF ; GET DISK BUFFER ADR IN HBIOS DRIVER BANK
|
|
RST 08 ; MAKE HBIOS CALL
|
|
LD (BUFADR),HL ; RECORD THE BUFFER ADDRESS
|
|
#ENDIF
|
|
;
|
|
LD A,$C3 ; LOAD A WITH 'JP' INSTRUCTION (USED BELOW)
|
|
;
|
|
; CPU RESET / RST 0 / JP 0 -> WARM START CP/M
|
|
LD ($0000),A ; JP OPCODE GOES HERE
|
|
LD HL,WBOOTE ; GET WARM BOOT ENTRY ADDRESS
|
|
LD ($0001),HL ; AND PUT IT AT $0001
|
|
|
|
; ; INT / RST 38 -> INVOKE MONITOR
|
|
; LD ($0038),A
|
|
; LD HL,GOMON
|
|
; LD ($0039),HL
|
|
|
|
; ; INT / RST 38 -> PANIC
|
|
; LD ($0038),A
|
|
; LD HL,PANIC ; PANIC ROUTINE ADDRESS
|
|
; LD ($0039),HL ; POKE IT
|
|
|
|
; CALL 5 -> INVOKE BDOS
|
|
LD ($0005),A ; JP OPCODE AT $0005
|
|
LD HL,BDOS ; GET BDOS ENTRY ADDRESS
|
|
LD ($0006),HL ; PUT IT AT $0006
|
|
;
|
|
; INSTALL ROMWBW CBIOS PAGE ZERO STAMP AT $40
|
|
LD HL,STPIMG ; FORM STAMP DATA IMAGE
|
|
LD DE,STPLOC ; TO IT'S LOCATION IN PAGE ZERO
|
|
LD BC,STPSIZ ; SIZE OF BLOCK TO COPY
|
|
LDIR ; DO IT
|
|
;
|
|
; RESET (DE)BLOCKING ALGORITHM
|
|
CALL BLKRES
|
|
;
|
|
; DEFAULT DMA ADDRESS
|
|
LD BC,$80 ; DEFAULT DMA ADDRESS IS $80
|
|
CALL SETDMA ; SET IT
|
|
;
|
|
; ENSURE VALID DISK AND JUMP TO CCP
|
|
LD A,(CDISK) ; GET CURRENT USER/DISK
|
|
AND $0F ; 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 ; JUMP TO COMMAND PROCESSOR
|
|
CURDSK:
|
|
LD A,(CDISK) ; GET CURRENT USER/DISK
|
|
GOCCP:
|
|
LD C,A ; SETUP C WITH CURRENT USER/DISK, ASSUME IT IS OK
|
|
JP CCP ; JUMP TO COMMAND PROCESSOR
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
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
|
|
;
|
|
;
|
|
;==================================================================================================
|
|
; CHARACTER BIOS FUNCTIONS
|
|
;==================================================================================================
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
CONST:
|
|
; CONSOLE STATUS, RETURN $FF IF CHARACTER READY, $00 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
|
|
POP HL ; NO COMPLETION ROUTINE, SETUP DIRECT RETURN TO CALLER
|
|
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
|
|
JR CIO_DISP
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
LIST:
|
|
; LIST CHARACTER FROM REGISTER C
|
|
;
|
|
LD B,BF_CIOOUT ; B = FUNCTION
|
|
POP HL ; NO COMPLETION ROUTINE, SETUP DIRECT RETURN TO CALLER
|
|
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
|
|
JR CIO_DISP
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
PUNCH:
|
|
; PUNCH CHARACTER FROM REGISTER C
|
|
;
|
|
LD B,BF_CIOOUT ; B = FUNCTION
|
|
POP HL ; NO COMPLETION ROUTINE, SETUP DIRECT RETURN TO CALLER
|
|
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
|
|
JR 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
|
|
JR 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)
|
|
;
|
|
#IF (PLATFORM == PLT_UNA)
|
|
LD A,E
|
|
#ENDIF
|
|
OR A ; SET FLAGS
|
|
RET Z ; NO CHARACTERS WAITING (IST) OR OUTPUT BUF FULL (OST)
|
|
OR $FF ; $FF SIGNALS READY TO READ (IST) OR WRITE (OST)
|
|
RET
|
|
;
|
|
;==================================================================================================
|
|
; CHARACTER DEVICE INTERFACE
|
|
;==================================================================================================
|
|
;
|
|
; ROUTING FOR CHARACTER DEVICE FUNCTIONS
|
|
; A = INDEX INTO DEVICE 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
|
|
AND $0F ; ISOLATE INDEX INTO DEVICE MAP
|
|
|
|
LD HL,DEVMAP ; HL = ADDRESS OF DEVICE MAP
|
|
CALL ADDHLA ; ADD OFFSET
|
|
|
|
LD A,(HL) ; LOOKUP DEVICE CODE
|
|
#IF (PLATFORM == PLT_UNA)
|
|
LD C,B ; MOVE FUNCTION TO C
|
|
LD B,A ; DEVICE GOES IN B
|
|
#ELSE
|
|
LD C,A ; SAVE IN C FOR BIOS USAGE
|
|
#ENDIF
|
|
|
|
CP CIODEV_BAT ; CHECK FOR SPECIAL DEVICE (BAT, NUL)
|
|
JR NC,CIO_DISP1 ; HANDLE SPECIAL DEVICE
|
|
RST 08 ; RETURN VIA COMPLETION ROUTINE SET AT START
|
|
RET
|
|
|
|
CIO_DISP1:
|
|
; HANDLE SPECIAL DEVICES
|
|
AND $F0 ; 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?
|
|
JR Z,READER ; -> READER
|
|
CP BF_CIOIST ; INPUT STATUS?
|
|
JR Z,READERST ; -> READER
|
|
CP BF_CIOOUT ; OUTPUT?
|
|
JR Z,LIST ; -> LIST
|
|
CP BF_CIOOST ; OUTPUT STATUS?
|
|
JR Z,LISTST ; -> LIST
|
|
CALL PANIC ; SOMETHING BAD HAPPENED
|
|
;
|
|
; 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
|
|
;
|
|
;==================================================================================================
|
|
; DISK BIOS FUNCTIONS
|
|
;==================================================================================================
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
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 ; SET FLAGS
|
|
JR NZ,HOMED ; BUFFER IS DIRTY
|
|
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
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
READWRITE:
|
|
LD (DSKOP),A ; SET THE ACTIVE DISK OPERATION
|
|
JR BLKRW
|
|
;
|
|
;==================================================================================================
|
|
; 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_ALC .EQU 0 ; WRITE TO ALLOCATED
|
|
WRT_DIR .EQU 1 ; WRITE TO DIRECTORY
|
|
WRT_UNA .EQU 2 ; WRITE TO UNALLOCATED
|
|
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; (DE)BLOCKING READ/WRITE ROUTINE. MANAGES PHYSICAL DISK BUFFER AND CALLS
|
|
; PHYSICAL READ/WRITE ROUTINES APPROPRIATELY.
|
|
;
|
|
BLKRW:
|
|
#IF DSKTRACE
|
|
CALL PRTDSKOP ; *DEBUG*
|
|
#ENDIF
|
|
|
|
; 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_ALC) 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_UNA ; 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_ALC
|
|
LD (WRTYPE),A ; NOW TREAT LIKE WRITE TO ALLOCATED
|
|
|
|
BLKRW2:
|
|
; IF WRTYPE = WRT_ALC 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_ALC, 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_UNA ; 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
|
|
; JR Z,BLKFLSH ; FLUSH PENDING WRITES AND RETURN STATUS
|
|
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
|
|
|
|
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:
|
|
#IF DSKTRACE
|
|
CALL PRTDSKOP ; *DEBUG*
|
|
#ENDIF
|
|
|
|
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:
|
|
#IF (PLATFORM == PLT_UNA)
|
|
CALL BLK_SETUP
|
|
EX DE,HL
|
|
LD BC,128
|
|
LDIR
|
|
RET
|
|
#ELSE
|
|
LD C,BID_USR ; C=SRC=USER BANK=TPA
|
|
LD B,BID_HB ; B=DEST=HBIOS
|
|
CALL HB_XCOPY ; HB_XCOPY
|
|
CALL BLK_SETUP ; SETUP SOURCE AND DESTINATION
|
|
EX DE,HL ; SWAP HL/DE FOR BLOCK OPERATION
|
|
LD BC,128 ; DMA BUFFER SIZE
|
|
CALL HB_COPY ; HB_COPY (INTERBANK COPY)
|
|
RET
|
|
#ENDIF
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; DEBLOCK DATA - EXTRACT DESIRED CPM DMA BUF FROM PHYSICAL SECTOR BUFFER
|
|
;
|
|
BLK_DEBLOCK:
|
|
#IF (PLATFORM == PLT_UNA)
|
|
CALL BLK_SETUP
|
|
LD BC,128
|
|
LDIR
|
|
RET
|
|
#ELSE
|
|
LD C,BID_HB ; C=SRC=HBIOS
|
|
LD B,BID_USR ; B=DEST=USER BANK=TPA
|
|
CALL HB_XCOPY ; HB_XCOPY
|
|
CALL BLK_SETUP ; SETUP SOURCE AND DESTINATION
|
|
LD BC,128 ; DMA BUFFER SIZE
|
|
CALL HB_COPY ; HB_COPY (INTERBANK COPY)
|
|
RET
|
|
#ENDIF
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; 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
|
|
;
|
|
;==================================================================================================
|
|
; PHYSICAL DISK INTERFACE
|
|
;==================================================================================================
|
|
;
|
|
; LOOKUP DISK INFORMATION BASED ON CPM DRIVE IN C
|
|
; ON RETURN, D=DEVICE/UNIT, E=SLICE, HL=DPH ADDRESS
|
|
;
|
|
DSK_GETINF:
|
|
LD HL,(DRVMAPADR) ; HL := START OF UNA DRIVE MAP
|
|
DEC HL ; POINT TO DRIVE COUNT
|
|
LD A,C ; A := CPM DRIVE
|
|
CP (HL) ; COMPARE TO NUMBER OF DRIVES CONFIGURED
|
|
JR NC,DSK_GETINF1 ; IF OUT OF RANGE, GO TO ERROR RETURN
|
|
INC HL ; POINT TO START OF DRIVE MAP
|
|
;
|
|
RLCA ; MULTIPLY A BY 4...
|
|
RLCA ; TO USE AS OFFSET INTO ???? MAP
|
|
CALL ADDHLA ; ADD OFFSET
|
|
LD D,(HL) ; D := DEVICE/UNIT
|
|
INC HL ; BUMP TO SLICE
|
|
LD E,(HL) ; E := SLICE
|
|
INC HL ; POINT TO DPH LSB
|
|
LD A,(HL) ; A := DPH LSB
|
|
INC HL ; POINT TO DPH MSB
|
|
LD H,(HL) ; H := DPH MSB
|
|
LD L,A ; L := DPH LSB
|
|
LD A,H ; TEST FOR INVALID DPH
|
|
OR L ; ... BY CHECKING FOR ZERO VALUE
|
|
JR Z,DSK_GETINF1 ; HANDLE ZERO DPH, DRIVE IS INVALID
|
|
XOR A ; SET SUCCESS
|
|
RET
|
|
;
|
|
DSK_GETINF1: ; ERROR RETURN
|
|
XOR A
|
|
LD H,A
|
|
LD L,A
|
|
LD D,A
|
|
LD E,A
|
|
INC A
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
DSK_SELECT:
|
|
LD B,E ; SAVE E IN B FOR NOW
|
|
CALL DSK_GETINF ; GET D=DEVICE/UNIT, E=SLICE, HL=DPH ADDRESS
|
|
RET NZ ; RETURN IF INVALID DRIVE (A=1, NZ SET, HL=0)
|
|
PUSH BC ; WE NEED B LATER, SAVE ON STACK
|
|
;
|
|
; SAVE ALL THE NEW STUFF
|
|
LD A,C ; A := CPM DRIVE NO
|
|
LD (SEKDSK),A ; SAVE IT
|
|
LD A,D ; A := DEVICE/UNIT
|
|
LD (SEKDU),A ; SAVE DEVICE/UNIT
|
|
LD (SEKDPH),HL ; SAVE DPH POINTER
|
|
;
|
|
; UPDATE OFFSET FOR ACTIVE SLICE
|
|
; A TRACK IS ASSUMED TO BE 16 SECTORS
|
|
; THE OFFSET REPRESENTS THE NUMBER OF BLOCKS * 256
|
|
; TO USE AS THE OFFSET
|
|
LD H,65 ; H = TRACKS PER SLICE, E = SLICE NO
|
|
CALL MULT8 ; HL := H * E (TOTAL TRACK OFFSET)
|
|
LD (SEKOFF),HL ; SAVE NEW TRACK OFFSET
|
|
;
|
|
; CHECK IF THIS IS LOGIN, IF NOT, BYPASS MEDIA DETECTION
|
|
; FIX: WHAT IF PREVIOUS MEDIA DETECTION FAILED???
|
|
POP BC ; GET ORIGINAL E INTO B
|
|
BIT 0,B ; TEST DRIVE LOGIN BIT
|
|
#IF (PLATFORM == PLT_UNA)
|
|
JR DSK_SELECT2 ; NO MEDIA DETECTION FOR UNA
|
|
#ENDIF
|
|
JR NZ,DSK_SELECT2 ; BYPASS MEDIA DETECTION
|
|
;
|
|
; DETERMINE MEDIA IN DRIVE
|
|
LD A,(SEKDU) ; GET DEVICE/UNIT
|
|
LD C,A ; STORE IN C
|
|
LD B,BF_DIOMED ; DRIVER FUNCTION = DISK MEDIA
|
|
RST 08
|
|
OR A ; SET FLAGS
|
|
LD HL,0 ; ASSUME FAILURE
|
|
RET Z ; BAIL OUT IF NO MEDIA
|
|
;
|
|
; A HAS MEDIA ID, SET HL TO CORRESPONDING DPBMAP ENTRY
|
|
LD HL,DPBMAP ; HL = DPBMAP
|
|
RLCA ; DPBMAP ENTRIES ARE 2 BYTES EACH
|
|
CALL ADDHLA ; ADD OFFSET TO HL
|
|
;
|
|
; LOOKUP THE ACTUAL DPB ADDRESS NOW
|
|
LD E,(HL) ; DEREFERENCE HL...
|
|
INC HL ; INTO DE...
|
|
LD D,(HL) ; DE = ADDRESS OF DESIRED DPB
|
|
;
|
|
; PLUG DPB INTO THE ACTIVE DPH
|
|
LD HL,(SEKDPH)
|
|
LD BC,10 ; OFFSET OF DPB IN DPH
|
|
ADD HL,BC ; HL := DPH.DPB
|
|
LD (HL),E ; SET LSB OF DPB IN DPH
|
|
INC HL ; BUMP TO MSB
|
|
LD (HL),D ; SET MSB OF DPB IN DPH
|
|
;
|
|
DSK_SELECT2:
|
|
LD HL,(SEKDPH) ; HL = DPH ADDRESS FOR CP/M
|
|
XOR A ; FLAG SUCCESS
|
|
RET ; NORMAL RETURN
|
|
;
|
|
;
|
|
;
|
|
DSK_STATUS:
|
|
#IF (PLATFORM == PLT_UNA)
|
|
XOR A ; ASSUME OK FOR NOW
|
|
RET ; RETURN
|
|
#ENDIF
|
|
; C HAS CPM DRIVE, LOOKUP DEVICE/UNIT AND CHECK FOR INVALID DRIVE
|
|
CALL DSK_GETINF ; B = DEVICE/UNIT
|
|
RET NZ ; INVALID DRIVE ERROR
|
|
|
|
; VALID DRIVE, DISPATCH TO DRIVER
|
|
LD C,D ; C := DEVICE/UNIT
|
|
LD B,BF_DIOST ; B := FUNCTION: STATUS
|
|
RST 08
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
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
|
|
;
|
|
;
|
|
;
|
|
#IF (PLATFORM == PLT_UNA)
|
|
|
|
DSK_IO:
|
|
DSK_IO1:
|
|
PUSH BC
|
|
LD DE,(HSTTRK) ; GET TRACK INTO HL
|
|
LD B,4 ; PREPARE TO LEFT SHIFT BY 4 BITS
|
|
DSK_IO2:
|
|
SLA E ; SHIFT DE LEFT BY 4 BITS
|
|
RL D
|
|
DJNZ DSK_IO2 ; LOOP TILL ALL BITS DONE
|
|
LD A,(HSTSEC) ; GET THE SECTOR INTO A
|
|
AND $0F ; GET RID OF TOP NIBBLE
|
|
OR E ; COMBINE WITH E
|
|
LD E,A ; BACK IN E
|
|
LD HL,0 ; HL:DE NOW HAS SLICE RELATIVE LBA
|
|
; APPLY OFFSET NOW
|
|
; OFFSET IS EXPRESSED AS NUMBER OF BLOCKS * 256 TO OFFSET!
|
|
LD A,(HSTOFF) ; LSB OF SLICE OFFSET TO A
|
|
ADD A,D ; ADD WITH D
|
|
LD D,A ; PUT IT BACK IN D
|
|
LD A,(HSTOFF+1) ; MSB OF SLICE OFFSET TO A
|
|
CALL ADDHLA ; ADD OFFSET
|
|
POP BC ; RECOVER FUNCTION IN B
|
|
LD A,(HSTDU) ; GET THE DEVICE/UNIT VALUE
|
|
LD C,A ; PUT IT IN C
|
|
; DISPATCH TO DRIVER
|
|
PUSH BC
|
|
EX DE,HL ; DE:HL NOW HAS LBA
|
|
LD B,C ; UNIT TO B
|
|
LD C,$41 ; UNA SET LBA
|
|
RST 08 ; CALL UNA
|
|
CALL NZ,PANIC
|
|
POP BC ; RECOVER B=FUNC, C=UNIT
|
|
LD E,C ; UNIT TO E
|
|
LD C,B ; FUNC TO C
|
|
LD B,E ; UNIT TO B
|
|
LD DE,(BUFADR) ; SET BUFFER ADDRESS
|
|
LD HL,1 ; 1 SECTOR
|
|
|
|
;CALL PC_SPACE
|
|
;LD A,B
|
|
;CALL PRTHEXBYTE
|
|
|
|
|
|
RST 08
|
|
CALL NZ,PANIC
|
|
XOR A ; SET FLAGS BASED ON RESULT
|
|
RET
|
|
|
|
#ELSE
|
|
|
|
DSK_IO:
|
|
LD A,(HSTDU) ; GET ACTIVE DEVICE/UNIT BYTE
|
|
AND $F0 ; ISOLATE DEVICE PORTION
|
|
CP DIODEV_FD ; FLOPPY?
|
|
JR NZ,DSK_IO1 ; NO, USE LBA HANDLING
|
|
; SET HL=TRACK (ADD IN TRACK OFFSET)
|
|
LD DE,(HSTOFF) ; DE = TRACK OFFSET FOR LU SUPPORT
|
|
LD HL,(HSTTRK) ; HL = TRACK #
|
|
ADD HL,DE ; APPLY OFFSET FOR ACTIVE SLICE
|
|
; 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
|
|
RST 08
|
|
OR A ; SET FLAGS BASED ON RESULT
|
|
RET
|
|
; NEW LBA HANDLING
|
|
; COERCE TRACK/SECTOR INTO HL:DE AS 0000:TTTS
|
|
DSK_IO1:
|
|
PUSH BC
|
|
LD DE,(HSTTRK) ; GET TRACK INTO HL
|
|
LD B,4 ; PREPARE TO LEFT SHIFT BY 4 BITS
|
|
DSK_IO2:
|
|
SLA E ; SHIFT DE LEFT BY 4 BITS
|
|
RL D
|
|
DJNZ DSK_IO2 ; LOOP TILL ALL BITS DONE
|
|
LD A,(HSTSEC) ; GET THE SECTOR INTO A
|
|
AND $0F ; GET RID OF TOP NIBBLE
|
|
OR E ; COMBINE WITH E
|
|
LD E,A ; BACK IN E
|
|
LD HL,0 ; HL:DE NOW HAS SLICE RELATIVE LBA
|
|
; APPLY OFFSET NOW
|
|
; OFFSET IS EXPRESSED AS NUMBER OF BLOCKS * 256 TO OFFSET!
|
|
LD A,(HSTOFF) ; LSB OF SLICE OFFSET TO A
|
|
ADD A,D ; ADD WITH D
|
|
LD D,A ; PUT IT BACK IN D
|
|
LD A,(HSTOFF+1) ; MSB OF SLICE OFFSET TO A
|
|
CALL ADDHLA ; ADD OFFSET
|
|
POP BC ; RECOVER FUNCTION IN B
|
|
LD A,(HSTDU) ; GET THE DEVICE/UNIT VALUE
|
|
LD C,A ; PUT IT IN C
|
|
; DISPATCH TO DRIVER
|
|
RST 08
|
|
OR A ; SET FLAGS BASED ON RESULT
|
|
RET
|
|
|
|
#ENDIF
|
|
;
|
|
;==================================================================================================
|
|
; 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_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
|
|
CCPBUF .DW 0 ; ADDRESS OF CCP BUF IN UNA BIOS
|
|
;
|
|
; 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-$0400 ; 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 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
|
|
;
|
|
;==================================================================================================
|
|
; DISK CONTROL STRUCTURES (DPB, DPH)
|
|
;==================================================================================================
|
|
;
|
|
RAMBLKS .EQU (((BID_RAMDN - BID_RAMD + 1) * 32) / 2)
|
|
CKS_RAM .EQU 0 ; CKS: 0 FOR NON-REMOVABLE MEDIA
|
|
ALS_RAM .EQU ((RAMBLKS + 7) / 8) ; ALS: BLKS / 8 (ROUNDED UP)
|
|
;
|
|
ROMBLKS .EQU (((BID_ROMDN - BID_ROMD + 1) * 32) / 2)
|
|
CKS_ROM .EQU 0 ; CKS: 0 FOR NON-REMOVABLE MEDIA
|
|
ALS_ROM .EQU ((ROMBLKS + 7) / 8) ; ALS: BLKS / 8 (ROUNDED UP)
|
|
;
|
|
CKS_FD .EQU 64 ; CKS: DIR ENT / 4 = 256 / 4 = 64
|
|
ALS_FD .EQU 128 ; ALS: BLKS / 8 = 1024 / 8 = 128
|
|
;
|
|
CKS_HD .EQU 0 ; CKS: 0 FOR NON-REMOVABLE MEDIA
|
|
ALS_HD .EQU 256 ; ALS: BLKS / 8 = 2048 / 8 = 256 (ROUNDED UP)
|
|
;
|
|
;
|
|
; 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: 64 SECS/TRK (LOGICAL), 128 BYTES/SEC
|
|
; BLOCKSIZE (BLS) = 2K, DIRECTORY ENTRIES = 256
|
|
; ROM DISK SIZE = TOTAL ROM - 32K RESERVED FOR SYSTEM USE
|
|
;
|
|
.DW CKS_ROM
|
|
.DW ALS_ROM
|
|
.DB (2048 / 128) ; RECORDS PER BLOCK (BLS / 128)
|
|
DPB_ROM:
|
|
.DW 64 ; SPT: SECTORS PER TRACK
|
|
.DB 4 ; BSH: BLOCK SHIFT FACTOR
|
|
.DB 15 ; BLM: BLOCK MASK
|
|
#IF ((ROMBLKS - 1) < 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: 64 SECS/TRK, 128 BYTES/SEC
|
|
; BLOCKSIZE (BLS) = 2K, DIRECTORY ENTRIES = 256
|
|
; RAM DISK SIZE = TOTAL RAM - 64K RESERVED FOR SYSTEM USE
|
|
;
|
|
.DW CKS_RAM
|
|
.DW ALS_RAM
|
|
.DB (2048 / 128) ; RECORDS PER BLOCK (BLS / 128)
|
|
DPB_RAM:
|
|
.DW 64 ; SPT: SECTORS PER TRACK
|
|
.DB 4 ; BSH: BLOCK SHIFT FACTOR
|
|
.DB 15 ; BLM: BLOCK MASK
|
|
#IF ((RAMBLKS - 1) < 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
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; 4MB RAM FLOPPY DRIVE, 32 TRKS, 1024 SECS/TRK, 128 BYTES/SEC
|
|
; BLOCKSIZE (BLS) = 2K, DIRECTORY ENTRIES = 256
|
|
; SEC/TRK ENGINEERED SO THAT AFTER DEBLOCKING, SECTOR NUMBER OCCUPIES 1 BYTE (0-255)
|
|
;
|
|
.DW CKS_HD
|
|
.DW ALS_HD
|
|
.DB (2048 / 128) ; RECORDS PER BLOCK (BLS / 128)
|
|
DPB_RF:
|
|
.DW 1024 ; SPT: SECTORS PER TRACK
|
|
.DB 4 ; BSH: BLOCK SHIFT FACTOR
|
|
.DB 15 ; BLM: BLOCK MASK
|
|
.DB 0 ; EXM: EXTENT MASK
|
|
.DW 2047 ; DSM: TOTAL STORAGE IN BLOCKS - 1 BLK = (4MB / 2K BLS) - 1 = 2047
|
|
.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 0 ; CKS: ZERO FOR NON-REMOVABLE MEDIA
|
|
.DW 0 ; OFF: RESERVED TRACKS = 0 TRK
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; GENERIC HARD DISK DRIVE (8MB DATA SPACE + 128K RESERVED SPACE)
|
|
; LOGICAL: 1040 TRKS (16 RESERVED), 64 SECS/TRK, 128 BYTES/SEC
|
|
; PHYSICAL: 65 CYLS (1 RESERVED), 16 HEADS/CYL, 16 SECS/TRK, 512 BYTES/SEC
|
|
; BLOCKSIZE (BLS) = 4K, DIRECTORY ENTRIES = 512
|
|
;
|
|
.DW CKS_HD
|
|
.DW ALS_HD
|
|
.DB (4096 / 128) ; RECORDS PER BLOCK (BLS / 128)
|
|
DPB_HD:
|
|
.DW 64 ; 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 = (8MB / 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 16 ; OFF: RESERVED TRACKS = 16 TRKS * (16 TRKS * 16 HEADS * 16 SECS * 512 BYTES) = 128K
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
; IBM 720KB 3.5" FLOPPY DRIVE, 80 TRKS, 36 SECS/TRK, 512 BYTES/SEC
|
|
; BLOCKSIZE (BLS) = 2K, DIRECTORY ENTRIES = 128
|
|
;
|
|
.DW CKS_FD
|
|
.DW ALS_FD
|
|
.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
|
|
;
|
|
.DW CKS_FD
|
|
.DW ALS_FD
|
|
.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
|
|
;
|
|
.DW CKS_FD
|
|
.DW ALS_FD
|
|
.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 1 ; 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, 15 SECS/TRK, 512 BYTES/SEC
|
|
; BLOCKSIZE (BLS) = 2K, DIRECTORY ENTRIES = 256
|
|
;
|
|
.DW CKS_FD
|
|
.DW ALS_FD
|
|
.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, 77 TRKS, 15 SECS/TRK, 512 BYTES/SEC
|
|
; BLOCKSIZE (BLS) = 2K, DIRECTORY ENTRIES = 256
|
|
;
|
|
.DW CKS_FD
|
|
.DW ALS_FD
|
|
.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 569 ; DSM: TOTAL STORAGE IN BLOCKS - 1 BLK = ((1,155K - 15K OFF) / 2K BLS) - 1 = 569
|
|
.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
|
|
;
|
|
#IF (PLATFORM == PLT_UNA)
|
|
SECBUF .FILL 512,0 ; PHYSICAL DISK SECTOR BUFFER
|
|
#ENDIF
|
|
;
|
|
;==================================================================================================
|
|
; CBIOS BUFFERS
|
|
;==================================================================================================
|
|
;
|
|
;BUFFERS:
|
|
;
|
|
BUFPOOL .EQU $ ; START OF BUFFER POOL
|
|
;
|
|
;==================================================================================================
|
|
; COLD BOOT INITIALIZATION
|
|
;
|
|
; THIS CODE IS PLACED IN THE BDOS BUFFER AREA TO CONSERVE SPACE. SINCE
|
|
; COLD BOOT DOES NO DISK IO, SO THIS IS SAFE.
|
|
;
|
|
;==================================================================================================
|
|
;
|
|
; .ORG BUFFERS
|
|
.FILL 16 * 4,0 ; RESERVED FOR DRVMAP TABLE
|
|
.FILL 16 * 16,0 ; RESERVED FOR DPH TABLE
|
|
;
|
|
INIT:
|
|
; SAVE INCOMING BOOT DEVICE/UNIT & LU
|
|
LD (BOOTDL),DE ; D -> BOOTDEV, E -> BOOTLU
|
|
|
|
; 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,$CD ; "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
|
|
|
|
#IF (PLATFORM == PLT_UNA)
|
|
; MAKE SURE UNA EXEC PAGE IS ACTIVE
|
|
LD BC,$01FB ; UNA FUNC = SET BANK
|
|
LD DE,$800E ; SWITCH BACK TO EXEC BANK
|
|
CALL $FFFD ; DO IT (RST 08 NOT SAFE HERE)
|
|
|
|
; INSTALL UNA INVOCATION VECTOR FOR RST 08
|
|
LD A,$C3 ; JP INSTRUCTION
|
|
LD (8),A ; STORE AT 0x0008
|
|
LD HL,($FFFE) ; UNA ENTRY VECTOR
|
|
LD (9),HL ; STORE AT 0x0009
|
|
#ENDIF
|
|
|
|
; PARAMETER INITIALIZATION
|
|
LD A,DEFIOBYTE ; LOAD DEFAULT IOBYTE
|
|
LD (IOBYTE),A ; STORE IT
|
|
|
|
#IF ((PLATFORM != PLT_N8) & (PLATFORM != PLT_MK4) & (PLATFORM != PLT_S100) & (PLATFORM != PLT_UNA))
|
|
IN A,(RTC) ; RTC PORT, BIT 6 HAS STATE OF CONFIG JUMPER
|
|
BIT 6,A ; BIT 6 HAS CONFIG JUMPER STATE
|
|
LD A,DEFIOBYTE ; ASSUME WE WANT DEFAULT IOBYTE VALUE
|
|
JR NZ,INIT1 ; IF BIT6=1, NOT SHORTED, CONTINUE WITH DEFAULT
|
|
LD A,ALTIOBYTE ; LOAD ALT IOBYTE VALUE
|
|
INIT1:
|
|
LD (IOBYTE),A ; SET THE ACTIVE IOBYTE
|
|
#ENDIF
|
|
|
|
; INIT DEFAULT DRIVE TO A: FOR NOW
|
|
XOR A ; ZERO
|
|
LD (DEFDRIVE),A ; STORE IT
|
|
|
|
; STARTUP MESSAGE
|
|
CALL NEWLINE ; FORMATTING
|
|
LD DE,STR_BANNER ; POINT TO BANNER
|
|
CALL WRITESTR ; DISPLAY IT
|
|
CALL NEWLINE ; FORMATTING
|
|
|
|
#IF (PLATFORM == PLT_UNA)
|
|
; SAVE COMMAND PROCESSOR IMAGE TO MALLOCED CACHE IN UNA BIOS PAGE
|
|
LD C,$F7 ; UNA MALLOC
|
|
LD DE,CCPSIZ ; SIZE OF CCP
|
|
RST 08 ; DO IT
|
|
CALL NZ,PANIC ; BIG PROBLEM
|
|
LD (CCPBUF),HL ; SAVE THE ADDRESS (IN BIOS MEM)
|
|
|
|
LD BC,$01FB ; UNA FUNC = SET BANK
|
|
LD DE,$800D ; UBIOS_PAGE (SEE PAGES.INC)
|
|
RST 08 ; DO IT
|
|
PUSH DE ; SAVE PREVIOUS BANK
|
|
|
|
LD HL,CPM_LOC ; ADDRESS IN HI MEM OF CCP
|
|
LD DE,(CCPBUF) ; ADDRESS OF CCP BUF IN BIOS MEM
|
|
LD BC,CCPSIZ ; SIZE OF CCP
|
|
LDIR ; DO IT
|
|
|
|
LD BC,$01FB ; UNA FUNC = SET BANK
|
|
POP DE ; RECOVER OPERATING BANK
|
|
RST 08 ; DO IT
|
|
#ELSE
|
|
; SAVE COMMAND PROCESSOR TO DEDICATED CACHE IN RAM BANK 1
|
|
LD C,BID_USR ; B = SRC BANK = USR BANK = TPA
|
|
LD B,BID_HB ; C = DEST BANK = HB BANK
|
|
CALL HB_XCOPY ; SET BANKS FOR INTERBANK COPY
|
|
LD HL,CPM_LOC ; COPY FROM CCP LOCATION IN USR BANK
|
|
LD DE,$0800 ; TO FIXED LOCATION IN HB BANK
|
|
LD BC,CCPSIZ ; COPY CONTENTS OF COMMAND PROCESSOR
|
|
CALL HB_COPY ; DO IT
|
|
#ENDIF
|
|
|
|
; DISK SYSTEM INITIALIZATION
|
|
CALL BLKRES ; RESET DISK (DE)BLOCKING ALGORITHM
|
|
CALL MD_INIT ; INITIALIZE MEMORY DISK DRIVER (RAM/ROM)
|
|
CALL DRV_INIT ; INITIALIZE DRIVE MAP
|
|
CALL DPH_INIT ; INITIALIZE DPH TABLE AND BUFFERS
|
|
CALL NEWLINE ; FORMATTING
|
|
;
|
|
; DISPLAY FREE MEMORY
|
|
LD DE,STR_LDR ; FORMATTING
|
|
CALL WRITESTR ; AND PRINT IT
|
|
LD HL,CBIOS_END ; SUBTRACT HIGH WATER
|
|
LD DE,(BUFTOP) ; ... FROM TOP OF CBIOS
|
|
OR A ; ... WITH CF CLEAR
|
|
SBC HL,DE ; ... SO HL GETS BYTES FREE
|
|
CALL PRTDEC ; PRINT IT
|
|
LD DE,STR_MEMFREE ; ADD DESCRIPTION
|
|
CALL WRITESTR ; AND PRINT IT
|
|
;
|
|
LD A,(DEFDRIVE) ; GET DEFAULT DRIVE
|
|
LD (CDISK),A ; ... AND SETUP CDISK
|
|
;
|
|
; SETUP AUTOSTART COMMAND
|
|
LD HL,CMD ; ADDRESS OF STARTUP COMMAND
|
|
LD DE,CCP+7 ; START OF COMMAND BUFFER IN CCP
|
|
LD BC,CMDLEN ; LENGTH OF AUTOSTART COMMAND
|
|
LDIR ; INSTALL IT
|
|
;
|
|
RET
|
|
;
|
|
CMD .DB CMDLEN - 1
|
|
#IFDEF AUTOCMD
|
|
.TEXT AUTOCMD
|
|
#ENDIF
|
|
.DB 0
|
|
CMDLEN .EQU $ - CMD
|
|
;
|
|
STR_BANNER .DB OSLBL, " for ", PLATFORM_NAME, ", CBIOS v", BIOSVER, "$"
|
|
STR_MEMFREE .DB " Disk Buffer Bytes Free\r\n$"
|
|
;
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
MD_INIT:
|
|
;
|
|
#IF (PLATFORM == PLT_UNA)
|
|
;
|
|
; INITIALIZE RAM DISK BY FILLING DIRECTORY WITH 'E5' BYTES
|
|
; FILL FIRST 8K OF RAM DISK TRACK 1 WITH 'E5'
|
|
;
|
|
#IF (CLRRAMDISK != CLR_NEVER)
|
|
LD BC,$01FB ; UNA FUNC = SET BANK
|
|
LD DE,$8000 ; FIRST BANK OF RAM DISK
|
|
CALL $FFFD ; DO IT (RST 08 NOT SAFE HERE)
|
|
|
|
#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 $E5
|
|
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
|
|
; LD A,BID_USR ; SWITCH BACK TO USR BANK
|
|
; CALL HB_SETBNK ; .. SO WRITESTR WILL WORK
|
|
|
|
LD BC,$01FB ; UNA FUNC = SET BANK
|
|
LD DE,$800E ; SWITCH BACK TO EXEC BANK FOR WRITESTR
|
|
CALL $FFFD ; DO IT (RST 08 NOT SAFE HERE)
|
|
|
|
LD DE,STR_INITRAMDISK ; RAM DISK INIT MESSAGE
|
|
CALL WRITESTR ; DISPLAY IT
|
|
|
|
; LD A,BID_RAMD ; SWITCH BACK TO FIRST BANK
|
|
; CALL HB_SETBNK ; .. OF RAM DISK
|
|
|
|
LD BC,$01FB ; UNA FUNC = SET BANK
|
|
LD DE,$8000 ; FIRST BANK OF RAM DISK
|
|
CALL $FFFD ; DO IT (RST 08 NOT SAFE HERE)
|
|
|
|
LD HL,0 ; SOURCE ADR FOR FILL
|
|
LD BC,$2000 ; LENGTH OF FILL IS 8K
|
|
LD A,$E5 ; FILL VALUE
|
|
CALL FILL ; DO IT
|
|
CLRRAM3:
|
|
; LD A,BID_USR ; USR BANK (TPA)
|
|
; CALL HB_SETBNK ; SELECT IT
|
|
|
|
LD BC,$01FB ; UNA FUNC = SET BANK
|
|
LD DE,$800E ; SWITCH BACK TO EXEC BANK
|
|
CALL $FFFD ; DO IT (RST 08 NOT SAFE HERE)
|
|
|
|
#ENDIF
|
|
|
|
#ELSE
|
|
;
|
|
; 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,BID_RAMD ; FIRST BANK OF RAM DISK
|
|
CALL HB_SETBNK ; SELECT IT
|
|
|
|
#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 $E5
|
|
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
|
|
LD A,BID_USR ; SWITCH BACK TO USR BANK
|
|
CALL HB_SETBNK ; .. SO WRITESTR WILL WORK
|
|
LD DE,STR_INITRAMDISK ; RAM DISK INIT MESSAGE
|
|
CALL WRITESTR ; DISPLAY IT
|
|
LD A,BID_RAMD ; SWITCH BACK TO FIRST BANK
|
|
CALL HB_SETBNK ; .. OF RAM DISK
|
|
LD HL,0 ; SOURCE ADR FOR FILL
|
|
LD BC,$2000 ; LENGTH OF FILL IS 8K
|
|
LD A,$E5 ; FILL VALUE
|
|
CALL FILL ; DO IT
|
|
CLRRAM3:
|
|
LD A,BID_USR ; USR BANK (TPA)
|
|
CALL HB_SETBNK ; SELECT IT
|
|
#ENDIF
|
|
;
|
|
#ENDIF
|
|
;
|
|
RET
|
|
;
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
#IF (PLATFORM == PLT_UNA)
|
|
;
|
|
DRV_INIT:
|
|
;
|
|
; PERFORM UNA BIOS SPECIFIC INITIALIZATION
|
|
; UPDATE DRVMAP BASED ON AVAILABLE UNA UNITS
|
|
;
|
|
; SETUP THE DRVMAP STRUCTURE
|
|
LD HL,(BUFTOP) ; GET CURRENT BUFFER TOP
|
|
INC HL ; SKIP 1 BYTE FOR ENTRY COUNT PREFIX
|
|
LD (DRVMAPADR),HL ; SAVE AS DRIVE MAP ADDRESS
|
|
LD (BUFTOP),HL ; ... AND AS NEW BUFTOP
|
|
;
|
|
LD B,0 ; START WITH UNIT 0
|
|
;
|
|
DRV_INIT1: ; LOOP THRU ALL UNITS AVAILABLE
|
|
LD C,$48 ; UNA FUNC: GET DISK TYPE
|
|
LD L,0 ; PRESET UNIT COUNT TO ZERO
|
|
CALL $FFFD ; CALL UNA, B IS ASSUMED TO BE UNTOUCHED!!!
|
|
LD A,L ; UNIT COUNT TO A
|
|
OR A ; PAST END?
|
|
JR Z,DRV_INIT2 ; WE ARE DONE
|
|
PUSH BC ; SAVE UNIT
|
|
CALL DRV_INIT3 ; PROCESS THE UNIT
|
|
POP BC ; RESTORE UNIT
|
|
INC B ; NEXT UNIT
|
|
JR DRV_INIT1 ; LOOP
|
|
;
|
|
DRV_INIT2: ; FINALIZE THE DRIVE MAP
|
|
RET ; DONE
|
|
;
|
|
DRV_INIT3: ; PROCESS CURRENT UNIT (SEE UNA PROTOIDS.INC)
|
|
LD A,D ; MOVE DISK TYPE TO A
|
|
; CALL PC_LBKT ; *DEBUG*
|
|
; CALL PRTHEXBYTE ; *DEBUG*
|
|
; CALL PC_RBKT ; *DEBUG*
|
|
;
|
|
CALL DRV_INIT4 ; MAKE A DRIVE MAP ENTRY
|
|
LD A,D ; LOAD DRIVE TYPE
|
|
CP $40 ; RAM/ROM?
|
|
RET Z ; DONE IF SO
|
|
; CP $?? ; FLOPPY DRIVE?
|
|
; RET Z ; DONE IF SO
|
|
CALL DRV_INIT4 ; ANOTHER ENTRY FOR HARD DISK
|
|
LD A,1 ; BUT WITH SLICE VALUE OF 1
|
|
INC HL ; BUMP TO SLICE POSITION
|
|
LD (HL),A ; SAVE IT
|
|
RET ; DONE
|
|
;
|
|
DRV_INIT4:
|
|
; ALLOCATE SPACE IN DRVMAP
|
|
PUSH BC ; SAVE INCOMING UNIT NUM
|
|
LD BC,4 ; 4 BYTES PER ENTRY
|
|
CALL ALLOC ; ALLOCATE
|
|
CALL NZ,PANIC ; SHOULD NEVER ERROR HERE
|
|
PUSH BC ; MOVE MEM PTR
|
|
POP HL ; ... TO HL
|
|
POP BC ; RECOVER UNIT NUM
|
|
LD (HL),B ; SAVE IT IN FIRST BYTE OF DRV MAP ENTRY
|
|
PUSH HL ; SAVE HL
|
|
LD HL,(DRVMAPADR) ; POINT TO DRIVE MAP
|
|
DEC HL ; BACK TO ENTRY COUNT
|
|
INC (HL) ; INCREMENT THE ENTRY COUNT
|
|
POP HL ; RECOVER HL
|
|
RET ; DONE
|
|
;
|
|
#ELSE
|
|
;
|
|
DRV_INIT:
|
|
;
|
|
; PERFORM HBIOS SPECIFIC INITIALIZATION
|
|
; BUILD DRVMAP BASED ON AVAILABLE HBIOS DISK DEVICE LIST
|
|
;
|
|
; SETUP THE DRVMAP STRUCTURE
|
|
LD HL,(BUFTOP) ; GET CURRENT BUFFER TOP
|
|
INC HL ; SKIP 1 BYTE FOR ENTRY COUNT PREFIX
|
|
LD (DRVMAPADR),HL ; SAVE AS DRVMAP ADDRESS
|
|
LD (BUFTOP),HL ; AND AS NEW BUFTOP
|
|
;
|
|
; SETUP TO LOOP THROUGH AVAILABLE DEVICES
|
|
LD B,BF_DIODEVCNT ; HBIOS FUNC: DEVICE COUNT
|
|
RST 08 ; CALL HBIOS, DEVICE COUNT TO B
|
|
LD A,B ; COUNT TO A
|
|
OR A ; SET FLAGS
|
|
RET Z ; HANDLE ZERO DEVICES (ALBEIT POORLY)
|
|
LD C,0 ; USE C AS DEVICE LIST INDEX
|
|
;
|
|
DRV_INIT1: ; DEVICE ENUMERATION LOOP
|
|
PUSH BC ; PRESERVE LOOP CONTROL
|
|
LD B,BF_DIODEVINF ; HBIOS FUNC: DEVICE INFO
|
|
RST 08 ; CALL HBIOS, DEVICE/UNIT TO C
|
|
CALL DRV_INIT3 ; MAKE DRIVE MAP ENTRY(S)
|
|
POP BC ; RESTORE LOOP CONTROL
|
|
INC C ; INCREMENT LIST INDEX
|
|
DJNZ DRV_INIT1 ; LOOP AS NEEDED
|
|
RET ; FINISHED
|
|
;
|
|
DRV_INIT3: ; PROCESS DEVICE/UNIT
|
|
LD A,C ; DEVICE/UNIT TO A
|
|
PUSH AF ; SAVE DEVICE/UNIT
|
|
CALL DRV_INIT4 ; MAKE A DRIVE MAP ENTRY
|
|
POP AF ; RESTORE DEVICE/UNIT
|
|
CP DIODEV_IDE ; FIRST SLICE CAPABLE DEVICE?
|
|
RET C ; DONE IF NOT SLICE WORTHY
|
|
CALL DRV_INIT4 ; MAKE ANOTHER ENTRY IF HARD DISK
|
|
LD A,1 ; ... BUT WITH SLICE = 1
|
|
INC HL ; BUMP TO SLICE POSITION
|
|
LD (HL),A ; SAVE IT
|
|
RET ; DONE
|
|
;
|
|
DRV_INIT4: ; MAKE A DRIVE MAP ENTRY
|
|
; ALLOCATE SPACE FOR ENTRY
|
|
PUSH AF ; SAVE INCOMING DEVICE/UNIT
|
|
LD BC,4 ; 4 BYTES PER ENTRY
|
|
CALL ALLOC ; ALLOCATE SPACE
|
|
CALL NZ,PANIC ; SHOULD NEVER ERROR HERE
|
|
PUSH BC ; MOVE MEM PTR
|
|
POP HL ; ... TO HL
|
|
POP AF ; RECOVER DEVICE/UNIT
|
|
LD (HL),A ; SAVE IT IN FIRST BYTE OF DRVMAP
|
|
PUSH HL ; SAVE ENTRY PTR
|
|
LD HL,(DRVMAPADR) ; POINT TO DRIVE MAP
|
|
DEC HL ; BACKUP TO ENTRY COUNT
|
|
INC (HL) ; INCREMENT THE ENTRY COUNT
|
|
POP HL ; RECOVER ENTRY POINTER
|
|
RET ; DONE
|
|
;
|
|
#ENDIF
|
|
;
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
DPH_INIT:
|
|
;
|
|
; ITERATE THROUGH DRIVE MAP TO BUILD DPH ENTRIES DYNAMICALLY
|
|
;
|
|
LD DE,STR_DPHINIT ; POINT TO MSG
|
|
CALL WRITESTR ; DISPLAY IT
|
|
CALL NEWLINE ; FORMATTING
|
|
;
|
|
; ALLOCATE DPH POOL SPACE BASED ON DRIVE COUNT
|
|
LD HL,(DRVMAPADR) ; LOAD DRIVE MAP POINTER
|
|
DEC HL ; BACKUP TO ENTRY COUNT
|
|
LD A,(HL) ; GET THE ENTRY COUNT
|
|
LD L,A ; PUT DRIVE COUNT
|
|
LD H,0 ; ... INTO HL
|
|
ADD HL,HL ; MULTIPLY
|
|
ADD HL,HL ; ... BY SIZE
|
|
ADD HL,HL ; ... OF DPH (16)
|
|
ADD HL,HL ; ... FOR TOTAL SIZE
|
|
PUSH HL ; MOVE POOL SIZE
|
|
POP BC ; ... INTO BC FOR MEM ALLOC
|
|
CALL ALLOC ; ALLOCATE THE SPACE
|
|
CALL NZ,PANIC ; SHOULD NEVER ERROR
|
|
;
|
|
; SET DPHTOP TO START OF ALLOCATED SPACE
|
|
PUSH BC ; MOVE MEM POINTER
|
|
POP HL ; ... TO HL
|
|
LD (DPHTOP),HL ; ... AND SAVE IN DPHTOP
|
|
;
|
|
; ALLOCATE DIRECTORY BUFFER
|
|
LD BC,128 ; SIZE OF DIRECTORY BUFFER
|
|
CALL ALLOC ; ALLOCATE THE SPACE
|
|
CALL NZ,PANIC ; SHOULD NEVER ERROR
|
|
PUSH BC ; MOVE MEM POINTER
|
|
POP HL ; ... TO HL
|
|
LD (DIRBUF),HL ; ... AND SAVE IN DIRBUF
|
|
;
|
|
; SETUP FOR DPH BUILD LOOP
|
|
LD HL,(DRVMAPADR) ; POINT TO DRIVE MAP
|
|
DEC HL ; BACKUP TO ENTRY COUNT
|
|
LD B,(HL) ; LOOP DRVCNT TIMES
|
|
LD C,0 ; DRIVE INDEX
|
|
INC HL ; BUMP TO START OF DRIVE MAP
|
|
;
|
|
DPH_INIT1:
|
|
; DISPLAY DRIVE LETTER
|
|
LD A,C ; LOAD DRIVE INDEX
|
|
ADD A,'A' ; MAKE IT A DISPLAY LETTER
|
|
LD DE,STR_LDR ; LEADER STRING
|
|
CALL WRITESTR ; DISPLAY IT
|
|
CALL COUT ; DISPLAY DRIVE LETTER
|
|
CALL PC_COLON ; DISPLAY COLON
|
|
LD A,'=' ; SEPARATOR
|
|
CALL COUT ; DISPLAY IT
|
|
; SETUP FOR DPH BUILD ROUTINE INCLUDING DPH BLOCK ALLOCATION
|
|
LD D,(HL) ; D := DEV/UNIT
|
|
INC HL ; BUMP
|
|
LD E,(HL) ; E := SLICE
|
|
INC HL ; BUMP
|
|
CALL PRTDUS ; PRINT DEVICE/UNIT/SLICE
|
|
LD A,D ; A := DEV/UNIT
|
|
PUSH HL ; SAVE DRIVE MAP POINTER
|
|
; MATCH AND SAVE DEFAULT DRIVE BASED ON BOOT DEVICE/UNIT/SLICE
|
|
LD HL,BOOTDEV ; POINT TO BOOT DEVICE/UNIT
|
|
LD A,D ; LOAD CURRENT DEVICE/UNIT
|
|
CP (HL) ; MATCH?
|
|
JR NZ,DPH_INIT1A ; BYPASS IF NOT BOOT DEVICE/UNIT
|
|
DEC HL ; POINT TO BOOT SLICE
|
|
LD A,E ; LOAD CURRENT SLICE
|
|
CP (HL) ; MATCH?
|
|
JR NZ,DPH_INIT1A ; BYPASS IF NOT BOOT SLICE
|
|
LD A,C ; LOAD THE CURRENT DRIVE NUM
|
|
LD (DEFDRIVE),A ; SAVE AS DEFAULT
|
|
DPH_INIT1A:
|
|
LD DE,(DPHTOP) ; GET ADDRESS OF NEXT DPH
|
|
PUSH DE ; ... AND SAVE IT
|
|
; INVOKE THE DPH BUILD ROUTINE
|
|
PUSH BC ; SAVE LOOP CONTROL
|
|
CALL MAKDPH ; MAKE THE DPH AT DE, DEV/UNIT IN A
|
|
;CALL NZ,PANIC ; FOR NOW, PANIC ON ANY ERROR
|
|
POP BC ; RESTORE LOOP CONTROL
|
|
; STORE THE DPH POINTER IN DRIVE MAP
|
|
POP DE ; RESTORE DPH ADDRESS TO DE
|
|
POP HL ; RESTORE DRIVE MAP POINTER TO HL
|
|
;RET NZ ; ABORT ON ERROR
|
|
JR Z,DPH_INIT2 ; IF MAKDPH OK, CONTINUE
|
|
LD DE,0 ; ... OTHERWISE ZERO OUT THE DPH POINTER
|
|
DPH_INIT2:
|
|
LD (HL),E ; SAVE DPH POINTER
|
|
INC HL ; ... IN
|
|
LD (HL),D ; ... DRIVE MAP
|
|
INC HL ; AND BUMP TO START OF NEXT ENTRY
|
|
; UPDATE DPH ALLOCATION TOP
|
|
LD A,16 ; SIZE OF A DPH ENTRY
|
|
EX DE,HL ; HL := DPH POINTER
|
|
CALL ADDHLA ; CALC NEW DPHTOP
|
|
LD (DPHTOP),HL ; SAVE IT
|
|
; HANDLE THE NEXT DRIVE MAP ENTRY
|
|
EX DE,HL ; HL := NEXT DRIVE MAP ENTRY
|
|
INC C ; NEXT DRIVE
|
|
DJNZ DPH_INIT1 ; LOOP AS NEEDED
|
|
RET ; DONE
|
|
;
|
|
MAKDPH:
|
|
;
|
|
; MAKE A DPH AT ADDRESS IN DE FOR DEV/UNIT IN A
|
|
;
|
|
PUSH DE ; SAVE INCOMING DPH ADDRESS
|
|
;
|
|
#IF (PLATFORM == PLT_UNA)
|
|
;
|
|
LD B,A ; UNIT NUM TO B
|
|
LD C,$48 ; UNA FUNC: GET DISK TYPE
|
|
CALL $FFFD ; CALL UNA
|
|
LD A,D ; MOVE DISK TYPE TO A
|
|
;
|
|
; DERIVE DPB ADDRESS BASED ON DISK TYPE
|
|
CP $40 ; RAM/ROM DRIVE?
|
|
JR Z,MAKDPH0 ; HANDLE RAM/ROM DRIVE IF SO
|
|
; CP $?? ; FLOPPY DRIVE?
|
|
; JR Z,XXXXX ; HANDLE FLOPPY
|
|
LD DE,DPB_HD ; ASSUME HARD DISK
|
|
JR MAKDPH1 ; CONTINUE
|
|
;
|
|
MAKDPH0: ; HANDLE RAM/ROM
|
|
LD C,$45 ; UNA FUNC: GET DISK INFO
|
|
LD DE,$9000 ; 512 BYTE BUFFER *** FIX!!! ***
|
|
CALL $FFFD ; CALL UNA
|
|
BIT 7,B ; TEST RAM DRIVE BIT
|
|
LD DE,DPB_ROM ; ASSUME ROM
|
|
JR Z,MAKDPH1 ; NOT SET, ROM DRIVE, CONTINUE
|
|
LD DE,DPB_RAM ; OTHERWISE, MUST BE RAM DRIVE
|
|
JR MAKDPH1 ; CONTINUE
|
|
;
|
|
#ELSE
|
|
;
|
|
; DETERMINE APPROPRIATE DPB
|
|
LD DE,DPB_ROM ; ASSUME ROM
|
|
CP DIODEV_MD+0 ; ROM?
|
|
JR Z,MAKDPH1 ; YES, JUMP AHEAD
|
|
LD DE,DPB_RAM ; ASSUME ROM
|
|
CP DIODEV_MD+1 ; ROM?
|
|
JR Z,MAKDPH1 ; YES, JUMP AHEAD
|
|
AND $F0 ; IGNORE UNIT NIBBLE NOW
|
|
LD DE,DPB_FD144 ; ASSUME FLOPPY
|
|
CP DIODEV_FD ; FLOPPY?
|
|
JR Z,MAKDPH1 ; YES, JUMP AHEAD
|
|
LD DE,DPB_RF ; ASSUME RAM FLOPPY
|
|
CP DIODEV_RF ; RAM FLOPPY?
|
|
JR Z,MAKDPH1 ; YES, JUMP AHEAD
|
|
LD DE,DPB_HD ; EVERYTHING ELSE IS ASSUMED TO BE HARD DISK
|
|
JR MAKDPH1 ; JUMP AHEAD
|
|
;
|
|
#ENDIF
|
|
;
|
|
MAKDPH1:
|
|
;
|
|
; BUILD THE DPH
|
|
POP HL ; HL := START OF DPH
|
|
LD A,8 ; SIZE OF DPH RESERVED AREA
|
|
CALL ADDHLA ; LEAVE IT ALONE (ZERO FILLED)
|
|
|
|
LD BC,(DIRBUF) ; ADDRESS OF DIRBUF
|
|
LD (HL),C ; PLUG DIRBUF
|
|
INC HL ; ... INTO DPH
|
|
LD (HL),B ; ... AND BUMP
|
|
INC HL ; ... TO NEXT DPH ENTRY
|
|
|
|
LD (HL),E ; PLUG DPB ADDRESS
|
|
INC HL ; ... INTO DPH
|
|
LD (HL),D ; ... AND BUMP
|
|
INC HL ; ... TO NEXT ENTRY
|
|
DEC DE ; POINT
|
|
DEC DE ; ... TO START
|
|
DEC DE ; ... OF
|
|
DEC DE ; ... DPB
|
|
DEC DE ; ... PREFIX DATA (CKS & ALS BUF SIZES)
|
|
CALL MAKDPH2 ; HANDLE CKS BUF, THEN FALL THRU FOR ALS BUF
|
|
RET NZ ; BAIL OUT ON ERROR
|
|
MAKDPH2:
|
|
EX DE,HL ; POINT HL TO CKS/ALS SIZE ADR
|
|
LD C,(HL) ; BC := CKS/ALS SIZE
|
|
INC HL ; ... AND BUMP
|
|
LD B,(HL) ; ... PAST
|
|
INC HL ; ... CKS/ALS SIZE
|
|
EX DE,HL ; BC AND HL ROLES RESTORED
|
|
LD A,B ; CHECK TO SEE
|
|
OR C ; ... IF BC IS ZERO
|
|
JR Z,MAKDPH3 ; IF ZERO, BYPASS ALLOC, USE ZERO FOR ADDRESS
|
|
CALL ALLOC ; ALLOC BC BYTES, ADDRESS RETURNED IN BC
|
|
JR NZ,ERR_BUFOVF ; HANDLE OVERFLOW ERROR
|
|
MAKDPH3:
|
|
LD (HL),C ; SAVE CKS/ALS BUF
|
|
INC HL ; ... ADDRESS IN
|
|
LD (HL),B ; ... DPH AND BUMP
|
|
INC HL ; ... TO NEXT DPH ENTRY
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
ALLOC:
|
|
;
|
|
; ALLOCATE BC BYTES FROM BUF POOL, RETURN STARTING
|
|
; ADDRESS IN BC. LEAVE ALL OTHER REGS ALONE EXCEPT A
|
|
; Z FOR SUCCESS, NZ FOR FAILURE
|
|
;
|
|
PUSH DE ; SAVE ORIGINAL DE
|
|
PUSH HL ; SAVE ORIGINAL HL
|
|
LD HL,(BUFTOP) ; HL := CURRENT BUFFER TOP
|
|
PUSH HL ; SAVE AS START OF NEW BUFFER
|
|
PUSH BC ; GET BYTE COUNT
|
|
POP DE ; ... INTO DE
|
|
ADD HL,DE ; ADD IT TO BUFFER TOP
|
|
LD A,$FF ; ASSUME OVERFLOW FAILURE
|
|
JR C,ALLOC1 ; IF OVERFLOW, BYPASS WITH A == $FF
|
|
PUSH HL ; SAVE IT
|
|
LD DE,$10000 - CBIOS_END ; SETUP DE FOR OVERFLOW TEST
|
|
ADD HL,DE ; CHECK FOR OVERFLOW
|
|
POP HL ; RECOVER HL
|
|
LD A,$FF ; ASSUME FAILURE
|
|
JR C,ALLOC1 ; IF OVERFLOW, CONTINUE WITH A == $FF
|
|
LD (BUFTOP),HL ; SAVE NEW TOP
|
|
INC A ; SIGNAL SUCCESS
|
|
;
|
|
ALLOC1:
|
|
POP BC ; BUF START ADDRESS TO BC
|
|
POP HL ; RESTORE ORIGINAL HL
|
|
POP DE ; RESTORE ORIGINAL DE
|
|
OR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
ERR_BUFOVF:
|
|
LD DE,STR_BUFOVF
|
|
JR ERR
|
|
;
|
|
ERR_INVMED:
|
|
LD DE,STR_INVMED
|
|
JR ERR
|
|
;
|
|
ERR:
|
|
CALL WRITESTR
|
|
OR $FF
|
|
RET
|
|
;
|
|
PRTDUS:
|
|
;
|
|
; PRINT THE DEVICE/UNIT/SLICE INFO
|
|
; ON INPUT D HAS DEVICE/UNIT, E HAS SLICE
|
|
; DESTROY NO REGISTERS OTHER THAN A
|
|
;
|
|
#IF (PLATFORM == PLT_UNA)
|
|
;
|
|
PUSH BC ; PRESERVE BC
|
|
PUSH DE ; PRESERVE DE
|
|
PUSH HL ; PRESERVE HL
|
|
|
|
LD B,D ; B := UNIT
|
|
LD C,$48 ; UNA FUNC: GET DISK TYPE
|
|
CALL $FFFD ; CALL UNA
|
|
LD A,D ; DISK TYPE TO A
|
|
|
|
CP $40
|
|
JR Z,PRTDUS1 ; IF SO, HANDLE RAM/ROM
|
|
|
|
LD DE,DEVIDE ; IDE STRING
|
|
CP $41 ; IDE?
|
|
JR Z,PRTDUSX ; IF YES, PRINT
|
|
LD DE,DEVPPIDE ; PPIDE STRING
|
|
CP $42 ; PPIDE?
|
|
JR Z,PRTDUSX ; IF YES, PRINT
|
|
LD DE,DEVSD ; SD STRING
|
|
CP $43 ; SD?
|
|
JR Z,PRTDUSX ; IF YES, PRINT
|
|
LD DE,DEVDSD ; DSD STRING
|
|
CP $44 ; DSD?
|
|
JR Z,PRTDUSX ; IF YES, PRINT
|
|
|
|
LD DE,DEVUNK ; OTHERWISE, UNKNOWN
|
|
JR PRTDUSX ; PRINT IT
|
|
|
|
PRTDUS1:
|
|
LD C,$45 ; UNA FUNC: GET DISK INFO
|
|
LD DE,$9000 ; 512 BYTE BUFFER *** FIX!!! ***
|
|
CALL $FFFD ; CALL UNA
|
|
BIT 7,B ; TEST RAM DRIVE BIT
|
|
LD DE,DEVROM ; ASSUME ROM
|
|
JR Z,PRTDUSX ; IF SO, DISPLAY ROM
|
|
LD DE,DEVRAM ; ELSE RAM
|
|
JR Z,PRTDUSX ; DO IT
|
|
|
|
PRTDUSX:
|
|
CALL WRITESTR ; PRINT DEVICE NAME
|
|
POP HL ; RECOVER HL
|
|
POP DE ; RECOVER DE
|
|
POP BC ; RECOVER BC
|
|
LD A,D ; LOAD DEVICE/UNIT
|
|
CALL PRTDECB ; PRINT IT
|
|
CALL PC_COLON ; FORMATTING
|
|
LD A,E ; LOAD SLICE
|
|
CALL PRTDECB ; PRINT IT
|
|
RET
|
|
;
|
|
DEVRAM .DB "RAM$"
|
|
DEVROM .DB "ROM$"
|
|
DEVIDE .DB "IDE$"
|
|
DEVPPIDE .DB "PPIDE$"
|
|
DEVSD .DB "SD$"
|
|
DEVDSD .DB "DSD$"
|
|
DEVUNK .DB "UNK$"
|
|
;
|
|
#ELSE
|
|
;
|
|
PUSH DE ; PRESERVE DE
|
|
PUSH HL ; PRESERVE HL
|
|
LD A,D ; LOAD DEVICE/UNIT
|
|
RRCA ; ROTATE DEVICE
|
|
RRCA ; ... BITS
|
|
RRCA ; ... INTO
|
|
RRCA ; ... LOWEST 4 BITS
|
|
AND $0F ; ISOLATE DEVICE BITS
|
|
ADD A,A ; MULTIPLE BY TWO FOR WORD TABLE
|
|
LD HL,DEVTBL ; POINT TO START OF DEVICE NAME TABLE
|
|
CALL ADDHLA ; ADD A TO HL TO POINT TO TABLE ENTRY
|
|
LD A,(HL) ; DEREFERENCE HL TO LOC OF DEVICE NAME STRING
|
|
INC HL ; ...
|
|
LD D,(HL) ; ...
|
|
LD E,A ; ...
|
|
CALL WRITESTR ; PRINT THE DEVICE NMEMONIC
|
|
POP HL ; RECOVER HL
|
|
POP DE ; RECOVER DE
|
|
LD A,D ; LOAD DEVICE/UNIT
|
|
AND $0F ; ISOLATE UNIT
|
|
CALL PRTDECB ; PRINT IT
|
|
CALL PC_COLON ; FORMATTING
|
|
LD A,E ; LOAD SLICE
|
|
CALL PRTDECB ; PRINT IT
|
|
RET
|
|
;
|
|
DEVTBL: ; DEVICE TABLE
|
|
.DW DEV00, DEV01, DEV02, DEV03
|
|
.DW DEV04, DEV05, DEV06, DEV07
|
|
.DW DEV08, DEV09, DEV10, DEV11
|
|
.DW DEV12, DEV13, DEV14, DEV15
|
|
;
|
|
DEVUNK .DB "???$"
|
|
DEV00 .DB "MD$"
|
|
DEV01 .DB "FD$"
|
|
DEV02 .DB "RAMF$"
|
|
DEV03 .DB "IDE$"
|
|
DEV04 .DB "ATAPI$"
|
|
DEV05 .DB "PPIDE$"
|
|
DEV06 .DB "SD$"
|
|
DEV07 .DB "PRPSD$"
|
|
DEV08 .DB "PPPSD$"
|
|
DEV09 .DB "HDSK$"
|
|
DEV10 .EQU DEVUNK
|
|
DEV11 .EQU DEVUNK
|
|
DEV12 .EQU DEVUNK
|
|
DEV13 .EQU DEVUNK
|
|
DEV14 .EQU DEVUNK
|
|
DEV15 .EQU DEVUNK
|
|
;
|
|
#ENDIF
|
|
;
|
|
DPHTOP .DW 0 ; CURRENT TOP OF DPH POOL
|
|
DIRBUF .DW 0 ; DIR BUF POINTER
|
|
BUFTOP .DW BUFPOOL ; CURRENT TOP OF BUF POOL
|
|
BOOTDL:
|
|
BOOTLU .DB 0
|
|
BOOTDEV .DB 0
|
|
;
|
|
STR_INITRAMDISK .DB "\r\nFormatting RAMDISK...$"
|
|
STR_LDR .DB "\r\n $"
|
|
STR_DPHINIT .DB "\r\n\r\nConfiguring Drives...$"
|
|
STR_BUFOVF .DB " *** Insufficient Memory ***$"
|
|
STR_INVMED .DB " *** Invalid Device ID ***$"
|
|
;
|
|
;==================================================================================================
|
|
;
|
|
;==================================================================================================
|
|
;
|
|
.FILL CBIOS_END - $,$00
|
|
;
|
|
SLACK .EQU (CBIOS_END - BUFPOOL)
|
|
.ECHO "CBIOS buffer space: "
|
|
.ECHO SLACK
|
|
.ECHO " bytes.\n"
|
|
;
|
|
.ECHO "CBIOS total space used: "
|
|
.ECHO $ - CBIOS_LOC
|
|
.ECHO " bytes.\n"
|
|
;
|
|
.END
|
|
|