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.
4757 lines
104 KiB
4757 lines
104 KiB
;===============================================================================
|
|
; FDU - FLOPPY DISK UTILITY PROGRAM FOR RETROBREW COMPUTERS
|
|
;===============================================================================
|
|
;
|
|
; AUTHOR: WAYNE WARTHEN (DERIVED FROM FDCMON BY ANDREW LYNCH & DAN WERNER)
|
|
;_______________________________________________________________________________
|
|
;
|
|
; CHANGELOG:
|
|
; 2011-08-05: v1.0 INITIAL RELEASE
|
|
; 2011-08-25: v1.1 SUPPORT ZETA
|
|
; SUPPORT INT/WAIT
|
|
; 2011-08-28: v1.2 FIX ZETA RESET LOGIC (from Sergey)
|
|
; FIX ZETA MOTOR DISPLAY (from Sergey)
|
|
; NEW ZETA DISK CHANGE DISPLAY
|
|
; 2011-09-01: V1.3 ADDED CONFIGURABLE CPU FREQUENCY FOR DELAYS
|
|
; 2011-09-05: V1.4 USE CPU FREQUENCY FOR POLLING TIMEOUT
|
|
; 2011-09-19: V1.5 IMPROVED USE OF FDC RESET ON ZETA
|
|
; ADDED FDC RESET TO FDC CONTROL MENU
|
|
; 2011-09-24: V1.5a MINOR CORRECTION TO POLLING ROUTINE TO AVOID OVERRUN
|
|
; 2011-10-07: V2.0 PRELIMINARY SUPPORT FOR DUAL IDE
|
|
; 2011-10-13: V2.1 PRELIMINARY SUPPORT FOR N8
|
|
; 2011-10-20: V2.2 INCLUDE BUSY & NDMA BITS IN RESULTS BYTE READY CHECKING
|
|
; 2011-10-22: V2.3 ADDED VERIFY FUNCTION
|
|
; 2011-11-25: V2.4 ADDED SUPPORT FOR DISKIO V3
|
|
; 2012-01-09: V2.5 WARM START CP/M AT TERMINATION TO LOGOUT ALL DRIVES
|
|
; 2012-01-09: V2.6 EXPERIMENTAL SUPPORT FOR 5 1/4" DRIVES
|
|
; 2012-04-05: V2.7 SUPPORT FOR 8" DRIVES
|
|
; 2012-04-06: V2.7a FIXED MEDIA SELECTION MENU (DUPLICATE ENTRIES)
|
|
; 2012-04-08: V2.7b HANDLE DENSITY SELECT PROPERLY
|
|
; 2012-05-22: V2.8 ADDED NEW MEDIA DEFINITIONS (5.25", 320K)
|
|
; 2012-06-01: V2.9 ADDED INTERLEAVE CAPABILITY IN FORMAT COMMAND
|
|
; 2012-06-05: V3.0 DOCUMENTATION CLEANUP
|
|
; 2012-07-01: V3.1 MODIFY HLT FOR 8" MEDIA (50ms PER YD-180 SPEC)
|
|
; 2013-06-17: V3.2 CLEANED UP THE SRT, HLT, AND HUT VALUES
|
|
; 2015-02-10: V3.3 ADDED ZETA SBC V2 SUPPORT (SERGEY KISELEV)
|
|
; 2015-03-25: V4.0 RENAMED APP FDTST --> FD
|
|
; 2017-09-02: V5.0 RENAMED APP TO FDU (FLOPPY DISK UTILITY)
|
|
; DYNAMIC FDC SELECTION AT STARTUP
|
|
; DYNAMIC CPU SPEED ADJUSTMENT
|
|
; 2017-12-16: V5.1 IMPROVED POLLING READ/WRITE PERFORMANCE
|
|
; 2018-01-08: V5.2 ADDED RCBUS SUPPORT FOR:
|
|
; - SCOTT BAKER (SMB) SMC 9266 FDC
|
|
; - SCOTT BAKER (SMB) WDC 37C65 FDC
|
|
; 2018-09-05: v5.3 ADDED SUPPORT FOR SMALLZ80
|
|
; - USE EOT=R TO END R/W AFTER ONE SECTOR INSTEAD
|
|
; OF USING PULSE TC
|
|
; 2020-01-05: V5.4 ADDED SUPPORT FOR DYNO FDC
|
|
; 2020-04-29: v5.5 ADDED SUPPORT FOR ETCHED PIXELS FDC
|
|
; 2020-12-12: v5.6 UPDATED SMALLZ80 TO NEW I/O ADDRESSES
|
|
; 2021-03-24: v5.7 ADDED SOME SINGLE-SIDED FORMATS
|
|
; 2021-07-26: v5.8 ADDED SUPPORT MBC FDC
|
|
;
|
|
;_______________________________________________________________________________
|
|
;
|
|
; BUILDING:
|
|
; CAN BE BUILT WITH TASM LIKE THIS:
|
|
; TASM -t80 -b -fFF FDU.ASM FDU.COM FDU.LST
|
|
;
|
|
; TODO:
|
|
; 1) CURRENT TRACK IS UPDATED EVEN IF SEEK FAILS! (DEFER, RECOVERS AUTOMATICALLY)
|
|
; 2) CLEAN UP UTILITY ROUTINES (DEFER, NOT IMPORTANT)
|
|
; 3) TIGHTEN UP THE TIMING LOOPS (DEFER, LOW PRIORITY, WORKING FINE AS IS)
|
|
; 4) MOVE STX EVALUATION TO DIO LEVEL? (NOT SURE..., LOW PRIORITY)
|
|
; 5) ALLOW <ESC> TO ABORT AT PROMPTS
|
|
; 6) ALLOW <ESC> TO ABORT OPERATION IN PROGRESS
|
|
; 7) MOVE CONTINUE PROMPT TO A SEPARATE ROUTINE
|
|
;
|
|
;_______________________________________________________________________________
|
|
;
|
|
;
|
|
FALSE .EQU 0
|
|
TRUE .EQU ~FALSE
|
|
;
|
|
; FDC ID
|
|
;
|
|
FDC_DIO .EQU 0
|
|
FDC_DIO3 .EQU 1
|
|
FDC_ZETA .EQU 2
|
|
FDC_ZETA2 .EQU 3
|
|
FDC_DIDE .EQU 4
|
|
FDC_N8 .EQU 5
|
|
FDC_RCSMC .EQU 6
|
|
FDC_RCWDC .EQU 7
|
|
FDC_SMZ80 .EQU 8
|
|
FDC_DYNO .EQU 9
|
|
FDC_EPFDC .EQU 10
|
|
FDC_MBC .EQU 11
|
|
;
|
|
; FDC MODE
|
|
;
|
|
_DIO .EQU $01 ; CUSTOM FOR DIO BOARD
|
|
_DIO3 .EQU $02 ; CUSTOM FOR DIO3 BOARD
|
|
_ZETA .EQU $04 ; CUSTOM FOR ZETA
|
|
_RCSMC .EQU $08 ; CUSTOM FOR RCBUS SMB SMC MODULE
|
|
_PCAT .EQU $10 ; PC/AT MODE IN NEWER CONTROLLERS
|
|
;
|
|
;===============================================================================
|
|
; MAIN PROGRAM PROCEDURE
|
|
;===============================================================================
|
|
;
|
|
.ORG 00100H
|
|
|
|
; SAVE PREVIOUS STACK POINTER, AND SWITCH TO OUR STACK
|
|
LD (STACKSAV),SP
|
|
LD SP,STACK
|
|
|
|
; GENERAL INITIALIZATION (BIOS & SPEED DETECTION)
|
|
CALL INIT
|
|
JR NZ,EXIT
|
|
|
|
; SELECT FD CONTROLLER
|
|
CALL NEWLINE
|
|
CALL FDCSEL
|
|
JR NZ,EXIT
|
|
|
|
; SETUP FOR DEFAULT MEDIA AND RUN THE MAIN MENU
|
|
CALL DIO_SETMEDIA
|
|
LD HL,MM_INFO
|
|
CALL RUNMENU
|
|
|
|
EXIT:
|
|
LD C,00H ; CP/M SYSTEM RESET (WARM START)
|
|
CALL 0005H ; RETURN TO CP/M
|
|
|
|
; CLEAN UP AND RETURN TO OS
|
|
CALL NEWLINE
|
|
LD SP,(STACKSAV)
|
|
RET
|
|
|
|
HALT ; SHOULD NEVER GET HERE
|
|
|
|
;
|
|
;===============================================================================
|
|
; FD CONTROLLER SELECTION
|
|
;===============================================================================
|
|
;
|
|
INIT:
|
|
; DISPLAY PROGRAM STARTUP BANNER
|
|
CALL NEWLINE
|
|
LD DE,STR_BANNER
|
|
CALL WRITESTR
|
|
|
|
; UNA UBIOS DETECTION...
|
|
LD A,($FFFD) ; FIXED LOCATION OF UNA API VECTOR
|
|
CP $C3 ; JP INSTRUCTION?
|
|
JR NZ,INIT1 ; IF NOT, NOT UNA
|
|
LD HL,($FFFE) ; GET JP ADDRESS
|
|
LD A,(HL) ; GET BYTE AT TARGET ADDRESS
|
|
CP $FD ; FIRST BYTE OF UNA PUSH IX INSTRUCTION
|
|
JR NZ,INIT1 ; IF NOT, NOT UNA
|
|
INC HL ; POINT TO NEXT BYTE
|
|
LD A,(HL) ; GET NEXT BYTE
|
|
CP $E5 ; SECOND BYTE OF UNA PUSH IX INSTRUCTION
|
|
JR NZ,INIT1 ; IF NOT, NOT UNA
|
|
LD DE,STR_UBIOS ; POINT TO UBIOS TAG
|
|
CALL WRITESTR ; AND DISPLAY IT
|
|
|
|
; GET CPU SPEED FROM UBIOS
|
|
LD C,0F8H ; UNA BIOS GET PHI FUNCTION
|
|
RST 08 ; RETURNS SPEED IN HZ IN DE:HL
|
|
LD B,4 ; DIVIDE MHZ IN DE:HL BY 100000H
|
|
INIT0:
|
|
SRL D ; ... TO GET APPROX CPU SPEED IN
|
|
RR E ; ...MHZ. THROW AWAY HL, AND
|
|
DJNZ INIT0 ; ...RIGHT SHIFT DE BY 4.
|
|
INC E ; FIX UP FOR VALUE TRUNCATION
|
|
LD A,E ; PUT IN A
|
|
LD (CPUSPD),A ; SAVE IT
|
|
JR INIT3 ; AND DONE
|
|
|
|
INIT1:
|
|
; ROMWBW HBIOS DETECTION
|
|
LD HL,(0FFFEH) ; HL := ADR OR ROMWBW HBIOS IDENT
|
|
LD A,(HL) ; GET FIRST BYTE OF ROMWBW MARKER
|
|
CP 'W' ; MATCH?
|
|
JP NZ,INIT2 ; ABORT WITH INVALID CONFIG BLOCK
|
|
INC HL ; NEXT BYTE (MARKER BYTE 2)
|
|
LD A,(HL) ; LOAD IT
|
|
CP ~'W' ; MATCH?
|
|
JP NZ,INIT2 ; ABORT WITH INVALID CONFIG BLOCK
|
|
LD DE,STR_HBIOS ; POINT TO HBIOS TAG
|
|
CALL WRITESTR ; AND DISPLAY IT
|
|
|
|
; GET CPU SPEED FROM HBIOS
|
|
LD B,0F8H ; HBIOS SYSGET FUNCTION 0XF8
|
|
LD C,0F0H ; CPUINFO SUBFUNCTION 0XF0
|
|
RST 08 ; DO IT, L := CPU SPEED IN MHZ
|
|
LD A,L ; MOVE IT TO A
|
|
LD (CPUSPD),A ; SAVE IT
|
|
JR INIT3 ; AND DONE
|
|
|
|
INIT2:
|
|
;; NO KNOWN BIOS DETECTED, BAIL OUT W/ ERROR
|
|
;LD DE,STR_BIOERR
|
|
;CALL WRITESTR
|
|
;OR 0FFH
|
|
;RET
|
|
LD A,20
|
|
LD (CPUSPD),A
|
|
|
|
INIT3:
|
|
; COMPUTE CPU SCALER FOR DELAY LOOPS
|
|
LD A,(CPUSPD)
|
|
CP 3 ; TEST FOR <= 2 (SPECIAL HANDLING)
|
|
JR C,INIT4 ; IF <= 2, SPECIAL PROCESSING
|
|
SUB 2 ; ADJUST AS REQUIRED BY DELAY FUNCTIONS
|
|
JR INIT5 ; AND CONTINUE
|
|
INIT4:
|
|
LD A,1 ; USE THE MIN VALUE OF 1
|
|
INIT5:
|
|
LD (CPUSCL),A ; UPDATE CPU SCALER VALUE
|
|
|
|
; REMAINDER OF BANNER
|
|
CALL NEWLINE
|
|
LD DE,STR_BANNER2
|
|
CALL WRITESTR
|
|
|
|
; INITIALIZATION DONE
|
|
XOR A
|
|
RET
|
|
|
|
STR_BANNER .DB "Floppy Disk Utility (FDU) v5.8, 26-Jul-2021$"
|
|
STR_BANNER2 .DB "Copyright (C) 2021, Wayne Warthen, GNU GPL v3","$"
|
|
STR_HBIOS .DB " [HBIOS]$"
|
|
STR_UBIOS .DB " [UBIOS]$"
|
|
;
|
|
STR_BIOERR .DB "\r\n\r\n*** Unknown BIOS ***\r\n$"
|
|
;
|
|
CPUSPD .DB 20 ; DEFAULT TO SAFE (HIGH) VALUE
|
|
CPUSCL .DB 0 ; CPU SPEED DELAY SCALER (COMPUTED)
|
|
|
|
;
|
|
;===============================================================================
|
|
; FD CONTROLLER SELECTION
|
|
;===============================================================================
|
|
;
|
|
FDCSEL:
|
|
; PROMPT
|
|
LD DE,FSS_MENU
|
|
CALL WRITESTR
|
|
;
|
|
FDCSEL1:
|
|
CALL GETKEYUC
|
|
CP 'X' ; EXIT?
|
|
JR NZ,FDCSEL2 ; IF NOT, CONTINUE
|
|
OR 0FFH ; ELSE SET NZ FOR EXIT REQUEST
|
|
RET ; AND RETURN
|
|
;
|
|
FDCSEL2:
|
|
SUB 'A' ; ASCII -> BINARY
|
|
CP FDCCNT ; TOO HIGH?
|
|
JR NC,FDCSEL1 ; IF SO, TRY AGAIN
|
|
;
|
|
; SAVE SELECTED FDC IDENTIFIER
|
|
LD (FDCID),A ; RECORD THE FDC ID
|
|
RLCA ; TIMES 4
|
|
RLCA ; ... FOR 4 BYTE ENTRIES
|
|
LD HL,FDCTBL ; POINT TO FDC INSTANCE TABLE
|
|
CALL ADDHLA ; OFFSET TO DESRIED ENTRY, A TRASHED
|
|
LD E,(HL) ; LOAD LABEL PTR INTO DE
|
|
INC HL ; ...
|
|
LD D,(HL) ; ...
|
|
LD (FDCLBL),DE ; SAVE LABEL PTR
|
|
INC HL ; BUMP TO CFG POINTER
|
|
LD E,(HL) ; LOAD CFG PTR INTO DE
|
|
INC HL ; ...
|
|
LD D,(HL) ; ...
|
|
LD (FDCCFG),DE ; SAVE CFG PTR
|
|
LD IY,(FDCCFG) ; AND INIT A WORKING COPY
|
|
LD A,(IY+CFG_MODE) ; GET MODE BITMAP BYTE
|
|
LD (FDCBM),A ; SAVE IT TO ACTIVE WORKING COPY
|
|
;
|
|
LD DE,(FDCLBL) ; GET LABEL POINTER
|
|
CALL WRITESTR ; AND DISPLAY IT
|
|
;
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; DONE
|
|
;
|
|
; TABLE OF FDC CONTROLLERS
|
|
;
|
|
FDCTBL: ; LABEL CONFIG DATA
|
|
; ----- -----------
|
|
.DW STR_DIO, CFG_DIO
|
|
.DW STR_DIO3, CFG_DIO3
|
|
.DW STR_ZETA, CFG_ZETA
|
|
.DW STR_ZETA2, CFG_ZETA2
|
|
.DW STR_DIDE, CFG_DIDE
|
|
.DW STR_N8, CFG_N8
|
|
.DW STR_RCSMC, CFG_RCSMC
|
|
.DW STR_RCWDC, CFG_RCWDC
|
|
.DW STR_SMZ80, CFG_SMZ80
|
|
.DW STR_DYNO, CFG_DYNO
|
|
.DW STR_EPFDC, CFG_EPFDC
|
|
.DW STR_MBC, CFG_MBC
|
|
FDCCNT .EQU ($-FDCTBL)/4 ; FD CONTROLLER COUNT
|
|
;
|
|
; FDC LABEL STRINGS
|
|
;
|
|
STR_DIO .TEXT "DISKIO$"
|
|
STR_DIO3 .TEXT "DISKIO3$"
|
|
STR_ZETA .TEXT "ZETA$"
|
|
STR_ZETA2 .TEXT "ZETA2$"
|
|
STR_DIDE .TEXT "D-IDE$"
|
|
STR_N8 .TEXT "N8$"
|
|
STR_RCSMC .TEXT "RC-SMC$"
|
|
STR_RCWDC .TEXT "RC-WDC$"
|
|
STR_SMZ80 .TEXT "SMZ80$"
|
|
STR_DYNO .TEXT "DYNO$"
|
|
STR_EPFDC .TEXT "EPFDC$"
|
|
STR_MBC .TEXT "MBC$"
|
|
;
|
|
; FDC CONFIGURATION BLOCKS
|
|
;
|
|
CFG_MSR .EQU 0
|
|
CFG_DATA .EQU 1
|
|
CFG_DIR .EQU 2
|
|
CFG_DOR .EQU 3
|
|
CFG_DCR .EQU 4
|
|
CFG_DACK .EQU 5
|
|
CFG_TC .EQU 6
|
|
CFG_DMA .EQU 7
|
|
CFG_MODE .EQU 8
|
|
;
|
|
CFG_DIO:
|
|
.DB 036H ; FDC MAIN STATUS REGISTER
|
|
.DB 037H ; FDC DATA PORT
|
|
.DB 038H ; DATA INPUT REGISTER
|
|
.DB 03AH ; DIGITAL OUTPUT REGISTER (LATCH)
|
|
.DB 0FFH ; DCR
|
|
.DB 0FFH ; DACK
|
|
.DB 0FFH ; TERMINAL COUNT (W/ DACK)
|
|
.DB 03CH ; PSEUDO DMA DATA PORT
|
|
.DB _DIO ; MODE=
|
|
CFG_DIO3:
|
|
.DB 036H ; FDC MAIN STATUS REGISTER
|
|
.DB 037H ; FDC DATA PORT
|
|
.DB 038H ; DATA INPUT REGISTER
|
|
.DB 03AH ; DIGITAL OUTPUT REGISTER (LATCH)
|
|
.DB 0FFH ; DCR
|
|
.DB 0FFH ; DACK
|
|
.DB 0FFH ; TERMINAL COUNT (W/ DACK)
|
|
.DB 03CH ; PSEUDO DMA DATA PORT
|
|
.DB _DIO3 ; MODE=
|
|
CFG_ZETA:
|
|
.DB 036H ; FDC MAIN STATUS REGISTER
|
|
.DB 037H ; FDC DATA PORT
|
|
.DB 038H ; DATA INPUT REGISTER
|
|
.DB 03AH ; DIGITAL OUTPUT REGISTER (LATCH)
|
|
.DB 0FFH ; DCR
|
|
.DB 0FFH ; DACK
|
|
.DB 0FFH ; TERMINAL COUNT (W/ DACK)
|
|
.DB 03CH ; PSEUDO DMA DATA PORT
|
|
.DB _ZETA ; MODE=
|
|
;
|
|
CFG_ZETA2:
|
|
.DB 030H ; FDC MAIN STATUS REGISTER
|
|
.DB 031H ; FDC DATA PORT
|
|
.DB 0FFH ; DATA INPUT REGISTER
|
|
.DB 038H ; DIGITAL OUTPUT REGISTER
|
|
.DB 028H ; CONFIGURATION CONTROL REGISTER
|
|
.DB 0FFH ; DACK
|
|
.DB 038H ; TERMINAL COUNT (W/ DACK)
|
|
.DB 0FFH ; NOT USED BY ZETA SBC V2
|
|
.DB _PCAT ; MODE=
|
|
;
|
|
CFG_DIDE:
|
|
.DB 02AH ; FDC MAIN STATUS REGISTER
|
|
.DB 02BH ; FDC DATA PORT
|
|
.DB 0FFH ; DATA INPUT REGISTER
|
|
.DB 02CH ; DOR
|
|
.DB 02DH ; DCR
|
|
.DB 03CH ; DACK
|
|
.DB 03DH ; TERMINAL COUNT (W/ DACK)
|
|
.DB 0FFH ; NOT USED BY DIDE
|
|
.DB _PCAT ; MODE=
|
|
;
|
|
CFG_N8:
|
|
.DB 08CH ; FDC MAIN STATUS REGISTER
|
|
.DB 08DH ; FDC DATA PORT
|
|
.DB 0FFH ; DATA INPUT REGISTER
|
|
.DB 092H ; DOR
|
|
.DB 091H ; DCR
|
|
.DB 090H ; DACK
|
|
.DB 093H ; TERMINAL COUNT (W/ DACK)
|
|
.DB 0FFH ; NOT USED BY N8
|
|
.DB _PCAT ; MODE=
|
|
;
|
|
CFG_RCSMC:
|
|
.DB 050H ; FDC MAIN STATUS REGISTER
|
|
.DB 051H ; FDC DATA PORT
|
|
.DB 0FFH ; DATA INPUT REGISTER
|
|
.DB 058H ; DIGITAL OUTPUT REGISTER (LATCH)
|
|
.DB 0FFH ; DCR
|
|
.DB 0FFH ; DACK
|
|
.DB 0FFH ; TERMINAL COUNT (W/ DACK)
|
|
.DB 0FFH ; PSEUDO DMA DATA PORT
|
|
.DB _RCSMC ; MODE=
|
|
;
|
|
CFG_RCWDC:
|
|
.DB 050H ; FDC MAIN STATUS REGISTER
|
|
.DB 051H ; FDC DATA PORT
|
|
.DB 0FFH ; DATA INPUT REGISTER
|
|
.DB 058H ; DIGITAL OUTPUT REGISTER (LATCH)
|
|
.DB 048H ; DCR
|
|
.DB 0FFH ; DACK
|
|
.DB 058H ; TERMINAL COUNT (W/ DACK)
|
|
.DB 0FFH ; PSEUDO DMA DATA PORT
|
|
.DB _PCAT ; MODE=
|
|
;
|
|
CFG_SMZ80:
|
|
.DB 074H ; FDC MAIN STATUS REGISTER
|
|
.DB 075H ; FDC DATA PORT
|
|
.DB 0FFH ; DATA INPUT REGISTER
|
|
.DB 072H ; DIGITAL OUTPUT REGISTER (LATCH)
|
|
.DB 077H ; DCR
|
|
.DB 0FFH ; DACK
|
|
.DB 0FFH ; TERMINAL COUNT (W/ DACK)
|
|
.DB 0FFH ; PSEUDO DMA DATA PORT
|
|
.DB _PCAT ; MODE=
|
|
;
|
|
CFG_DYNO:
|
|
.DB 084H ; FDC MAIN STATUS REGISTER
|
|
.DB 085H ; FDC DATA PORT
|
|
.DB 0FFH ; DATA INPUT REGISTER
|
|
.DB 086H ; DIGITAL OUTPUT REGISTER (LATCH)
|
|
.DB 087H ; DCR
|
|
.DB 0FFH ; DACK
|
|
.DB 086H ; TERMINAL COUNT (W/ DACK)
|
|
.DB 0FFH ; PSEUDO DMA DATA PORT
|
|
.DB _PCAT ; MODE=
|
|
;
|
|
CFG_EPFDC:
|
|
.DB 048H ; FDC MAIN STATUS REGISTER
|
|
.DB 049H ; FDC DATA PORT
|
|
.DB 0FFH ; DATA INPUT REGISTER
|
|
.DB 04AH ; DIGITAL OUTPUT REGISTER (LATCH)
|
|
.DB 04BH ; DCR
|
|
.DB 0FFH ; DACK
|
|
.DB 04CH ; TERMINAL COUNT (W/ DACK)
|
|
.DB 0FFH ; PSEUDO DMA DATA PORT
|
|
.DB _PCAT ; MODE=
|
|
;
|
|
CFG_MBC:
|
|
.DB 030H ; FDC MAIN STATUS REGISTER
|
|
.DB 031H ; FDC DATA PORT
|
|
.DB 0FFH ; DATA INPUT REGISTER
|
|
.DB 036H ; DIGITAL OUTPUT REGISTER (WHEN WRITTEN)
|
|
.DB 035H ; CONFIGURATION CONTROL REGISTER
|
|
.DB 036H ; DACK (WHEN READ)
|
|
.DB 037H ; TERMINAL COUNT (W/ DACK)
|
|
.DB 0FFH ; NOT USED BY ZETA SBC V2
|
|
.DB _PCAT ; MODE=
|
|
;
|
|
FDCID .DB 0 ; FDC IDENTIFIER (0 INDEXED)
|
|
FDCBM .DB 0 ; FDC ID BITMAP
|
|
FDCLBL .DW 0 ; POINTER TO ACTIVE FDC LABEL STRING
|
|
FDCCFG .DW 0 ; POINTER TO ACTIVE CFG DATA
|
|
;
|
|
FSS_MENU:
|
|
.TEXT "\r\n"
|
|
.TEXT "SELECT FLOPPY DISK CONTROLLER:\r\n"
|
|
.TEXT " (A) Disk IO ECB Board\r\n"
|
|
.TEXT " (B) Disk IO 3 ECB Board\r\n"
|
|
.TEXT " (C) Zeta SBC Onboard FDC\r\n"
|
|
.TEXT " (D) Zeta 2 SBC Onboard FDC\r\n"
|
|
.TEXT " (E) Dual IDE ECB Board\r\n"
|
|
.TEXT " (F) N8 Onboard FDC\r\n"
|
|
.TEXT " (G) RCBus SMC (SMB)\r\n"
|
|
.TEXT " (H) RCBus WDC (SMB)\r\n"
|
|
.TEXT " (I) SmallZ80 Expansion\r\n"
|
|
.TEXT " (J) Dyno-Card FDC, D1030\r\n"
|
|
.TEXT " (K) RCBus EPFDC\r\n"
|
|
.TEXT " (L) Multi-Board Computer FDC\r\n"
|
|
.TEXT " (X) Exit\r\n"
|
|
.TEXT "=== OPTION ===> $\r\n"
|
|
;
|
|
;===============================================================================
|
|
; MAIN MENU
|
|
;===============================================================================
|
|
;
|
|
; MAIN MENU DATA
|
|
;
|
|
MM_TABLE .DB 'S' \ .DW MMS_SETUP, MM_SETUP
|
|
MM_ENTSIZ .EQU $ - MM_TABLE
|
|
.DB 'R' \ .DW MMS_READ, MM_READ
|
|
.DB 'W' \ .DW MMS_WRITE, MM_WRITE
|
|
.DB 'F' \ .DW MMS_FORMAT, MM_FORMAT
|
|
.DB 'V' \ .DW MMS_VERIFY, MM_VERIFY
|
|
.DB 'I' \ .DW MMS_INITBUF, MM_INITBUF
|
|
.DB 'D' \ .DW MMS_DUMPBUF, MM_DUMPBUF
|
|
.DB 'C' \ .DW MMS_FDCMENU, MM_FDCMENU
|
|
.DB 'X' \ .DW MMS_EXIT, 0000H
|
|
MM_COUNT .EQU (($ - MM_TABLE) / MM_ENTSIZ) ; # ENTRIES IN TABLE
|
|
MM_INFO: .DW MM_DRAW
|
|
.DW MM_TABLE
|
|
.DB MM_ENTSIZ
|
|
.DB MM_COUNT
|
|
;
|
|
; MAIN MENU DISPLAY STRINGS
|
|
;
|
|
STR_MAINMENU:
|
|
.TEXT "=======================<< FDU MAIN MENU >>======================\r\n"
|
|
; .TEXT "(S)ETUP: UNIT=XX MEDIA=XXXXXXXXXXXXX MODE=XXXXXXXXXX TRACE=XX\r\n"
|
|
.TEXT "(S)ETUP: UNIT="
|
|
MV_UNIT .TEXT "XX"
|
|
.TEXT " MEDIA="
|
|
MV_MED .TEXT "XXXXXXXXXXXXX"
|
|
.TEXT " MODE="
|
|
MV_MODE .TEXT "XXXXXXXXXX"
|
|
.TEXT " TRACE="
|
|
MV_TRC .TEXT "XX"
|
|
.TEXT "\r\n"
|
|
.TEXT "----------------------------------------------------------------\r\n"
|
|
.TEXT "(R)EAD (W)RITE (F)ORMAT (V)ERIFY\r\n"
|
|
.TEXT "(I)NIT BUFFER (D)UMP BUFFER FDC (C)MDS E(X)IT\r\n"
|
|
.TEXT "=== OPTION ===> $\r\n"
|
|
;
|
|
MMS_SETUP: .TEXT "SETUP$"
|
|
MMS_READ: .TEXT "READ$"
|
|
MMS_WRITE: .TEXT "WRITE$"
|
|
MMS_FORMAT: .TEXT "FORMAT$"
|
|
MMS_VERIFY: .TEXT "VERIFY$"
|
|
MMS_INITBUF: .TEXT "INITIALIZE BUFFER$"
|
|
MMS_DUMPBUF: .TEXT "DUMP BUFFER$"
|
|
MMS_FDCMENU: .TEXT "FDC MENU$"
|
|
MMS_EXIT: .TEXT "EXIT$"
|
|
;
|
|
; MAIN MENU DRAW PROCEDURE
|
|
;
|
|
MM_DRAW:
|
|
CALL NEWLINE
|
|
CALL NEWLINE
|
|
|
|
; UPDATE FDC LABEL
|
|
LD DE,STR_MAINMENU + 5
|
|
LD A,' '
|
|
LD (DE),A
|
|
INC DE
|
|
LD HL,(FDCLBL)
|
|
CALL COPYSTR
|
|
LD A,' '
|
|
LD (DE),A
|
|
|
|
; UPDATE UNIT
|
|
LD DE,MV_UNIT
|
|
LD A,(DCD_UNIT)
|
|
CALL HEXSTRBYTE
|
|
|
|
; UPDATE MEDIA
|
|
LD DE,(MDB_LABEL)
|
|
LD HL,MV_MED
|
|
CALL STRCPY
|
|
|
|
; UPDATE MODE
|
|
LD A,(DCD_MD)
|
|
RLA
|
|
LD E,A
|
|
LD D,0
|
|
LD HL,MDT
|
|
ADD HL,DE
|
|
LD E,(HL)
|
|
INC HL
|
|
LD D,(HL)
|
|
EX DE,HL
|
|
LD E,(HL)
|
|
INC HL
|
|
LD D,(HL)
|
|
LD HL,MV_MODE
|
|
CALL STRCPY
|
|
|
|
; UPDATE TRACE
|
|
LD DE,MV_TRC
|
|
LD A,(DCD_TRACE)
|
|
CALL HEXSTRBYTE
|
|
|
|
; DISPLAY THE MENU
|
|
LD DE,STR_MAINMENU
|
|
CALL WRITESTR
|
|
|
|
RET
|
|
;
|
|
; MAIN MENU FUNCTIONS
|
|
;
|
|
MM_SETUP:
|
|
CALL MM_GETSETUP
|
|
CALL DIO_SETMEDIA
|
|
RET
|
|
|
|
MM_READ:
|
|
LD A,DOP_READ
|
|
LD (DCD_DOP),A
|
|
CALL MM_GETTGT
|
|
CALL MM_GETTGTPARMS
|
|
CALL MMOP_PROC
|
|
RET
|
|
|
|
MM_WRITE:
|
|
LD A,DOP_WRITE
|
|
LD (DCD_DOP),A
|
|
CALL MM_GETTGT
|
|
CALL MM_GETTGTPARMS
|
|
CALL MMOP_PROC
|
|
RET
|
|
|
|
MM_FORMAT:
|
|
LD A,DOP_FORMAT
|
|
LD (DCD_DOP),A
|
|
CALL MM_GETTGT
|
|
CALL MM_GETTGTPARMS
|
|
CALL MM_GETINTRLV
|
|
CALL MMOP_PROC
|
|
RET
|
|
|
|
MM_VERIFY:
|
|
LD A,DOP_VERIFY
|
|
LD (DCD_DOP),A
|
|
CALL MM_GETTGT
|
|
CALL MM_GETTGTPARMS
|
|
CALL MM_SETVFYBUF
|
|
CALL MMOP_PROC
|
|
RET
|
|
|
|
MM_INITBUF:
|
|
CALL PC_SPACE
|
|
LD DE,MMPS_IBOPT
|
|
CALL WRITESTR
|
|
MM_IBKEY:
|
|
CALL GETKEYUC
|
|
CP 'P' ; PATTERN
|
|
JP Z,MM_IBPAT
|
|
CP 'F' ; FILL
|
|
JP Z,MM_IBFILL
|
|
JP MM_IBKEY
|
|
MM_IBPAT:
|
|
LD DE,MMBS_PATTERN
|
|
CALL PC_SPACE
|
|
CALL WRITESTR
|
|
CALL MM_GETPATTERN
|
|
LD HL,BUFFER
|
|
LD DE,BUFSIZ
|
|
LD A,(DCD_PATTERN)
|
|
LD B,A
|
|
CALL PAT_BUFFER
|
|
RET
|
|
MM_IBFILL:
|
|
LD DE,MMBS_FILL
|
|
CALL WRITESTR
|
|
CALL PC_SPACE
|
|
CALL MM_GETFILL
|
|
LD HL,BUFFER
|
|
LD DE,BUFSIZ
|
|
LD A,(DCD_FILL)
|
|
LD B,A
|
|
CALL FILL_BUFFER
|
|
RET
|
|
|
|
MM_DUMPBUF:
|
|
LD HL,BUFFER ; SET ADDRESS TO DUMP
|
|
LD DE,BUFFER ; SET END ADDRESS
|
|
INC D ;
|
|
INC D ;
|
|
CALL DUMP_BUFFER ; DUMP BUFFER TO CONSOLE
|
|
RET
|
|
|
|
MM_FDCMENU:
|
|
CALL DIO_INIT
|
|
CALL FDCMENU
|
|
CALL DIO_TERM
|
|
RET
|
|
;
|
|
; MAIN MENU SUPPORT FUNCTIONS
|
|
;
|
|
MM_GETSETUP:
|
|
LD DE,MMP_UNIT
|
|
LD HL,DCD_UNIT
|
|
LD BC,0003H
|
|
CALL GETHEXBYTERNG
|
|
|
|
CALL MM_MEDIALIST
|
|
LD DE,MMP_MEDIA
|
|
LD HL,DCD_MT
|
|
LD B,0
|
|
LD A,MIT_ENTCNT
|
|
DEC A
|
|
LD C,A
|
|
CALL GETHEXBYTERNG
|
|
|
|
MM_GETMODE:
|
|
CALL MM_MODELIST
|
|
LD DE,MMP_MODE
|
|
LD HL,DCD_MD
|
|
LD B,0
|
|
LD A,MDT_ENTCNT
|
|
DEC A
|
|
LD C,A
|
|
CALL GETHEXBYTERNG
|
|
|
|
; VALIDATE MODE AGAINST CURRENT FDC
|
|
INC A ; PREP VALUE FOR LOOP
|
|
LD B,A ; PUT IN LOOP COUNTER
|
|
XOR A ; CLEAR A
|
|
SCF ; SET CF
|
|
MM_GETMODE1:
|
|
RLA ; ROTATE BIT ONE POSITION
|
|
DJNZ MM_GETMODE1 ; UNTIL BIT SET FOR MODE SPECIFIED
|
|
PUSH AF ; SAVE IT
|
|
LD A,(FDCID) ; A := FDC ID
|
|
LD HL,MD_MAP ; HL := START OF MODE MAP
|
|
CALL ADDHLA ; OFFSET TO CORRECT ENTRY FOR FDC
|
|
POP AF ; RECOVER MODE BIT VALUE
|
|
AND (HL) ; MASK WITH MODE MAP OF FDC
|
|
JR NZ,MM_TRACE ; NON-ZERO IS A MODE MATCH FOR FDC, CONTINUE
|
|
LD DE,MM_MODEERR ; INVALID MODE FOR FDC ERROR MESSAGE
|
|
CALL WRITESTR
|
|
JR MM_GETMODE
|
|
|
|
MM_TRACE:
|
|
LD DE,MMP_TRACE
|
|
LD HL,DCD_TRACE
|
|
LD BC,0001H
|
|
CALL GETHEXBYTERNG
|
|
|
|
RET
|
|
|
|
MM_GETFILL:
|
|
LD DE,MMP_FILL
|
|
LD HL,DCD_FILL
|
|
CALL GETHEXBYTE
|
|
RET
|
|
|
|
MM_GETPATTERN:
|
|
LD DE,MMP_PATTERN
|
|
LD HL,DCD_PATTERN
|
|
CALL GETHEXBYTE
|
|
RET
|
|
|
|
MM_GETTGT:
|
|
CALL PC_SPACE
|
|
LD A,(DCD_DOP)
|
|
LD DE,MMPS_TGTF
|
|
CP DOP_FORMAT
|
|
JP Z,MM_GETTGT0
|
|
LD DE,MMPS_TGTRW
|
|
MM_GETTGT0:
|
|
CALL WRITESTR
|
|
MM_GETTGT1:
|
|
CALL GETKEYUC
|
|
|
|
LD B,MMT_TRACK
|
|
LD DE,MMTS_TRACK
|
|
CP 'T'
|
|
JP Z,MM_GETTGT3
|
|
LD B,MMT_DISK
|
|
LD DE,MMTS_DISK
|
|
CP 'D'
|
|
JP Z,MM_GETTGT3
|
|
; FORMAT CANNOT DO THE NEXT ONES (GETTGT2 CHECKS FOR THIS)
|
|
LD B,MMT_SECTOR
|
|
LD DE,MMTS_SECTOR
|
|
CP 'S'
|
|
JP Z,MM_GETTGT2
|
|
LD B,MMT_RANDOM
|
|
LD DE,MMTS_RANDOM
|
|
CP 'R'
|
|
JP Z,MM_GETTGT2
|
|
JP MM_GETTGT1
|
|
MM_GETTGT2: ; PREVENT FORMAT FROM USING SECTOR OR RANDOM FUNCTIONS
|
|
LD A,(DCD_DOP)
|
|
CP DOP_FORMAT
|
|
JP Z,MM_GETTGT1
|
|
MM_GETTGT3:
|
|
LD A,B
|
|
LD (MMD_TGT),A
|
|
CALL WRITESTR
|
|
RET
|
|
|
|
MM_GETTGTPARMS:
|
|
LD A,(MMD_TGT)
|
|
CP MMT_DISK
|
|
JP Z,MM_GETTGTPARMS1
|
|
CP MMT_RANDOM
|
|
JP Z,MM_GETTGTPARMS1
|
|
CALL MM_GETTRACK
|
|
CALL MM_GETHEAD
|
|
LD A,(MMD_TGT)
|
|
CP MMT_TRACK
|
|
JP Z,MM_GETTGTPARMS1
|
|
CALL MM_GETSECTOR
|
|
JP MM_GETTGTPARMSX
|
|
MM_GETTGTPARMS1:
|
|
LD A,1 ; FIX UP THE SECTOR VALUE TO BE 1 IF NOT SINGLE SECTOR MODE
|
|
LD (DCD_SECTOR),A
|
|
MM_GETTGTPARMSX:
|
|
RET
|
|
|
|
MM_GETTRACK:
|
|
LD DE,MMP_TRACK
|
|
LD HL,DCD_TRACK
|
|
LD B,0
|
|
LD A,(MDB_NUMCYL)
|
|
DEC A
|
|
LD C,A
|
|
CALL GETHEXBYTERNG
|
|
RET
|
|
|
|
MM_GETHEAD:
|
|
LD DE,MMP_HEAD
|
|
LD HL,DCD_HEAD
|
|
LD B,0
|
|
LD A,(MDB_NUMHD)
|
|
DEC A
|
|
LD C,A
|
|
CALL GETHEXBYTERNG
|
|
RET
|
|
|
|
MM_GETSECTOR:
|
|
LD DE,MMP_SECTOR
|
|
LD HL,DCD_SECTOR
|
|
LD A,(MDB_SOT)
|
|
LD B,A
|
|
LD A,(MDB_EOT)
|
|
LD C,A
|
|
CALL GETHEXBYTERNG
|
|
RET
|
|
|
|
MM_GETINTRLV:
|
|
LD DE,MMP_INTRLV
|
|
LD HL,DCD_INTRLV
|
|
LD B,1
|
|
LD A,(MDB_NUMSEC)
|
|
LD C,A
|
|
CALL GETHEXBYTERNG
|
|
RET
|
|
|
|
MM_MEDIALIST:
|
|
LD HL,MIT
|
|
LD B,MIT_ENTCNT
|
|
LD C,0
|
|
MM_MEDIALISTLOOP:
|
|
CALL NEWLINE
|
|
LD A,C
|
|
CALL PRTHEXBYTE
|
|
CALL PC_COLON
|
|
CALL PC_SPACE
|
|
PUSH HL
|
|
|
|
LD A,(HL) ; HL = ENTRY VALUE
|
|
INC HL ; "
|
|
LD H,(HL) ; "
|
|
LD L,A ; "
|
|
|
|
INC HL
|
|
INC HL
|
|
|
|
LD A,(HL) ; HL = ENTRY VALUE
|
|
INC HL ; "
|
|
LD D,(HL) ; "
|
|
LD E,A ; "
|
|
|
|
CALL WRITESTR
|
|
|
|
POP HL
|
|
INC HL
|
|
INC HL
|
|
INC C
|
|
DJNZ MM_MEDIALISTLOOP
|
|
RET
|
|
|
|
MM_MODELIST:
|
|
LD HL,MDT
|
|
LD B,MDT_ENTCNT
|
|
LD C,0
|
|
MM_MODELISTLOOP:
|
|
CALL NEWLINE
|
|
LD A,C
|
|
CALL PRTHEXBYTE
|
|
CALL PC_COLON
|
|
CALL PC_SPACE
|
|
PUSH HL
|
|
|
|
LD A,(HL) ; HL = ENTRY VALUE
|
|
INC HL ; "
|
|
LD H,(HL) ; "
|
|
LD L,A ; "
|
|
|
|
INC HL
|
|
INC HL
|
|
|
|
LD A,(HL) ; HL = ENTRY VALUE
|
|
INC HL ; "
|
|
LD D,(HL) ; "
|
|
LD E,A ; "
|
|
|
|
CALL WRITESTR
|
|
|
|
POP HL
|
|
INC HL
|
|
INC HL
|
|
INC C
|
|
DJNZ MM_MODELISTLOOP
|
|
RET
|
|
|
|
MM_SETVFYBUF:
|
|
LD HL,BUFFER
|
|
LD DE,VFYBUF
|
|
LD BC,BUFSIZ
|
|
LDIR
|
|
RET
|
|
;
|
|
; MAIN MENU PROMPTS
|
|
;
|
|
MMP_FILL .TEXT "FILL VALUE$"
|
|
MMP_PATTERN .TEXT "PATTERN START VALUE$"
|
|
MMP_UNIT .TEXT "UNIT$"
|
|
MMP_TRACE .TEXT "TRACE LEVEL$"
|
|
MMP_TRACK .TEXT "TRACK$"
|
|
MMP_HEAD .TEXT "HEAD$"
|
|
MMP_SECTOR .TEXT "SECTOR$"
|
|
MMP_MEDIA .TEXT "MEDIA$"
|
|
MMP_MODE .TEXT "MODE$"
|
|
MMP_INTRLV .TEXT "INTERLEAVE$"
|
|
;
|
|
; MAIN MENU TARGET
|
|
;
|
|
MMT_SECTOR .EQU 'S' ; PERFORM OPERATION ON ONE SECTOR
|
|
MMT_TRACK .EQU 'T' ; PERFORM OPERATION ON ONE TRACK
|
|
MMT_DISK .EQU 'D' ; PERFORM OPERATION ON ENTIRE DISK
|
|
MMT_RANDOM .EQU 'R' ; PERFORM OPERATION ON RANDOM SECTORS
|
|
;
|
|
; MAIN MENU TARGET STRINGS
|
|
;
|
|
MMTS_SECTOR .TEXT "SECTOR$"
|
|
MMTS_TRACK .TEXT "TRACK$"
|
|
MMTS_DISK .TEXT "DISK$"
|
|
MMTS_RANDOM .TEXT "RANDOM$"
|
|
;
|
|
; MAIN MENU DATA
|
|
;
|
|
MMD_TGT .DB MMT_SECTOR
|
|
;
|
|
; MAIN MENU PROMPT STRINGS
|
|
;
|
|
MMPS_TGTRW .TEXT "(S)ECTOR, (T)RACK, (D)ISK, (R)ANDOM ===> $"
|
|
MMPS_TGTF .TEXT "(T)RACK, (D)ISK ===> $"
|
|
MMPS_IBOPT .TEXT "(P)ATTERN, (F)ILL ===> $"
|
|
;
|
|
; MAIN MENU BUFFER OPTIONS
|
|
;
|
|
MMBS_PATTERN .TEXT "PATTERN$"
|
|
MMBS_FILL .TEXT "FILL$"
|
|
;
|
|
;
|
|
;
|
|
MM_MODEERR .TEXT "\r\n\r\n*** SELECTED MODE NOT SUPPORTED ON HARDWARE ***\r\n$"
|
|
;
|
|
;________________________________________________________________________________________________________________________________
|
|
;
|
|
; MAIN MENU OPERATIONS
|
|
;________________________________________________________________________________________________________________________________
|
|
;
|
|
MMOP_PROC:
|
|
CALL NEWLINE
|
|
CALL NEWLINE
|
|
|
|
LD A,FALSE
|
|
LD (DCD_ABORT),A
|
|
|
|
CALL DIO_INIT
|
|
|
|
LD A,(MMD_TGT)
|
|
CP MMT_DISK
|
|
JP Z,MMOP_PROCDISK
|
|
CP MMT_TRACK
|
|
JP Z,MMOP_PROCTRK
|
|
CP MMT_SECTOR
|
|
JP Z,MMOP_PROCSEC
|
|
CP MMT_RANDOM
|
|
JP Z,MMOP_PROCRND
|
|
|
|
JP MMOP_PROCX
|
|
|
|
MMOP_PROCDISK:
|
|
CALL MMOP_DISK
|
|
JP MMOP_PROCX
|
|
|
|
MMOP_PROCTRK:
|
|
CALL MMOP_TRACK
|
|
JP MMOP_PROCX
|
|
|
|
MMOP_PROCSEC:
|
|
CALL MMOP_SECTOR
|
|
JP MMOP_PROCX
|
|
|
|
MMOP_PROCRND:
|
|
CALL MMOP_RANDOM
|
|
JP MMOP_PROCX
|
|
|
|
MMOP_PROCX:
|
|
CALL DIO_TERM
|
|
RET
|
|
|
|
MMOP_DISK:
|
|
LD A,0
|
|
LD (DCD_TRACK),A
|
|
LD (DCD_HEAD),A
|
|
MMOP_DISK1:
|
|
LD A,(DCD_ABORT)
|
|
CP TRUE
|
|
JP Z,MMOP_DISKX
|
|
|
|
CALL MMOP_TRACK
|
|
|
|
LD A,(MDB_NUMHD)
|
|
LD C,A
|
|
LD A,(DCD_HEAD) ; INC HEAD
|
|
INC A
|
|
LD (DCD_HEAD),A
|
|
CP C ; # OF HEADS
|
|
JP NZ,MMOP_DISK1 ; LOOP IF LESS THAN # OF HEADS
|
|
LD A,0 ; RESET HEAD
|
|
LD (DCD_HEAD),A ; AND FALL THROUGH TO INC TRACK
|
|
|
|
LD A,(MDB_NUMCYL)
|
|
LD C,A
|
|
LD A,(DCD_TRACK) ; INC TRACK
|
|
INC A
|
|
LD (DCD_TRACK),A
|
|
CP C ; # OF TRACKS
|
|
JP NZ,MMOP_DISK1
|
|
MMOP_DISKX:
|
|
LD A,0 ; RESET TRACK TO A VALID VALUE
|
|
LD (DCD_TRACK),A
|
|
RET
|
|
|
|
MMOP_TRACK:
|
|
LD A,(DCD_DOP) ; SPECIAL CASE, FORMAT IS TRACK-AT-A-TIME
|
|
CP DOP_FORMAT
|
|
JP Z,MMOP_TRACKFMT
|
|
|
|
LD A,(MDB_SOT)
|
|
LD (DCD_SECTOR),A
|
|
MMOP_TRACK1:
|
|
LD A,(DCD_ABORT)
|
|
CP TRUE
|
|
JP Z,MMOP_TRACKX
|
|
|
|
CALL DIO_RUN
|
|
|
|
LD A,(MDB_EOT)
|
|
LD C,A
|
|
INC C ; ONE MORE THAN EOT
|
|
LD A,(DCD_SECTOR) ; INC SECTOR
|
|
INC A
|
|
LD (DCD_SECTOR),A
|
|
CP C ; > MAX SECTOR?
|
|
JP NZ,MMOP_TRACK1
|
|
JP MMOP_TRACKX
|
|
|
|
MMOP_TRACKFMT:
|
|
CALL DIO_RUN
|
|
JP MMOP_TRACKX
|
|
|
|
MMOP_TRACKX:
|
|
LD A,(MDB_SOT) ; RESET SECTOR TO A VALID VALUE
|
|
LD (DCD_SECTOR),A
|
|
RET
|
|
|
|
MMOP_SECTOR:
|
|
CALL DIO_RUN
|
|
RET
|
|
|
|
MMOP_RANDOM:
|
|
LD B,20H ; READ 20H SECTORS RANDOMLY
|
|
|
|
MMOP_RANDOM0:
|
|
LD A,(DCD_ABORT)
|
|
CP TRUE
|
|
JP Z,MMOP_RANDOMX
|
|
|
|
PUSH BC
|
|
|
|
MMOP_RANDOM1: ; GENERATE RANDOM TRACK
|
|
LD A,(MDB_NUMCYL)
|
|
LD C,A
|
|
CALL RNDBYTE
|
|
AND 7FH ; USE 7 BITS FOR UP TO 128 TRACKS
|
|
CP C ; MAX TRACK IS 4F + 1 = 50H
|
|
JP P,MMOP_RANDOM1
|
|
LD (DCD_TRACK),A
|
|
|
|
MMOP_RANDOM2: ; GENERATE RANDOM HEAD
|
|
;OR A
|
|
;CALL RNDBYTE
|
|
;AND 01H ; JUST USE LOW ORDER BIT
|
|
;LD (DCD_HEAD),A
|
|
LD A,(MDB_NUMHD)
|
|
LD C,A
|
|
CALL RNDBYTE
|
|
AND 01H ; USE 1 BIT FOR UP TO 2 HEADS
|
|
CP C
|
|
JP P,MMOP_RANDOM2
|
|
LD (DCD_HEAD),A
|
|
|
|
MMOP_RANDOM3: ; GENERATE RANDOM SECTOR
|
|
LD A,(MDB_EOT)
|
|
LD C,A
|
|
INC C ; ONE MORE THEN MAX SECTOR
|
|
CALL RNDBYTE
|
|
AND 1FH ; USE 5 BITS FOR UP TO 32 SECTORS
|
|
CP C ; MAX SECTOR NUM IS 9 + 1 = 0AH
|
|
JP P,MMOP_RANDOM3
|
|
CP 00H ; SECTOR NUM STARTS AT 1, DON'T ALLOW ZERO
|
|
JP Z,MMOP_RANDOM3
|
|
LD (DCD_SECTOR),A
|
|
|
|
CALL DIO_RUN
|
|
|
|
POP BC
|
|
DJNZ MMOP_RANDOM0
|
|
|
|
MMOP_RANDOMX:
|
|
RET
|
|
|
|
;
|
|
;===============================================================================
|
|
; DISK INPUT/OUTPUT SERVICES, DEVICE INDEPENDENT (LOGICAL) ACCESS TO STORAGE
|
|
; TRANSLATES BETWEEN LOGICAL AND PHYSICAL DEVICE OPERATIONS
|
|
;===============================================================================
|
|
;
|
|
;
|
|
STR_CONTINUE:
|
|
.TEXT "CONTINUE? (A)BORT, (R)ETRY, (I)GNORE ===> $"
|
|
;
|
|
DIO_SETMEDIA:
|
|
; INITIZLIZE THE MEDIA DESCRIPTION BLOCK
|
|
; FILL IN MDB BASED ON USER SELECTION
|
|
LD A,(DCD_MT) ; A = MEDIA ID (OFFSET IN MEDIA INDEX TABLE)
|
|
ADD A,A ; * 2 (2 BYTES PER ENTRY)
|
|
LD H,0 ; MOVE IT TO HL
|
|
LD L,A ; "
|
|
LD DE,MIT ; DE = START OF MEDIA INDEX TABLE
|
|
ADD HL,DE ; ADD HL TO DE, HL NOW POINTS TO DESIRED ENTRY
|
|
LD A,(HL) ; HL = ENTRY VALUE
|
|
INC HL ; "
|
|
LD H,(HL) ; "
|
|
LD L,A ; "
|
|
LD DE,MDB ; HL = SOURCE, DE = DESTINATION
|
|
LD BC,MDB_LEN ; BC = BYTES TO COPY
|
|
LDIR ; COPY ENTRY TO FCD
|
|
|
|
LD A,FALSE ; SET DRIVE READY TO FALSE!
|
|
LD (DCD_DSKRDY),A ; "
|
|
RET
|
|
;
|
|
DIO_INIT:
|
|
; UPDATE DRIVE SELECTTION
|
|
LD A,(FCD_DS) ; GET THE CURRENT DRIVE SELECTION
|
|
LD B,A ; SAVE IN B
|
|
LD A,(DCD_UNIT) ; GET THE NEW DRIVE SELECTION
|
|
CP B ; CHANGED?
|
|
; WE NEED TO SET DRIVE STATUS TO NOT READY IFF IT CHANGED
|
|
JP Z,DIO_INIT1 ; DO NOT RESET DRIVE STATUS!
|
|
LD (FCD_DS),A ; UPDATE FCD_DS TO NEW VALUE
|
|
LD A,FALSE ; SET DRIVE READY TO FALSE!
|
|
LD (DCD_DSKRDY),A ; "
|
|
|
|
DIO_INIT1:
|
|
; INITIALIZE TRACE SETTING
|
|
LD A,(DCD_TRACE)
|
|
LD (FCD_TRACE),A
|
|
|
|
LD HL,MDB_FCD ; HL = SOURCE
|
|
LD DE,FCD ; DE = DESTINATION
|
|
LD BC,FCD_LEN ; BC = BYTES TO COPY
|
|
LDIR ; BYTES COPY FROM MDB TO FCD
|
|
|
|
LD A,0 ; ASSUME DMA (NON-DMA = 0)
|
|
LD (FCD_ND),A
|
|
LD A,(DCD_MD)
|
|
CP MD_DRQWAIT
|
|
JP Z,DIO_INIT2 ; YES, DMA NEEDED, DO IT
|
|
|
|
LD A,1 ; SET TO NON-DMA (NDMA = 1)
|
|
LD (FCD_ND),A
|
|
|
|
DIO_INIT2:
|
|
CALL FC_INIT
|
|
CALL FC_MOTORON
|
|
RET
|
|
|
|
DIO_TERM:
|
|
CALL FC_MOTOROFF
|
|
RET
|
|
;
|
|
; DIO_CLRDSKCHG
|
|
;
|
|
DIO_CLRDSKCHG:
|
|
; PROCESS ANY PENDING DISK CHANGE NOTIFICATIONS
|
|
LD B,5
|
|
DIO_CLRDSKCHG1:
|
|
PUSH BC
|
|
CALL FC_SENSEINT
|
|
POP BC
|
|
CALL DIO_CHKFC
|
|
CP FRC_DSKCHG
|
|
RET NZ
|
|
DJNZ DIO_CLRDSKCHG1
|
|
RET
|
|
;
|
|
; DIO_WTSEEK
|
|
;
|
|
; WAIT FOR PENDING SEEK OPERATION TO COMPLETE BY POLLING SENSEINT
|
|
; AND WAITING FOR ABTERM OR OK.
|
|
;
|
|
DIO_WTSEEK:
|
|
LD BC,1000H
|
|
; LD BC,20H ; *DEBUG*
|
|
; LD BC,1H ; *DEBUG*
|
|
DIO_WTSEEKLOOP:
|
|
PUSH BC
|
|
CALL FC_SENSEINT
|
|
POP BC
|
|
|
|
LD A,(FST_RC) ; CHECK RC
|
|
CP FRC_ABTERM ; ABTERM = DONE
|
|
RET Z
|
|
CP FRC_OK ; OK = DONE
|
|
RET Z
|
|
|
|
DEC BC ; CHECK LOOP COUNTER IN BC
|
|
LD A,B ; "
|
|
OR C ; "
|
|
JP NZ,DIO_WTSEEKLOOP ; LOOP UNTIL COUNTER EXHAUSTED
|
|
|
|
DIO_DRIVERESET:
|
|
CALL NEWLINE
|
|
CALL NEWLINE
|
|
LD DE,STR_DRIVERESET
|
|
CALL WRITESTR
|
|
|
|
CALL FC_RESETFDC
|
|
|
|
CALL DIO_CLRDSKCHG
|
|
CALL DIO_CHKFC
|
|
CP FRC_INVCMD ; INVALID COMMAND IS CORRECT RESPONSE HERE
|
|
JP NZ,DIO_NORESP
|
|
|
|
; CONTINUE RESET SEQUENCE WITH 'SPECIFY' COMMAND
|
|
CALL FC_SPECIFY
|
|
CALL DIO_CHKFC
|
|
JP NZ,DIO_NORESP
|
|
|
|
CALL FC_RECAL
|
|
CALL DIO_CHKFC
|
|
JP NZ,DIO_NORESP
|
|
|
|
; CAREFUL... FIRST RECAL MAY FAIL TO REACH TRACK 0
|
|
; SO WE ALLOW FOR A SECOND TRY IN CASE OF A FAILURE
|
|
CALL DIO_WTSEEK
|
|
CALL DIO_CHKFC
|
|
JP Z,DIO_DRIVERESET1
|
|
|
|
; SECOND TRY, ONLY IF NEEDED
|
|
CALL FC_RECAL
|
|
CALL DIO_CHKFC
|
|
JP NZ,DIO_NORESP
|
|
|
|
CALL DIO_WTSEEK
|
|
CALL DIO_CHKFC
|
|
JP NZ,DIO_NORESP
|
|
JP DIO_DRIVERESET1
|
|
|
|
DIO_NORESP:
|
|
CALL NEWLINE
|
|
LD DE,STR_NORESP
|
|
CALL WRITESTR
|
|
RET
|
|
|
|
DIO_DRIVERESET1:
|
|
LD A,TRUE
|
|
LD (DCD_DSKRDY),A
|
|
|
|
LD A,0
|
|
LD (DCD_CURTRK),A
|
|
|
|
RET
|
|
|
|
DIO_CHKFC:
|
|
LD A,(FST_RC)
|
|
OR A
|
|
RET
|
|
|
|
DIO_RUN:
|
|
LD A,(DCD_DSKRDY)
|
|
CP TRUE
|
|
JP Z,DIO_RUN0
|
|
|
|
CALL DIO_DRIVERESET
|
|
LD A,(DCD_DSKRDY)
|
|
CP TRUE
|
|
JP NZ,DIO_RUNERR ; DRIVERESET FAILED!
|
|
|
|
DIO_RUN0:
|
|
CALL DIO_PROGRESS
|
|
|
|
; COPY PARMS OVER
|
|
LD A,(DCD_UNIT)
|
|
LD (FCD_DS),A
|
|
|
|
LD A,(DCD_TRACE)
|
|
LD (FCD_TRACE),A
|
|
|
|
LD A,(DCD_TRACK)
|
|
LD (FCD_C),A
|
|
|
|
LD A,(DCD_HEAD)
|
|
LD (FCD_H),A
|
|
|
|
LD A,(DCD_SECTOR)
|
|
LD (FCD_R),A
|
|
|
|
LD A,(DCD_INTRLV)
|
|
LD (FCD_X),A
|
|
|
|
; FIX: COMBINE WITH DCD_TRACK SETUP ABOVE?
|
|
LD A,(DCD_CURTRK)
|
|
LD B,A
|
|
LD A,(DCD_TRACK)
|
|
CP B
|
|
JP Z,DIO_RUN1 ; SKIP SEEK IF POSSIBLE
|
|
|
|
; SEEK AND WAIT FOR COMPLETE
|
|
CALL FC_SEEK
|
|
CALL DIO_CHKFC
|
|
JP NZ,DIO_RUNERR
|
|
|
|
CALL DIO_WTSEEK
|
|
CALL DIO_CHKFC
|
|
JP NZ,DIO_RUNERR
|
|
|
|
; RECORD CURRENT TRACK
|
|
; FIX: SHOULD NOT ASSUME SEEK REQUEST SUCCEEDED (FC_READID?)
|
|
LD A,(DCD_TRACK)
|
|
LD (DCD_CURTRK),A
|
|
|
|
DIO_RUN1:
|
|
LD A,(DCD_DOP)
|
|
|
|
CP DOP_READ
|
|
JP Z,DIO_RUNREAD
|
|
|
|
CP DOP_WRITE
|
|
JP Z,DIO_RUNWRITE
|
|
|
|
CP DOP_FORMAT
|
|
JP Z,DIO_RUNFORMAT
|
|
|
|
CP DOP_VERIFY
|
|
JP Z,DIO_RUNVERIFY
|
|
|
|
JP DIO_RUNX
|
|
|
|
DIO_RUNREAD:
|
|
CALL FC_READ
|
|
JP DIO_RUNCHK
|
|
|
|
DIO_RUNWRITE:
|
|
CALL FC_WRITE
|
|
JP DIO_RUNCHK
|
|
|
|
DIO_RUNFORMAT:
|
|
CALL FC_FMTTRK
|
|
JP DIO_RUNCHK
|
|
|
|
DIO_RUNVERIFY:
|
|
CALL FC_READ
|
|
JP DIO_RUNCHK
|
|
|
|
DIO_RUNCHK:
|
|
LD A,(FST_RC)
|
|
OR A
|
|
CP FRC_OK
|
|
JP NZ,DIO_RUNERR ; HANDLE I/O ERROR
|
|
LD A,(DCD_DOP)
|
|
CP DOP_VERIFY
|
|
JP NZ,DIO_RUNX ; NOT VERIFY, ALL DONE
|
|
CALL DIO_VERIFY
|
|
LD A,(FST_RC)
|
|
OR A
|
|
CP FRC_OK
|
|
JP NZ,DIO_RUNERR ; HANDLE VERIFY ERROR
|
|
JP DIO_RUNX
|
|
|
|
DIO_RUNERR:
|
|
LD A,FALSE
|
|
LD (DCD_DSKRDY),A
|
|
CALL FC_RESETFDC ; FIX...
|
|
CALL NEWLINE
|
|
LD DE,STR_CONTINUE ; ABORT/RETRY/IGNORE PROMPT
|
|
CALL WRITESTR
|
|
|
|
DIO_RUNERR1:
|
|
CALL GETKEYUC
|
|
|
|
CP 'A'
|
|
JP Z,DIO_ABORT
|
|
CP 'R'
|
|
JP Z,DIO_RETRY
|
|
CP 'I'
|
|
JP Z,DIO_IGNORE
|
|
|
|
JP DIO_RUNERR1
|
|
|
|
DIO_ABORT:
|
|
LD DE,DIOCS_ABORT
|
|
CALL WRITESTR
|
|
LD A,TRUE
|
|
LD (DCD_ABORT),A
|
|
JP DIO_RUNX
|
|
|
|
DIO_RETRY:
|
|
LD DE,DIOCS_RETRY
|
|
CALL WRITESTR
|
|
JP DIO_RUN
|
|
|
|
DIO_IGNORE:
|
|
LD DE,DIOCS_IGNORE
|
|
CALL WRITESTR
|
|
JP DIO_RUNX
|
|
|
|
DIO_RUNX:
|
|
RET
|
|
|
|
DIO_PROGRESS:
|
|
LD A,(NEWLINE_USED)
|
|
OR A
|
|
JP Z,DIO_PROGRESS1
|
|
CALL NEWLINE
|
|
LD A,0
|
|
LD (NEWLINE_USED),A
|
|
|
|
DIO_PROGRESS1:
|
|
CALL PC_CR
|
|
LD DE,STR_PROGRESS
|
|
CALL WRITESTR
|
|
CALL PC_COLON
|
|
CALL PC_SPACE
|
|
LD DE,DPL_TRACK
|
|
CALL WRITESTR
|
|
CALL PC_EQUAL
|
|
LD A,(DCD_TRACK)
|
|
CALL PRTHEXBYTE
|
|
CALL PC_SPACE
|
|
LD DE,DPL_HEAD
|
|
CALL WRITESTR
|
|
CALL PC_EQUAL
|
|
LD A,(DCD_HEAD)
|
|
CALL PRTHEXBYTE
|
|
CALL PC_SPACE
|
|
LD DE,DPL_SECTOR
|
|
CALL WRITESTR
|
|
CALL PC_EQUAL
|
|
LD A,(DCD_SECTOR)
|
|
CALL PRTHEXBYTE
|
|
|
|
RET
|
|
|
|
DIO_VERIFY:
|
|
LD HL,BUFFER
|
|
LD DE,VFYBUF
|
|
LD BC,BUFSIZ
|
|
|
|
DIO_VERIFY1:
|
|
LD A,(DE)
|
|
CP (HL)
|
|
JP NZ,DIO_VERIFY2
|
|
INC DE
|
|
INC HL
|
|
DEC BC
|
|
LD A,B
|
|
OR C
|
|
JP NZ,DIO_VERIFY1
|
|
RET
|
|
|
|
DIO_VERIFY2:
|
|
PUSH DE
|
|
|
|
CALL NEWLINE
|
|
LD DE,STR_MISMATCH
|
|
CALL WRITESTR
|
|
POP DE
|
|
LD A,D
|
|
SUB VFYBUF >> 8
|
|
CALL PRTHEXBYTE
|
|
LD A,E
|
|
CALL PRTHEXBYTE
|
|
LD A,FRC_MISMATCH
|
|
LD (FST_RC),A
|
|
RET
|
|
;
|
|
; CONTINUE PROMPT OPTION STRINGS
|
|
;
|
|
DIOCS_ABORT .TEXT "ABORT$"
|
|
DIOCS_RETRY .TEXT "RETRY$"
|
|
DIOCS_IGNORE .TEXT "IGNORE$"
|
|
;
|
|
; DISK PROGRESS LABELS
|
|
;
|
|
DPL_TRACK .TEXT "TRACK$"
|
|
DPL_HEAD .TEXT "HEAD$"
|
|
DPL_SECTOR .TEXT "SECTOR$"
|
|
;
|
|
; DISK OPERATIONS
|
|
;
|
|
DOP_READ .EQU 0 ; READ OPERATION
|
|
DOP_WRITE .EQU 1 ; WRITE OPERATION
|
|
DOP_FORMAT .EQU 2 ; FORMAT OPERATION
|
|
DOP_VERIFY .EQU 3 ; VERIFY OPERATION
|
|
;
|
|
; DEVICE CONTROL DATA
|
|
;
|
|
DCD_FILL .DB 0E5H ; DEFAULT TO E5 (EMPTY DIRECTORY BYTE)
|
|
DCD_PATTERN .DB 000H ; DEFAULT TO 00
|
|
DCD_TRACE .DB 000H ; TRACE LEVEL
|
|
DCD_UNIT .DB 000H ; DEFAULT UNIT = 0
|
|
DCD_SECTOR .DB 001H ; DEFAULT SECTOR = 1
|
|
DCD_HEAD .DB 000H ; DEFAULT HEAD = 0
|
|
DCD_TRACK .DB 000H ; DEFAULT TRACK = 0
|
|
DCD_INTRLV .DB 002H ; DEFAULT INTERLEAVE = 2
|
|
DCD_DOP .DB DOP_READ ; DEFAULT OP = READ
|
|
DCD_MT .DB MT_PC720 ; DEFAULT FLOPPY DEVICE = PC720
|
|
DCD_MD .DB MD_POLL ; DEFAULT MODE = POLL
|
|
;
|
|
; DEVICE CONTROL DATA (PRIVATE)
|
|
;
|
|
DCD_DSKRDY .DB FALSE ; 0 = NOT RDY, 1 = RDY
|
|
DCD_ABORT .DB FALSE ; 0 = CONT, 1 = ABORT
|
|
DCD_CURTRK .DB 0FFH ; CURRENT TRACK, FF = UNKNOWN
|
|
;
|
|
; MODES
|
|
;
|
|
MD_POLL .EQU 0
|
|
MD_INT .EQU 1
|
|
MD_INTFAST .EQU 2
|
|
MD_INTWAIT .EQU 3
|
|
MD_DRQWAIT .EQU 4
|
|
;
|
|
; MODE MAPPING
|
|
; BIT IS SET FOR ALLOWED MODES PER FDC
|
|
;
|
|
MD_MAP:
|
|
.DB %00011111 ; DIO POLL,INT,INTFAST,INTWAIT,DRQWAIT
|
|
.DB %00000111 ; DIO3 POLL,INT,INTFAST
|
|
.DB %00000111 ; ZETA POLL,INT,INTFAST
|
|
.DB %00000001 ; ZETA2 POLL
|
|
.DB %00000001 ; DIDE POLL
|
|
.DB %00000001 ; N8 POLL
|
|
.DB %00000001 ; RCSMC POLL
|
|
.DB %00000001 ; RCWDC POLL
|
|
.DB %00000001 ; SMZ80 POLL
|
|
.DB %00000001 ; DYNO POLL
|
|
.DB %00000001 ; EPFDC POLL
|
|
.DB %00000001 ; MBC POLL
|
|
;
|
|
; MEDIA DESCRIPTION BLOCK
|
|
;
|
|
MDB:
|
|
MDB_LABEL .DW 000H ; ADDRESS OF MEDIA LABEL
|
|
MDB_DESC .DW 000H ; ADDRESS OF MEDIA DESCRIPTION
|
|
MDB_NUMCYL .DB 000H ; NUMBER OF CYLINDERS
|
|
MDB_NUMHD .DB 000H ; NUMBER OF HEADS
|
|
MDB_NUMSEC .DB 000H ; NUMBER OF SECTORS
|
|
MDB_SOT .DB 000H ; START OF TRACK (ID OF FIRST SECTOR, USUALLY 1)
|
|
MDB_FCD: ; FLOPPY CONFIGURATION DATA (PUBLIC) MANAGED AS A "BLOCK", MUST MATCH FCB BELOW
|
|
MDB_EOT ; END OF TRACK SECTOR (SAME AS SC SINCE SOT ALWAYS 1)
|
|
MDB_SC .DB 000H ; SECTOR COUNT
|
|
MDB_SECSZ .DW 000H ; SECTOR SIZE IN BYTES
|
|
MDB_GPL .DB 000H ; GAP LENGTH (R/W)
|
|
MDB_GPLF .DB 000H ; GAP LENGTH (FORMAT)
|
|
MDB_SRTHUT .DB 000H ; STEP RATE, IBM PS/2 CALLS FOR 3ms, 0DH = 3ms SRT, HEAD UNLOAD TIME
|
|
MDB_HLT .DB 000H ; HEAD LOAD TIME, IBM PS/2 CALLS FOR 15ms 08H = 16ms HUT
|
|
MDB_DORA .DB 000H ; OPERATIONS REGISTER VALUE FOR MEDIA
|
|
MDB_DORB .DB 000H ; OPERATIONS REGISTER VALUE FOR MEDIA
|
|
MDB_DORC .DB 000H ; OPERATIONS REGISTER VALUE FOR MEDIA
|
|
MDB_DORD .DB 000H ; OPERATIONS REGISTER VALUE FOR MEDIA
|
|
MDB_DCR .DB 000H ; CONTROL REGISTER VALUE FOR MEDIA
|
|
MDB_LEN .EQU $ - MDB
|
|
;
|
|
MDT: ; MODE TABLE
|
|
.DW MTB_POLL
|
|
.DW MTB_INT
|
|
.DW MTB_INTFAST
|
|
.DW MTB_INTWAIT
|
|
.DW MTB_DRQWAIT
|
|
MDT_ENTCNT .EQU (($ - MDT) / 2)
|
|
;
|
|
MTB_POLL .DW MTL_POLL ; ADDRESS OF MODE LABEL
|
|
.DW MTS_POLL ; ADDRESS OF MODE DESCRIPTION
|
|
MTL_POLL .TEXT "POLL $"
|
|
MTS_POLL .TEXT "POLLING (RECOMMENDED)$"
|
|
;
|
|
MTB_INT .DW MTL_INT ; ADDRESS OF MODE LABEL
|
|
.DW MTS_INT ; ADDRESS OF MODE DESCRIPTION
|
|
MTL_INT .TEXT "INT $"
|
|
MTS_INT .TEXT "INTERRUPT (!!! READ MANUAL !!!)$"
|
|
;
|
|
MTB_INTFAST .DW MTL_INTFAST ; ADDRESS OF MODE LABEL
|
|
.DW MTS_INTFAST ; ADDRESS OF MODE DESCRIPTION
|
|
MTL_INTFAST .TEXT "INT-FAST $"
|
|
MTS_INTFAST .TEXT "FAST INTERRUPT (!!! READ MANUAL !!!)$"
|
|
;
|
|
MTB_INTWAIT .DW MTL_INTWAIT ; ADDRESS OF MODE LABEL
|
|
.DW MTS_INTWAIT ; ADDRESS OF MODE DESCRIPTION
|
|
MTL_INTWAIT .TEXT "INT/WAIT $"
|
|
MTS_INTWAIT .TEXT "INT/WAIT (!!! READ MANUAL !!!)$"
|
|
;
|
|
MTB_DRQWAIT .DW MTL_DRQWAIT ; ADDRESS OF MODE LABEL
|
|
.DW MTS_DRQWAIT ; ADDRESS OF MODE DESCRIPTION
|
|
MTL_DRQWAIT .TEXT "DRQ/WAIT $"
|
|
MTS_DRQWAIT .TEXT "DRQ/WAIT (!!! NOT YET IMPLEMENTED!!!)$"
|
|
;
|
|
; MEDIA TYPE INFORMATION
|
|
;
|
|
MT_PC720 .EQU 0
|
|
MT_PC144 .EQU 1
|
|
MT_PC320 .EQU 2
|
|
MT_PC360 .EQU 3
|
|
MT_PC120 .EQU 4
|
|
MT_PC111 .EQU 5
|
|
MT_PC160 .EQU 6
|
|
MT_PC180 .EQU 7
|
|
MT_PC320SS .EQU 8
|
|
MT_PC360SS .EQU 9
|
|
;
|
|
MIT: ; MEDIA INDEX TABLE
|
|
.DW MDB_PC720
|
|
.DW MDB_PC144
|
|
.DW MDB_PC320
|
|
.DW MDB_PC360
|
|
.DW MDB_PC120
|
|
.DW MDB_PC111
|
|
.DW MDB_PC160
|
|
.DW MDB_PC180
|
|
.DW MDB_PC320SS
|
|
.DW MDB_PC360SS
|
|
MIT_ENTCNT .EQU (($ - MIT) / 2)
|
|
;
|
|
; Specify Command:
|
|
; +-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
|
; |Byte | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
|
; +-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
|
; | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
|
|
; | 1 | ----- STEP RATE ----- | -- HEAD UNLOAD TIME - |
|
|
; | 2 | ------------ HEAD LOAD TIME ----------- | NDM |
|
|
; +-----+-----+-----+-----+-----+-----+-----+-----+-----+
|
|
;
|
|
;
|
|
; Step Rate (milliseconds): Head Unload Time (milliseconds): Head Load Time (milliseconds):
|
|
; +------+------+------+------+------+ +------+------+------+------+------+ +------+------+------+------+------+
|
|
; | | BITRATE | | | BITRATE | | | BITRATE |
|
|
; | VAL | 1.0M | 500K | 300K | 250K | | VAL | 1.0M | 500K | 300K | 250K | | VAL | 1.0M | 500K | 300K | 250K |
|
|
; +------+------+------+------+------+ +------+------+------+------+------+ +------+------+------+------+------+
|
|
; | 0 | 8.0 | 16.0 | 26.7 | 32.0 | | 0 | 128 | 256 | 426 | 512 | | 0 | 128 | 256 | 426 | 512 |
|
|
; | 1 | 7.5 | 15.0 | 25.0 | 30.0 | | 1 | 8 | 16 | 26.7 | 32 | | 1 | 1 | 2 | 3.3 | 4 |
|
|
; | 2 | 7.0 | 14.0 | 23.3 | 28.0 | | 2 | 16 | 32 | 53.3 | 64 | | 2 | 2 | 4 | 6.7 | 8 |
|
|
; | ... | ... | ... | ... | ... | | ... | ... | ... | ... | ... | | ... | ... | ... | ... | ... |
|
|
; | 14 | 1.0 | 2.0 | 3.3 | 4.0 | | 14 | 112 | 224 | 373 | 448 | | 126 | 126 | 252 | 420 | 504 |
|
|
; | 15 | 0.5 | 1.0 | 1.7 | 2.0 | | 15 | 120 | 240 | 400 | 480 | | 127 | 127 | 254 | 423 | 508 |
|
|
; +------+------+------+------+------+ +------+------+------+------+------+ +------+------+------+------+------+
|
|
;
|
|
; IBM PS/2 CALLS FOR:
|
|
; STEP RATE: 3ms (6ms FOR ALL 41mm OR 720K DRIVES)
|
|
; HEAD LOAD TIME: 15ms
|
|
;
|
|
; STATIC CONFIGURATION, NEVER CHANGES (PRIVATE)
|
|
;
|
|
MDB_PC720 .DW DTL_PC720 ; ADDRESS OF MEDIA LABEL
|
|
.DW DTS_PC720 ; ADDRESS OF MEDIA DESCRIPTION
|
|
.DB 050H ; NUMBER OF CYLINDERS
|
|
.DB 002H ; NUMBER OF HEADS
|
|
.DB 009H ; NUMBER OF SECTORS
|
|
.DB 001H ; START OF TRACK (ID OF FIRST SECTOR, USUALLY 1)
|
|
FCB_PC720 .DB 009H ; SECTOR COUNT
|
|
.DW 200H ; SECTOR SIZE IN BYTES
|
|
.DB 02AH ; GAP LENGTH (R/W)
|
|
.DB 050H ; GAP LENGTH (FORMAT)
|
|
.DB (13 << 4) | 0 ; SRT = 6ms, HUT = 512ms
|
|
.DB 4 ; HLT = 16ms
|
|
.DB DORA_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DORB_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DORC_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DORD_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DCR_BR250 ; CONTROL REGISTER VALUE
|
|
.IF (($ - MDB_PC720) != MDB_LEN)
|
|
.ECHO "*** FCB SIZE ERROR!!! ***\n"
|
|
.ENDIF
|
|
DTL_PC720 .TEXT "720KB DS/DD $"
|
|
DTS_PC720 .TEXT "3.5\" 720KB - 9 SECTORS, 2 SIDES, 80 TRACKS, DOUBLE DENSITY$"
|
|
;
|
|
MDB_PC144 .DW DTL_PC144 ; ADDRESS OF MEDIA LABEL
|
|
.DW DTS_PC144 ; ADDRESS OF MEDIA DESCRIPTION
|
|
.DB 050H ; NUMBER OF CYLINDERS
|
|
.DB 002H ; NUMBER OF HEADS
|
|
.DB 012H ; NUMBER OF SECTORS
|
|
.DB 001H ; START OF TRACK (ID OF FIRST SECTOR, USUALLY 1)
|
|
FCB_PC144 .DB 012H ; SECTOR COUNT
|
|
.DW 200H ; SECTOR SIZE IN BYTES
|
|
.DB 01BH ; GAP LENGTH (R/W)
|
|
.DB 06CH ; GAP LENGTH (FORMAT)
|
|
.DB (13 << 4) | 0 ; SRT = 3ms, HUT = 256ms
|
|
.DB 8 ; HLT = 16ms
|
|
.DB DORA_BR500 ; OPERATIONS REGISTER VALUE
|
|
.DB DORB_BR500 ; OPERATIONS REGISTER VALUE
|
|
.DB DORC_BR500 ; OPERATIONS REGISTER VALUE
|
|
.DB DORD_BR500 ; OPERATIONS REGISTER VALUE
|
|
.DB DCR_BR500 ; CONTROL REGISTER VALUE
|
|
.IF (($ - MDB_PC144) != MDB_LEN)
|
|
.ECHO "*** FCB SIZE ERROR!!! ***\n"
|
|
.ENDIF
|
|
DTL_PC144 .TEXT "1.44MB DS/HD $"
|
|
DTS_PC144 .TEXT "3.5\" 1.44MB - 18 SECTORS, 2 SIDES, 80 TRACKS, HIGH DENSITY$"
|
|
;
|
|
MDB_PC320 .DW DTL_PC320 ; ADDRESS OF MEDIA LABEL
|
|
.DW DTS_PC320 ; ADDRESS OF MEDIA DESCRIPTION
|
|
.DB 028H ; NUMBER OF CYLINDERS
|
|
.DB 002H ; NUMBER OF HEADS
|
|
.DB 008H ; NUMBER OF SECTORS
|
|
.DB 001H ; START OF TRACK (ID OF FIRST SECTOR, USUALLY 1)
|
|
FCB_PC320 .DB 008H ; SECTOR COUNT
|
|
.DW 200H ; SECTOR SIZE IN BYTES
|
|
.DB 02AH ; GAP LENGTH (R/W)
|
|
.DB 050H ; GAP LENGTH (FORMAT)
|
|
.DB (13 << 4) | 0 ; SRT = 6ms, HUT = 512ms
|
|
.DB 4 ; HLT = 16ms
|
|
.DB DORA_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DORB_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DORC_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DORD_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DCR_BR250 ; CONTROL REGISTER VALUE
|
|
.IF (($ - MDB_PC320) != MDB_LEN)
|
|
.ECHO "*** FCB SIZE ERROR!!! ***\n"
|
|
.ENDIF
|
|
DTL_PC320 .TEXT "320KB DS/DD $"
|
|
DTS_PC320 .TEXT "5.25\" 320KB - 8 SECTORS, 2 SIDES, 40 TRACKS, DOUBLE DENSITY$"
|
|
;
|
|
MDB_PC360 .DW DTL_PC360 ; ADDRESS OF MEDIA LABEL
|
|
.DW DTS_PC360 ; ADDRESS OF MEDIA DESCRIPTION
|
|
.DB 028H ; NUMBER OF CYLINDERS
|
|
.DB 002H ; NUMBER OF HEADS
|
|
.DB 009H ; NUMBER OF SECTORS
|
|
.DB 001H ; START OF TRACK (ID OF FIRST SECTOR, USUALLY 1)
|
|
FCB_PC360 .DB 009H ; SECTOR COUNT
|
|
.DW 200H ; SECTOR SIZE IN BYTES
|
|
.DB 02AH ; GAP LENGTH (R/W)
|
|
.DB 050H ; GAP LENGTH (FORMAT)
|
|
.DB (13 << 4) | 0 ; SRT = 6ms, HUT = 512ms
|
|
.DB 4 ; HLT = 16ms
|
|
.DB DORA_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DORB_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DORC_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DORD_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DCR_BR250 ; CONTROL REGISTER VALUE
|
|
.IF (($ - MDB_PC360) != MDB_LEN)
|
|
.ECHO "*** FCB SIZE ERROR!!! ***\n"
|
|
.ENDIF
|
|
DTL_PC360 .TEXT "360KB DS/DD $"
|
|
DTS_PC360 .TEXT "5.25\" 360KB - 9 SECTORS, 2 SIDES, 40 TRACKS, DOUBLE DENSITY$"
|
|
;
|
|
MDB_PC120 .DW DTL_PC120 ; ADDRESS OF MEDIA LABEL
|
|
.DW DTS_PC120 ; ADDRESS OF MEDIA DESCRIPTION
|
|
.DB 050H ; NUMBER OF CYLINDERS
|
|
.DB 002H ; NUMBER OF HEADS
|
|
.DB 00FH ; NUMBER OF SECTORS
|
|
.DB 001H ; START OF TRACK (ID OF FIRST SECTOR, USUALLY 1)
|
|
FCB_PC120 .DB 00FH ; SECTOR COUNT
|
|
.DW 200H ; SECTOR SIZE IN BYTES
|
|
.DB 01BH ; GAP LENGTH (R/W)
|
|
.DB 054H ; GAP LENGTH (FORMAT)
|
|
.DB (10 << 4) | 0 ; SRT = 6ms, HUT = 256ms
|
|
.DB 8 ; HLT = 16ms
|
|
.DB DORA_BR500 ; OPERATIONS REGISTER VALUE
|
|
.DB DORB_BR500 ; OPERATIONS REGISTER VALUE
|
|
.DB DORC_BR500 ; OPERATIONS REGISTER VALUE
|
|
.DB DORD_BR500 ; OPERATIONS REGISTER VALUE
|
|
.DB DCR_BR500 ; CONTROL REGISTER VALUE
|
|
.IF (($ - MDB_PC120) != MDB_LEN)
|
|
.ECHO "*** FCB SIZE ERROR!!! ***\n"
|
|
.ENDIF
|
|
DTL_PC120 .TEXT "1.2MB DS/HD $"
|
|
DTS_PC120 .TEXT "5.25\" 1.2MB - 15 SECTORS, 2 SIDES, 80 TRACKS, HIGH DENSITY$"
|
|
;
|
|
MDB_PC111 .DW DTL_PC111 ; ADDRESS OF MEDIA LABEL
|
|
.DW DTS_PC111 ; ADDRESS OF MEDIA DESCRIPTION
|
|
.DB 04DH ; NUMBER OF CYLINDERS
|
|
.DB 002H ; NUMBER OF HEADS
|
|
.DB 00FH ; NUMBER OF SECTORS
|
|
.DB 001H ; START OF TRACK (ID OF FIRST SECTOR, USUALLY 1)
|
|
FCB_PC111 .DB 00FH ; SECTOR COUNT
|
|
.DW 200H ; SECTOR SIZE IN BYTES
|
|
.DB 01BH ; GAP LENGTH (R/W)
|
|
.DB 054H ; GAP LENGTH (FORMAT)
|
|
.DB (13 << 4) | 0 ; SRT = 3ms, HUT = 256ms
|
|
.DB 25 ; HLT = 50ms
|
|
.DB DORA_BR500 ; OPERATIONS REGISTER VALUE
|
|
.DB DORB_BR500 ; OPERATIONS REGISTER VALUE
|
|
.DB DORC_BR500 ; OPERATIONS REGISTER VALUE
|
|
.DB DORD_BR500 ; OPERATIONS REGISTER VALUE
|
|
.DB DCR_BR500 ; CONTROL REGISTER VALUE
|
|
.IF (($ - MDB_PC111) != MDB_LEN)
|
|
.ECHO "*** FCB SIZE ERROR!!! ***\n"
|
|
.ENDIF
|
|
DTL_PC111 .TEXT "1.11MB DS/DD $"
|
|
DTS_PC111 .TEXT "8\" 1.11MB - 15 SECTORS, 2 SIDES, 77 TRACKS, DOUBLE DENSITY$"
|
|
;
|
|
MDB_PC160 .DW DTL_PC160 ; ADDRESS OF MEDIA LABEL
|
|
.DW DTS_PC160 ; ADDRESS OF MEDIA DESCRIPTION
|
|
.DB 028H ; NUMBER OF CYLINDERS
|
|
.DB 001H ; NUMBER OF HEADS
|
|
.DB 008H ; NUMBER OF SECTORS
|
|
.DB 001H ; START OF TRACK (ID OF FIRST SECTOR, USUALLY 1)
|
|
FCB_PC160 .DB 008H ; SECTOR COUNT
|
|
.DW 200H ; SECTOR SIZE IN BYTES
|
|
.DB 02AH ; GAP LENGTH (R/W)
|
|
.DB 050H ; GAP LENGTH (FORMAT)
|
|
.DB (13 << 4) | 0 ; SRT = 6ms, HUT = 512ms
|
|
.DB 4 ; HLT = 16ms
|
|
.DB DORA_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DORB_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DORC_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DORD_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DCR_BR250 ; CONTROL REGISTER VALUE
|
|
.IF (($ - MDB_PC160) != MDB_LEN)
|
|
.ECHO "*** FCB SIZE ERROR!!! ***\n"
|
|
.ENDIF
|
|
DTL_PC160 .TEXT "160KB SS/DD $"
|
|
DTS_PC160 .TEXT "5.25\" 160KB - 8 SECTORS, 1 SIDE, 40 TRACKS, DOUBLE DENSITY$"
|
|
;
|
|
MDB_PC180 .DW DTL_PC180 ; ADDRESS OF MEDIA LABEL
|
|
.DW DTS_PC180 ; ADDRESS OF MEDIA DESCRIPTION
|
|
.DB 028H ; NUMBER OF CYLINDERS
|
|
.DB 001H ; NUMBER OF HEADS
|
|
.DB 009H ; NUMBER OF SECTORS
|
|
.DB 001H ; START OF TRACK (ID OF FIRST SECTOR, USUALLY 1)
|
|
FCB_PC180 .DB 009H ; SECTOR COUNT
|
|
.DW 200H ; SECTOR SIZE IN BYTES
|
|
.DB 02AH ; GAP LENGTH (R/W)
|
|
.DB 050H ; GAP LENGTH (FORMAT)
|
|
.DB (13 << 4) | 0 ; SRT = 6ms, HUT = 512ms
|
|
.DB 4 ; HLT = 16ms
|
|
.DB DORA_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DORB_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DORC_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DORD_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DCR_BR250 ; CONTROL REGISTER VALUE
|
|
.IF (($ - MDB_PC180) != MDB_LEN)
|
|
.ECHO "*** FCB SIZE ERROR!!! ***\n"
|
|
.ENDIF
|
|
DTL_PC180 .TEXT "180KB SS/DD $"
|
|
DTS_PC180 .TEXT "5.25\" 180KB - 9 SECTORS, 1 SIDE, 40 TRACKS, DOUBLE DENSITY$"
|
|
;
|
|
MDB_PC320SS .DW DTL_PC320SS ; ADDRESS OF MEDIA LABEL
|
|
.DW DTS_PC320SS ; ADDRESS OF MEDIA DESCRIPTION
|
|
.DB 050H ; NUMBER OF CYLINDERS
|
|
.DB 001H ; NUMBER OF HEADS
|
|
.DB 008H ; NUMBER OF SECTORS
|
|
.DB 001H ; START OF TRACK (ID OF FIRST SECTOR, USUALLY 1)
|
|
FCB_PC320SS .DB 008H ; SECTOR COUNT
|
|
.DW 200H ; SECTOR SIZE IN BYTES
|
|
.DB 02AH ; GAP LENGTH (R/W)
|
|
.DB 050H ; GAP LENGTH (FORMAT)
|
|
.DB (13 << 4) | 0 ; SRT = 6ms, HUT = 512ms
|
|
.DB 4 ; HLT = 16ms
|
|
.DB DORA_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DORB_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DORC_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DORD_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DCR_BR250 ; CONTROL REGISTER VALUE
|
|
.IF (($ - MDB_PC320SS) != MDB_LEN)
|
|
.ECHO "*** FCB SIZE ERROR!!! ***\n"
|
|
.ENDIF
|
|
DTL_PC320SS .TEXT "320KB SS/DD $"
|
|
DTS_PC320SS .TEXT "5.25\" 320KB - 8 SECTORS, 1 SIDE, 80 TRACKS, DOUBLE DENSITY$"
|
|
;
|
|
MDB_PC360SS .DW DTL_PC360SS ; ADDRESS OF MEDIA LABEL
|
|
.DW DTS_PC360SS ; ADDRESS OF MEDIA DESCRIPTION
|
|
.DB 050H ; NUMBER OF CYLINDERS
|
|
.DB 001H ; NUMBER OF HEADS
|
|
.DB 009H ; NUMBER OF SECTORS
|
|
.DB 001H ; START OF TRACK (ID OF FIRST SECTOR, USUALLY 1)
|
|
FCB_PC360SS .DB 009H ; SECTOR COUNT
|
|
.DW 200H ; SECTOR SIZE IN BYTES
|
|
.DB 02AH ; GAP LENGTH (R/W)
|
|
.DB 050H ; GAP LENGTH (FORMAT)
|
|
.DB (13 << 4) | 0 ; SRT = 6ms, HUT = 512ms
|
|
.DB 4 ; HLT = 16ms
|
|
.DB DORA_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DORB_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DORC_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DORD_BR250 ; OPERATIONS REGISTER VALUE
|
|
.DB DCR_BR250 ; CONTROL REGISTER VALUE
|
|
.IF (($ - MDB_PC360SS) != MDB_LEN)
|
|
.ECHO "*** FCB SIZE ERROR!!! ***\n"
|
|
.ENDIF
|
|
DTL_PC360SS .TEXT "360KB SS/DD $"
|
|
DTS_PC360SS .TEXT "5.25\" 360KB - 9 SECTORS, 1 SIDE, 80 TRACKS, DOUBLE DENSITY$"
|
|
;
|
|
;===============================================================================
|
|
; FLOPPY DISK CONTROL MENU (DIRECT MENU INTERFACE TO FDC & RELATED HARDWARE)
|
|
;===============================================================================
|
|
;
|
|
; FDC MENU DATA
|
|
;
|
|
FM_TABLE .DB 'R' \ .DW FMS_READ, FM_READ
|
|
FM_ENTSIZ .EQU $ - FM_TABLE
|
|
.DB 'D' \ .DW FMS_READDEL, FM_READDEL
|
|
.DB 'W' \ .DW FMS_WRITE, FM_WRITE
|
|
.DB 'E' \ .DW FMS_WRITEDEL, FM_WRITEDEL
|
|
.DB 'T' \ .DW FMS_READTRK, FM_READTRK
|
|
.DB 'I' \ .DW FMS_READID, FM_READID
|
|
.DB 'F' \ .DW FMS_FMTTRK, FM_FMTTRK
|
|
.DB 'Q' \ .DW FMS_SCANEQ, FM_SCANEQ
|
|
.DB 'L' \ .DW FMS_SCANLOEQ, FM_SCANLOEQ
|
|
.DB 'H' \ .DW FMS_SCANHIEQ, FM_SCANHIEQ
|
|
.DB 'C' \ .DW FMS_RECAL, FM_RECAL
|
|
.DB 'N' \ .DW FMS_SENSEINT, FM_SENSEINT
|
|
.DB 'P' \ .DW FMS_SPECIFY, FM_SPECIFY
|
|
.DB 'V' \ .DW FMS_DRVSTAT, FM_DRVSTAT
|
|
.DB 'S' \ .DW FMS_SEEK, FM_SEEK
|
|
.DB 'O' \ .DW FMS_VERSION, FM_VERSION
|
|
.DB 'U' \ .DW FMS_PULSETC, FM_PULSETC
|
|
.DB 'A' \ .DW FMS_DOR, FM_DOR
|
|
.DB 'M' \ .DW FMS_MOTOR, FM_MOTOR
|
|
.DB 'Z' \ .DW FMS_FDCRESET, FM_FDCRESET
|
|
.DB 'X' \ .DW FMS_EXIT, 0000H
|
|
FM_COUNT .EQU (($ - FM_TABLE) / FM_ENTSIZ) ; # ENTRIES IN TABLE
|
|
FM_INFO: .DW FM_DRAW
|
|
.DW FM_TABLE
|
|
.DB FM_ENTSIZ
|
|
.DB FM_COUNT
|
|
;
|
|
; FDC COMMAND MENU STRINGS
|
|
;
|
|
STR_FDCMENU:
|
|
; .TEXT "===================<< FDU FDC COMMAND MENU >>======= [MSR=XX] ==\r\n"
|
|
.TEXT "===================<< FDU FDC COMMAND MENU >>======= [MSR="
|
|
MV_MSR .TEXT "XX"
|
|
.TEXT "] ==\r\n"
|
|
.TEXT "(R)EAD READ (D)EL (W)RITE WRITE D(E)L\r\n"
|
|
.TEXT "READ (T)RK READ (I)D (F)ORMAT SCAN E(Q)\r\n"
|
|
.TEXT "SCAN (L)O/EQ SCAN (H)I/EQ RE(C)AL SE(N)SE INT\r\n"
|
|
.TEXT "S(P)ECIFY DRI(V)E STAT (S)EEK VERSI(O)N\r\n"
|
|
; .TEXT "P(U)LSE TC L(A)TCH:XX (M)OTOR:XXX FDC RESET (Z)\r\n"
|
|
.TEXT "P(U)LSE TC L(A)TCH:"
|
|
MV_LAT .TEXT "XX"
|
|
.TEXT " (M)OTOR:"
|
|
MV_MOT .TEXT "XXX"
|
|
.TEXT " FDC RESET (Z)"
|
|
.TEXT "\r\n"
|
|
.TEXT "E(X)IT\r\n"
|
|
.TEXT "=== OPTION ===> $"
|
|
;
|
|
FMS_NOP .TEXT "NOP$"
|
|
FMS_READ .TEXT "READ$"
|
|
FMS_READDEL .TEXT "READ DELETED$"
|
|
FMS_WRITE .TEXT "WRITE$"
|
|
FMS_WRITEDEL .TEXT "WRITE DELETED$"
|
|
FMS_READTRK .TEXT "READ TRACK$"
|
|
FMS_READID .TEXT "READ ID$"
|
|
FMS_FMTTRK .TEXT "FORMAT TRACK$"
|
|
FMS_SCANEQ .TEXT "SCAN EQUAL$"
|
|
FMS_SCANLOEQ .TEXT "SCAN LOW OR EQUAL$"
|
|
FMS_SCANHIEQ .TEXT "SCAN HIGH OR EQUAL$"
|
|
FMS_RECAL .TEXT "RECALIBRATE$"
|
|
FMS_SENSEINT .TEXT "SENSE INTERRUPT$"
|
|
FMS_SPECIFY .TEXT "SPECIFY$"
|
|
FMS_DRVSTAT .TEXT "DRIVE STATUS$"
|
|
FMS_SEEK .TEXT "SEEK$"
|
|
FMS_VERSION .TEXT "VERSION$"
|
|
FMS_PULSETC .TEXT "PULSE TC$"
|
|
FMS_DOR .TEXT "DOR$"
|
|
FMS_MOTOR .TEXT "MOTOR$"
|
|
FMS_FDCRESET .TEXT "FDC RESET$"
|
|
FMS_EXIT .TEXT "EXIT$"
|
|
;
|
|
; ENTRY POINT FOR FDCMENU
|
|
;
|
|
FDCMENU:
|
|
LD A,01H
|
|
LD (FCD_TRACE),A ; FORCE TRACING OF ALL FDC COMMANDS
|
|
LD HL,FM_INFO
|
|
CALL RUNMENU
|
|
RET
|
|
;
|
|
; FDCMENU DRAW PROCEDURE
|
|
;
|
|
FM_DRAW:
|
|
CALL NEWLINE
|
|
CALL NEWLINE
|
|
|
|
; UPDATE MOTOR STATUS
|
|
LD HL,FDCBM
|
|
LD A,(HL)
|
|
AND _DIO
|
|
JR NZ,FM_DRAW0A
|
|
LD A,(HL)
|
|
AND _ZETA | _DIO3
|
|
JR NZ,FM_DRAW0B
|
|
LD A,(HL)
|
|
AND _PCAT
|
|
JR NZ,FM_DRAW0C
|
|
LD A,(HL)
|
|
AND _RCSMC
|
|
JR NZ,FM_DRAW0D
|
|
JR FM_DRAW3
|
|
FM_DRAW0A: ; DIO
|
|
LD A,(FST_DOR)
|
|
AND 00000010B
|
|
XOR 00000010B
|
|
JR FM_DRAW1
|
|
FM_DRAW0B: ; ZETA, DIO3
|
|
LD A,(FST_DOR)
|
|
AND 00000010B
|
|
JR FM_DRAW1
|
|
FM_DRAW0C: ; DIDE, N8, ZETA2, RCWDC, SMZ80, DYNO, EPFDC, MBC
|
|
LD A,(FST_DOR)
|
|
AND 11110000B
|
|
JR FM_DRAW1
|
|
FM_DRAW0D: ; RCSMC
|
|
LD A,(FST_DOR)
|
|
AND 00000110B
|
|
JR FM_DRAW1
|
|
FM_DRAW1:
|
|
LD DE,STR_ON
|
|
JP NZ,FM_DRAW2
|
|
LD DE,STR_OFF
|
|
FM_DRAW2:
|
|
LD HL,MV_MOT
|
|
CALL STRCPY
|
|
FM_DRAW3:
|
|
|
|
; UPDATE MSR VALUE
|
|
LD DE,MV_MSR
|
|
LD C,(IY+CFG_MSR)
|
|
IN A,(C)
|
|
CALL HEXSTRBYTE
|
|
|
|
; UPDATE FST_DOR VALUE
|
|
LD DE,MV_LAT
|
|
LD A,(FST_DOR)
|
|
CALL HEXSTRBYTE
|
|
|
|
; DISPLAY THE MENU
|
|
LD DE,STR_FDCMENU
|
|
CALL WRITESTR
|
|
|
|
RET
|
|
;
|
|
; FDCMENU FUNCTIONS
|
|
;
|
|
FM_READ:
|
|
CALL FM_GETTHS
|
|
CALL FC_READ
|
|
RET
|
|
|
|
FM_READDEL:
|
|
CALL FM_GETTHS
|
|
CALL FC_READDEL
|
|
RET
|
|
|
|
FM_WRITE:
|
|
CALL FM_GETTHS
|
|
CALL FC_WRITE
|
|
RET
|
|
|
|
FM_WRITEDEL:
|
|
CALL FM_GETTHS
|
|
CALL FC_WRITEDEL
|
|
RET
|
|
|
|
FM_READTRK:
|
|
CALL FM_GETTHS
|
|
CALL FC_READTRK
|
|
RET
|
|
|
|
FM_READID:
|
|
CALL FM_GETHEAD
|
|
CALL FC_READID
|
|
RET
|
|
|
|
FM_FMTTRK:
|
|
CALL FM_GETTRK
|
|
CALL FM_GETHEAD
|
|
CALL FC_FMTTRK
|
|
RET
|
|
|
|
FM_SCANEQ:
|
|
JP FM_NOTIMPL ; NOT IMPLEMENTED!
|
|
CALL FM_GETTHS
|
|
CALL FC_SCANEQ
|
|
RET
|
|
|
|
FM_SCANLOEQ:
|
|
JP FM_NOTIMPL ; NOT IMPLEMENTED!
|
|
CALL FM_GETTHS
|
|
CALL FC_SCANLOEQ
|
|
RET
|
|
|
|
FM_SCANHIEQ:
|
|
JP FM_NOTIMPL ; NOT IMPLEMENTED!
|
|
CALL FM_GETTHS
|
|
CALL FC_SCANHIEQ
|
|
RET
|
|
|
|
FM_RECAL:
|
|
LD A,0 ; UPDATE CYLINDER FOR FUTURE CALLS
|
|
LD (FCD_C),A ; FIX: NOT IN THE RIGHT PLACE
|
|
CALL FC_RECAL
|
|
RET
|
|
|
|
FM_SENSEINT:
|
|
CALL FC_SENSEINT
|
|
RET
|
|
|
|
FM_SPECIFY:
|
|
CALL FC_SPECIFY
|
|
RET
|
|
|
|
FM_DRVSTAT:
|
|
CALL FM_GETHEAD
|
|
CALL FC_DRVSTAT
|
|
RET
|
|
|
|
FM_SEEK:
|
|
CALL FM_GETTRK
|
|
CALL FC_SEEK
|
|
RET
|
|
|
|
FM_VERSION:
|
|
CALL FC_VERSION
|
|
RET
|
|
|
|
FM_PULSETC:
|
|
CALL NEWLINE
|
|
CALL FC_PULSETC
|
|
RET
|
|
|
|
FM_DOR:
|
|
CALL FM_GETDOR
|
|
CALL FC_SETDOR
|
|
RET
|
|
|
|
FM_MOTOR:
|
|
; TOGGLE MOTOR STATE
|
|
LD HL,FDCBM
|
|
LD A,(HL)
|
|
AND _DIO
|
|
JR NZ,FM_MOTOR0A
|
|
LD A,(HL)
|
|
AND _ZETA | _DIO3
|
|
JR NZ,FM_MOTOR0B
|
|
LD A,(HL)
|
|
AND _PCAT
|
|
JR NZ,FM_MOTOR0C
|
|
LD A,(HL)
|
|
AND _RCSMC
|
|
JR NZ,FM_MOTOR0D
|
|
RET
|
|
FM_MOTOR0A: ; DIO
|
|
LD A,(FST_DOR)
|
|
AND 00000010B
|
|
XOR 00000010B
|
|
JR FM_MOTOR1
|
|
FM_MOTOR0B: ; ZETA, DIO3
|
|
LD A,(FST_DOR)
|
|
AND 00000010B
|
|
JR FM_MOTOR1
|
|
FM_MOTOR0C: ; DIDE, N8, ZETA2, RCWDC, SMZ80, DYNO, EPFDC, MBC
|
|
LD A,(FST_DOR)
|
|
AND 11110000B
|
|
JR FM_MOTOR1
|
|
FM_MOTOR0D: ; RCSMC
|
|
LD A,(FST_DOR)
|
|
AND 00000110B
|
|
JR FM_MOTOR1
|
|
FM_MOTOR1:
|
|
JP Z,FC_MOTORON
|
|
JP FC_MOTOROFF
|
|
|
|
FM_FDCRESET:
|
|
CALL NEWLINE
|
|
LD A,(FDCID)
|
|
CP FDC_DIO ; RESET NOT POSSIBLE ON DIO
|
|
JP NZ,FC_RESETFDC
|
|
LD DE,FCS_NORES
|
|
JP WRITESTR
|
|
|
|
FM_NOTIMPL:
|
|
CALL PC_SPACE ; NOT IMPLEMENTED
|
|
LD DE,STR_NOTIMPL
|
|
CALL WRITESTR
|
|
RET
|
|
|
|
FM_GETTHS:
|
|
CALL FM_GETTRK
|
|
CALL FM_GETHEAD
|
|
CALL FM_GETSEC
|
|
RET
|
|
|
|
FM_GETTRK:
|
|
LD DE,FCPP_TRK
|
|
LD HL,FCD_C
|
|
CALL GETHEXBYTE
|
|
RET
|
|
|
|
FM_GETHEAD:
|
|
LD DE,FCPP_HEAD
|
|
LD HL,FCD_H
|
|
CALL GETHEXBYTE
|
|
RET
|
|
|
|
FM_GETSEC:
|
|
LD DE,FCPP_SEC
|
|
LD HL,FCD_R
|
|
CALL GETHEXBYTE
|
|
RET
|
|
|
|
FM_GETDOR:
|
|
LD DE,FCPP_DOR
|
|
LD HL,FST_DOR
|
|
CALL GETHEXBYTE
|
|
RET
|
|
;
|
|
FCS_NORES .TEXT "\r\n*** RESET NOT SUPORTED BY HARDWARE ***$"
|
|
;
|
|
;===============================================================================
|
|
; FLOPPY DISK CONTROL SERVICES (PHYSICAL DEVICE CONTROL FOR FDC HARDWARE)
|
|
;===============================================================================
|
|
;
|
|
; FDC RESULT CODES
|
|
;
|
|
FRC_OK .EQU 0 ; 00
|
|
FRC_NOTIMPL .EQU -01H ; FF
|
|
FRC_CMDERR .EQU -02H ; FE
|
|
FRC_ERROR .EQU -03H ; FD
|
|
FRC_ABORT .EQU -04H ; FC
|
|
FRC_BUFMAX .EQU -05H ; FB
|
|
FRC_ABTERM .EQU -08H ; F8
|
|
FRC_INVCMD .EQU -09H ; F7
|
|
FRC_DSKCHG .EQU -0AH ; F6
|
|
FRC_ENDCYL .EQU -0BH ; F5
|
|
FRC_DATAERR .EQU -0CH ; F4
|
|
FRC_OVERRUN .EQU -0DH ; F3
|
|
FRC_NODATA .EQU -0EH ; F2
|
|
FRC_NOTWRIT .EQU -0FH ; F1
|
|
FRC_MISADR .EQU -10H ; F0
|
|
FRC_TOFDCRDY .EQU -11H ; EF
|
|
FRC_TOSNDCMD .EQU -12H ; EE
|
|
FRC_TOGETRES .EQU -13H ; ED
|
|
FRC_TOEXEC .EQU -14H ; EC
|
|
FRC_TOSEEKWT .EQU -15H ; EB
|
|
FRC_MISMATCH .EQU -16H ; EA
|
|
;
|
|
; FDC STATUS CODE STRINGS
|
|
;
|
|
FSS_OK .TEXT "OK$"
|
|
FSS_NOTIMPL .TEXT "NOT IMPLEMENTED$"
|
|
FSS_CMDERR .TEXT "COMMAND ERROR$"
|
|
FSS_ERROR .TEXT "ERROR$"
|
|
FSS_ABORT .TEXT "ABORT$"
|
|
FSS_BUFMAX .TEXT "BUFFER EXCEEDED$"
|
|
FSS_ABTERM .TEXT "ABNORMAL TERMINATION$"
|
|
FSS_INVCMD .TEXT "INVALID COMMAND$"
|
|
FSS_DSKCHG .TEXT "DISK CHANGE$"
|
|
FSS_ENDCYL .TEXT "END OF CYLINDER$"
|
|
FSS_DATAERR .TEXT "DATA ERROR$"
|
|
FSS_OVERRUN .TEXT "OVERRUN$"
|
|
FSS_NODATA .TEXT "NO DATA$"
|
|
FSS_NOTWRIT .TEXT "NOT WRITABLE$"
|
|
FSS_MISADR .TEXT "MISSING ADDRESS MARK$"
|
|
FSS_TOFDCRDY .TEXT "FDC READY TIMEOUT$"
|
|
FSS_TOSNDCMD .TEXT "SENDCMD TIMEOUT$"
|
|
FSS_TOGETRES .TEXT "GET RESULTS TIMEOUT$"
|
|
FSS_TOEXEC .TEXT "EXEC TIMEOUT$"
|
|
FSS_TOSEEKWT .TEXT "SEEK WAIT TIMEOUT$"
|
|
;
|
|
; FDC STATUS STRING TABLE
|
|
;
|
|
FSST: .DB FRC_OK \ .DW FSS_OK
|
|
FSST_ENTSIZ .EQU $ - FSST
|
|
.DB FRC_NOTIMPL \ .DW FSS_NOTIMPL
|
|
.DB FRC_CMDERR \ .DW FSS_CMDERR
|
|
.DB FRC_ERROR \ .DW FSS_ERROR
|
|
.DB FRC_ABORT \ .DW FSS_ABORT
|
|
.DB FRC_BUFMAX \ .DW FSS_BUFMAX
|
|
.DB FRC_ABTERM \ .DW FSS_ABTERM
|
|
.DB FRC_INVCMD \ .DW FSS_INVCMD
|
|
.DB FRC_DSKCHG \ .DW FSS_DSKCHG
|
|
.DB FRC_ENDCYL \ .DW FSS_ENDCYL
|
|
.DB FRC_DATAERR \ .DW FSS_DATAERR
|
|
.DB FRC_OVERRUN \ .DW FSS_OVERRUN
|
|
.DB FRC_NODATA \ .DW FSS_NODATA
|
|
.DB FRC_NOTWRIT \ .DW FSS_NOTWRIT
|
|
.DB FRC_MISADR \ .DW FSS_MISADR
|
|
.DB FRC_TOFDCRDY \ .DW FSS_TOFDCRDY
|
|
.DB FRC_TOSNDCMD \ .DW FSS_TOSNDCMD
|
|
.DB FRC_TOGETRES \ .DW FSS_TOGETRES
|
|
.DB FRC_TOEXEC \ .DW FSS_TOEXEC
|
|
.DB FRC_TOSEEKWT \ .DW FSS_TOSEEKWT
|
|
FSST_COUNT .EQU (($ - FSST) / FSST_ENTSIZ) ; # ENTRIES IN TABLE
|
|
;
|
|
; FDC COMMAND PHASE
|
|
;
|
|
FCP_CMD .DB 000H ; INPUT: COMMAND CODE
|
|
FCP_BUFLEN .DB 00H
|
|
FCP_BUF .FILL 10H
|
|
FCP_BUFSIZ .EQU $-FCP_BUF
|
|
FCP_XFRCNT .DW 00H ; BYTES TRANSFERRED DURING COMMAND PHASE
|
|
;
|
|
; FDC EXECUTION PHASE
|
|
;
|
|
FXP_XR .DW 00H ; INPUT: ADDRESS OF EXECUTION ROUTINE TO INVOKE
|
|
FXP_TO .DB 00H ; TIMEOUT COUNTDOWN TIMER USED IN SOME VARIATIONS
|
|
FXP_ITER .DB 00H ; LOOP ITERATION COUNTER (MUST IMMEDIATELY FOLLOW FXP_TO)
|
|
FXP_A .DB 00H ; LAST VALUE OF REG A RECORDED DURING EXECUTION
|
|
FXP_BC .DW 00H ; LAST VALUE OF REG BC RECORDED DURING EXECUTION
|
|
FXP_DE .DW 00H ; LAST VALUE OF REG DE RECORDED DURING EXECUTION
|
|
FXP_HL .DW 00H ; LAST VALUE OF REG HL RECORDED DURING EXECUTION
|
|
FXP_BUFLEN .DB 00H
|
|
FXP_BUF .FILL 50H ; USED FOR CERTAIN EXEC ROUTINES (FORMAT TRACK)
|
|
FXP_BUFSIZ .EQU $-FXP_BUF
|
|
;
|
|
; FDC STATUS
|
|
;
|
|
FST_RC .DB 00H
|
|
FST_MSR .DB 00H
|
|
FST_DOR .DB 00H
|
|
;
|
|
; FDC RESULTS BUFFER
|
|
;
|
|
FRB_LEN .DB 00H
|
|
FRB
|
|
FRB_ST0
|
|
FRB_ST3 .DB 0
|
|
FRB_ST1
|
|
FRB_PCN .DB 0
|
|
FRB_ST2 .DB 0
|
|
FRB_C .DB 0
|
|
FRB_H .DB 0
|
|
FRB_R .DB 0
|
|
FRB_N .DB 0
|
|
.FILL 10H ; ALLOWS EXTRA CHARACTERS TO BE RETREIEVED
|
|
FRB_SIZ .EQU $-FRB
|
|
;
|
|
; FDC COMMANDS
|
|
;
|
|
CMD_READ .EQU 00000110B ; ST0,ST1,ST2,C,H,R,N
|
|
CMD_READDEL .EQU 00001100B ; ST0,ST1,ST2,C,H,R,N
|
|
CMD_WRITE .EQU 00000101B ; ST0,ST1,ST2,C,H,R,N
|
|
CMD_WRITEDEL .EQU 00001001B ; ST0,ST1,ST2,C,H,R,N
|
|
CMD_READTRK .EQU 00000010B ; ST0,ST1,ST2,C,H,R,N
|
|
CMD_READID .EQU 00001010B ; ST0,ST1,ST2,C,H,R,N
|
|
CMD_FMTTRK .EQU 00001101B ; ST0,ST1,ST2,C,H,R,N
|
|
CMD_SCANEQ .EQU 00010001B ; ST0,ST1,ST2,C,H,R,N
|
|
CMD_SCANLOEQ .EQU 00011001B ; ST0,ST1,ST2,C,H,R,N
|
|
CMD_SCANHIEQ .EQU 00011101B ; ST0,ST1,ST2,C,H,R,N
|
|
CMD_RECAL .EQU 00000111B ; <EMPTY>
|
|
CMD_SENSEINT .EQU 00001000B ; ST0,PCN
|
|
CMD_SPECIFY .EQU 00000011B ; <EMPTY>
|
|
CMD_DRVSTAT .EQU 00000100B ; ST3
|
|
CMD_SEEK .EQU 00001111B ; <EMPTY>
|
|
CMD_VERSION .EQU 00010000B ; ST0
|
|
;
|
|
; FDC COMMAND DATA
|
|
;
|
|
FCD: ; FLOPPY CONFIGURATION DATA (PUBLIC) MANAGED AS A "BLOCK", SEE FCB BELOW
|
|
FCD_EOT ; END OF TRACK SECTOR (SAME AS SC SINCE SOT ALWAYS 1)
|
|
FCD_SC .DB 000H ; SECTOR COUNT
|
|
FCD_SECSZ .DW 000H ; SECTOR SIZE IN BYTES
|
|
FCD_GPL .DB 000H ; GAP LENGTH (R/W)
|
|
FCD_GPLF .DB 000H ; GAP LENGTH (FORMAT)
|
|
FCD_SRTHUT .DB 000H ; STEP RATE, IBM PS/2 CALLS FOR 3ms, 0DH = 3ms SRT, HEAD UNLOAD TIME
|
|
FCD_HLT .DB 000H ; HEAD LOAD TIME, IBM PS/2 CALLS FOR 15ms 08H = 16ms HUT
|
|
FCD_DORA .DB 000H ; DEFAULT DOR VALUE FOR MEDIA
|
|
FCD_DORB .DB 000H ; DEFAULT DOR VALUE FOR MEDIA
|
|
FCD_DORC .DB 000H ; DEFAULT DOR VALUE FOR MEDIA
|
|
FCD_DORD .DB 000H ; DEFAULT DOR VALUE FOR MEDIA
|
|
FCD_DCR .DB 000H ; DOR VALUE FOR MEDIA
|
|
FCD_LEN .EQU $ - FCD
|
|
; DYNAMICALLY MANAGED (PUBLIC)
|
|
FCD_DS .DB 001H ; DRIVE SELECT (UNIT NUMBER 0-3)
|
|
FCD_C .DB 000H ; CYLINDER
|
|
FCD_H .DB 000H ; HEAD
|
|
FCD_R .DB 001H ; RECORD
|
|
FCD_D .DB 0E5H ; FORMAT DATA FILL BYTE
|
|
FCD_X .DB 002H ; FORMAT INTERLEAVE FACTOR (1...N)
|
|
FCD_ND .DB 000H ; DMA, 0=DMA, 1=NON-DMA
|
|
; STATIC CONFIGURATION, NEVER CHANGES (PRIVATE)
|
|
FCD_SOT .DB 001H ; STARTING SECTOR NUMBER OF TRACK
|
|
FCD_MT .DB 000H ; MULTI-TRACK, WE DON'T USE, SET TO 0
|
|
FCD_MFM .DB 001H ; MFM, 0=FM, 1=MFM, WE USE MFM ALWAYS
|
|
FCD_SK .DB 000H ; SKIP MODE, WE DON'T USE, SET TO 0
|
|
FCD_N .DB 002H ; SECTOR SIZE, N=2 FOR 512 BYTES
|
|
FCD_DTL .DB 0FFH ; DATA LENGTH (WHEN N=0, SET TO FF OTHERWISE)
|
|
FCD_STP .DB 001H ; SECTOR SCAN TYPE, 1=CONTIG, 2=ALTERNATING
|
|
; CONTROL STUFF (PUBLIC)
|
|
FCD_TRACE .DB 00H ; TRACE LEVEL
|
|
;
|
|
;
|
|
; FDC CMD PARM PROMPTS
|
|
;
|
|
FCPP_TRK .TEXT "TRACK$"
|
|
FCPP_HEAD .TEXT "HEAD$"
|
|
FCPP_SEC .TEXT "SECTOR$"
|
|
FCPP_DOR .TEXT "DOR$"
|
|
;
|
|
; FDC EXECUTION ROUTINE JUMP TABLE
|
|
;
|
|
FXRJ_NOP: JP FXR_NOP
|
|
FXRJ_READ: JP FXR_READ
|
|
FXRJ_READDEL: JP FXR_READDEL
|
|
FXRJ_WRITE: JP FXR_WRITE
|
|
FXRJ_WRITEDEL: JP FXR_WRITEDEL
|
|
FXRJ_READTRK: JP FXR_READTRK
|
|
FXRJ_READID: JP FXR_READID
|
|
FXRJ_FMTTRK: JP FXR_FMTTRK
|
|
FXRJ_SCANEQ: JP FXR_SCANEQ
|
|
FXRJ_SCANLOEQ: JP FXR_SCANLOEQ
|
|
FXRJ_SCANHIEQ: JP FXR_SCANHIEQ
|
|
FXRJ_RECAL: JP FXR_RECAL
|
|
FXRJ_SENSEINT: JP FXR_SENSEINT
|
|
FXRJ_SPECIFY: JP FXR_SPECIFY
|
|
FXRJ_DRVSTAT: JP FXR_DRVSTAT
|
|
FXRJ_SEEK: JP FXR_SEEK
|
|
FXRJ_VERSION JP FXR_VERSION
|
|
;
|
|
; FDC COMMAND STRINGS
|
|
;
|
|
FCS_NOP: .TEXT "NOP$"
|
|
FCS_READ: .TEXT "READ$"
|
|
FCS_READDEL: .TEXT "READ DELETED$"
|
|
FCS_WRITE: .TEXT "WRITE$"
|
|
FCS_WRITEDEL: .TEXT "WRITE DELETED$"
|
|
FCS_READTRK: .TEXT "READ TRACK$"
|
|
FCS_READID: .TEXT "READ ID$"
|
|
FCS_FMTTRK: .TEXT "FORMAT TRACK$"
|
|
FCS_SCANEQ: .TEXT "SCAN EQUAL$"
|
|
FCS_SCANLOEQ: .TEXT "SCAN LOW OR EQUAL$"
|
|
FCS_SCANHIEQ: .TEXT "SCAN HIGH OR EQUAL$"
|
|
FCS_RECAL: .TEXT "RECALIBRATE$"
|
|
FCS_SENSEINT: .TEXT "SENSE INTERRUPT$"
|
|
FCS_SPECIFY: .TEXT "SPECIFY$"
|
|
FCS_DRVSTAT: .TEXT "DRIVE STATUS$"
|
|
FCS_SEEK: .TEXT "SEEK$"
|
|
FCS_VERSION: .TEXT "VERSION$"
|
|
;
|
|
; FDC COMMAND TABLE
|
|
;
|
|
FCT .DB CMD_READ \ .DW FCS_READ, FXRJ_READ
|
|
FCT_ENTSIZ .EQU $ - FCT
|
|
.DB CMD_READDEL \ .DW FCS_READDEL, FXRJ_READDEL
|
|
.DB CMD_WRITE \ .DW FCS_WRITE, FXRJ_WRITE
|
|
.DB CMD_WRITEDEL \ .DW FCS_WRITEDEL, FXRJ_WRITEDEL
|
|
.DB CMD_READTRK \ .DW FCS_READTRK, FXRJ_READTRK
|
|
.DB CMD_READID \ .DW FCS_READID, FXRJ_READID
|
|
.DB CMD_FMTTRK \ .DW FCS_FMTTRK, FXRJ_FMTTRK
|
|
.DB CMD_SCANEQ \ .DW FCS_SCANEQ, FXRJ_SCANEQ
|
|
.DB CMD_SCANLOEQ \ .DW FCS_SCANLOEQ, FXRJ_SCANLOEQ
|
|
.DB CMD_SCANHIEQ \ .DW FCS_SCANHIEQ, FXRJ_SCANHIEQ
|
|
.DB CMD_RECAL \ .DW FCS_RECAL, FXRJ_RECAL
|
|
.DB CMD_SENSEINT \ .DW FCS_SENSEINT, FXRJ_SENSEINT
|
|
.DB CMD_SPECIFY \ .DW FCS_SPECIFY, FXRJ_SPECIFY
|
|
.DB CMD_DRVSTAT \ .DW FCS_DRVSTAT, FXRJ_DRVSTAT
|
|
.DB CMD_SEEK \ .DW FCS_SEEK, FXRJ_SEEK
|
|
.DB CMD_VERSION \ .DW FCS_VERSION, FXRJ_VERSION
|
|
FCT_COUNT .EQU (($ - FCT) / FCT_ENTSIZ) ; # ENTRIES IN TABLE
|
|
;
|
|
; ENTRY POINTS FOR FDC COMMANDS
|
|
;
|
|
FC_READ:
|
|
LD A,CMD_READ
|
|
LD B,0FFH ; MT & MFM & SK & CMD BITS
|
|
LD (FCP_CMD),A
|
|
LD HL,FXR_READ
|
|
LD (FXP_XR),HL
|
|
CALL FC_SETUPIO
|
|
CALL FC_CMDPROC
|
|
RET
|
|
|
|
FC_READDEL:
|
|
LD A,CMD_READDEL
|
|
LD B,0FFH ; MT & MFM & SK & CMD BITS
|
|
LD (FCP_CMD),A
|
|
LD HL,FXR_READDEL
|
|
LD (FXP_XR),HL
|
|
CALL FC_SETUPIO
|
|
CALL FC_CMDPROC
|
|
RET
|
|
|
|
FC_WRITE:
|
|
LD A,CMD_WRITE
|
|
LD B,0DFH ; MT & MFM & CMD BITS
|
|
LD (FCP_CMD),A
|
|
LD HL,FXR_WRITE
|
|
LD (FXP_XR),HL
|
|
CALL FC_SETUPIO
|
|
CALL FC_CMDPROC
|
|
RET
|
|
|
|
FC_WRITEDEL:
|
|
LD A,CMD_WRITEDEL
|
|
LD B,0DFH ; MT & MFM & CMD BITS
|
|
LD (FCP_CMD),A
|
|
LD HL,FXR_WRITEDEL
|
|
LD (FXP_XR),HL
|
|
CALL FC_SETUPIO
|
|
CALL FC_CMDPROC
|
|
RET
|
|
|
|
FC_READTRK:
|
|
LD A,CMD_READTRK
|
|
LD B,07FH ; MFM & SK & CMD BITS
|
|
LD (FCP_CMD),A
|
|
LD HL,FXR_READTRK
|
|
LD (FXP_XR),HL
|
|
CALL FC_SETUPIO
|
|
CALL FC_CMDPROC
|
|
RET
|
|
|
|
FC_READID:
|
|
LD A,CMD_READID
|
|
LD B,05FH ; MFM & CMD BITS
|
|
LD (FCP_CMD),A
|
|
LD HL,FXR_READID
|
|
LD (FXP_XR),HL
|
|
CALL FC_SETUPCMD
|
|
CALL FC_CMDPROC
|
|
RET
|
|
|
|
FC_FMTTRK:
|
|
LD A,CMD_FMTTRK
|
|
LD B,05FH ; MFM & CMD BITS
|
|
LD (FCP_CMD),A
|
|
LD HL,FXR_FMTTRK
|
|
LD (FXP_XR),HL
|
|
CALL FC_SETUPFMT
|
|
CALL FC_CMDPROC
|
|
RET
|
|
|
|
FC_SCANEQ:
|
|
LD A,CMD_SCANEQ
|
|
LD B,0FFH ; MT & MFM & SK & CMD BITS
|
|
LD (FCP_CMD),A
|
|
LD HL,FXR_SCANEQ
|
|
LD (FXP_XR),HL
|
|
CALL FC_SETUPSCAN
|
|
CALL FC_CMDPROC
|
|
RET
|
|
|
|
FC_SCANLOEQ:
|
|
LD A,CMD_SCANLOEQ
|
|
LD B,0FFH ; MT & MFM & SK & CMD BITS
|
|
LD (FCP_CMD),A
|
|
LD HL,FXR_SCANLOEQ
|
|
LD (FXP_XR),HL
|
|
CALL FC_SETUPSCAN
|
|
CALL FC_CMDPROC
|
|
RET
|
|
|
|
FC_SCANHIEQ:
|
|
LD A,CMD_SCANHIEQ
|
|
LD B,0FFH ; MT & MFM & SK & CMD BITS
|
|
LD (FCP_CMD),A
|
|
LD HL,FXR_SCANHIEQ
|
|
LD (FXP_XR),HL
|
|
CALL FC_SETUPSCAN
|
|
CALL FC_CMDPROC
|
|
RET
|
|
|
|
FC_RECAL:
|
|
LD A,CMD_RECAL
|
|
LD B,01FH ; CMD BITS ONLY
|
|
LD (FCP_CMD),A
|
|
LD HL,FXR_RECAL
|
|
LD (FXP_XR),HL
|
|
CALL FC_SETUPSEEK ; SPECIALIZATION OF SEEK
|
|
LD A,2 ; GENERIC COMMAND, BUT JUST FIRST COMMAND CODE
|
|
LD (FCP_BUFLEN),A
|
|
CALL FC_CMDPROC
|
|
RET
|
|
|
|
FC_SENSEINT:
|
|
LD A,CMD_SENSEINT
|
|
LD B,01FH ; CMD BITS ONLY
|
|
LD (FCP_CMD),A
|
|
LD HL,FXR_SENSEINT
|
|
LD (FXP_XR),HL
|
|
CALL FC_SETUPCMD
|
|
LD A,1 ; GENERIC COMMAND, BUT JUST FIRST COMMAND CODE
|
|
LD (FCP_BUFLEN),A
|
|
CALL FC_CMDPROC
|
|
RET
|
|
|
|
FC_SPECIFY:
|
|
LD A,CMD_SPECIFY
|
|
LD B,01FH ; CMD BITS ONLY
|
|
LD (FCP_CMD),A
|
|
LD HL,FXR_SPECIFY
|
|
LD (FXP_XR),HL
|
|
CALL FC_SETUPSPECIFY
|
|
CALL FC_CMDPROC
|
|
RET
|
|
|
|
FC_DRVSTAT:
|
|
LD A,CMD_DRVSTAT
|
|
LD B,01FH ; CMD BITS ONLY
|
|
LD (FCP_CMD),A
|
|
LD HL,FXR_DRVSTAT
|
|
LD (FXP_XR),HL
|
|
CALL FC_SETUPCMD
|
|
CALL FC_CMDPROC
|
|
RET
|
|
|
|
FC_SEEK:
|
|
LD A,CMD_SEEK
|
|
LD B,01FH ; CMD BITS ONLY
|
|
LD (FCP_CMD),A
|
|
LD HL,FXR_SEEK
|
|
LD (FXP_XR),HL
|
|
CALL FC_SETUPSEEK
|
|
CALL FC_CMDPROC
|
|
RET
|
|
|
|
FC_VERSION:
|
|
LD A,CMD_VERSION
|
|
LD B,01FH ; CMD BITS ONLY
|
|
LD (FCP_CMD),A
|
|
LD HL,FXR_VERSION
|
|
LD (FXP_XR),HL
|
|
CALL FC_SETUPCMD
|
|
LD A,1 ; GENERIC COMMAND, BUT JUST FIRST COMMAND CODE
|
|
LD (FCP_BUFLEN),A
|
|
CALL FC_CMDPROC
|
|
RET
|
|
;
|
|
; HELPER FUNCTIONS TO SETUP CMDBUF
|
|
;
|
|
FC_SETUPCMD:
|
|
PUSH BC ; B CONTAINS BIT MASK TO USE FOR FIRST BYTE
|
|
; SO THAT WE CAN MASK OFF BITS THAT ARE NOT
|
|
; USED FOR CERTAIN COMMANDS
|
|
LD DE,FCP_BUF
|
|
|
|
AND 01FH ; REMOVE ANY EXTRANEOUS BITS FROM COMMAND BYTE
|
|
LD C,A ; SAVE THE COMMAND
|
|
LD A,(FCD_MT) ; GET MT BIT
|
|
AND 01H ; MASK TO REMOVE IRRELEVANT BITS FOR SAFETY
|
|
RLA ; MAKE ROOM FOR MFM
|
|
LD B,A ; SAVE WHAT WE HAVE SO FAR IN B
|
|
LD A,(FCD_MFM) ; GET MFM BIT
|
|
AND 01H ; MASK TO REMOVE IRRELEVANT BITS FOR SAFETY
|
|
OR B ; COMBINE WITH SAVED
|
|
RLA ; MAKE ROOM FOR SK
|
|
LD B,A ; SAVE WHAT WE HAVE SO FAR IN B
|
|
LD A,(FCD_SK) ; GET SK BIT
|
|
AND 01H ; MASK TO REMOVE IRRELEVANT BITS FOR SAFETY
|
|
OR B ; COMBINE WITH SAVED
|
|
RLA ; MAKE ROOM FOR THE COMMAND BITS
|
|
RLA
|
|
RLA
|
|
RLA
|
|
RLA
|
|
LD B,C ; RECOVER THE COMMAND VALUE
|
|
OR B ; COMBINE WITH SAVED
|
|
POP BC ; GET THE BIT MASK FOR FIRST BYTE
|
|
AND B ; APPLY IT
|
|
LD (DE),A ; SAVE THE BYTE
|
|
INC DE
|
|
|
|
LD A,(FCD_H) ; START WITH HDS
|
|
AND 01H ; MASK TO REMOVE IRRELEVANT BITS FOR SAFETY
|
|
RLA ; MAKE ROOM FOR DS BITS
|
|
RLA ;
|
|
LD B,A ; SAVE WHAT WE HAVE SO FAR IN B
|
|
LD A,(FCD_DS) ; GET DS VALUE
|
|
AND 03H ; MASK TO REMOVE IRRELEVANT BITS FOR SAFETY
|
|
OR B ; COMBINE WITH SAVED
|
|
LD (DE),A ; SAVE THE BYTE
|
|
INC DE
|
|
|
|
LD A,2 ; THIS IS A 2 BYTE COMMAND STRING
|
|
LD (FCP_BUFLEN),A
|
|
|
|
RET
|
|
|
|
FC_SETUPIO:
|
|
CALL FC_SETUPCMD
|
|
|
|
LD A,(FCD_C)
|
|
LD (DE),A
|
|
INC DE
|
|
|
|
LD A,(FCD_H)
|
|
LD (DE),A
|
|
INC DE
|
|
|
|
LD A,(FCD_R)
|
|
LD (DE),A
|
|
INC DE
|
|
|
|
LD A,(FCD_N)
|
|
LD (DE),A
|
|
INC DE
|
|
|
|
; V5.3, USE EOT=R TO R/W ONLY ONE SECTOR
|
|
;LD A,(FCD_EOT)
|
|
LD A,(FCD_R)
|
|
LD (DE),A
|
|
INC DE
|
|
|
|
LD A,(FCD_GPL)
|
|
LD (DE),A
|
|
INC DE
|
|
|
|
LD A,(FCD_DTL)
|
|
LD (DE),A
|
|
INC DE
|
|
|
|
LD A,9
|
|
LD (FCP_BUFLEN),A
|
|
|
|
RET
|
|
|
|
FC_SETUPFMT:
|
|
CALL FC_SETUPCMD
|
|
|
|
LD A,(FCD_N)
|
|
LD (DE),A
|
|
INC DE
|
|
|
|
LD A,(FCD_SC)
|
|
LD (DE),A
|
|
INC DE
|
|
|
|
LD A,(FCD_GPLF)
|
|
LD (DE),A
|
|
INC DE
|
|
|
|
LD A,(FCD_D)
|
|
LD (DE),A
|
|
INC DE
|
|
|
|
LD A,6
|
|
LD (FCP_BUFLEN),A
|
|
|
|
; SETUP FORMAT BUFFER WITH SECTOR ID INFO FOR ENTIRE TRACK - (C,H,S,N) FOR EACH SECTOR
|
|
; INTERLEAVE AS REQUESTED
|
|
;
|
|
; B = CURRENT INTERLEAVE PASS STARTING SECTOR ID
|
|
; C = CURRENT SECTOR ID
|
|
; H = INTERLEAVE STEP
|
|
; L = LAST SECTOR ID + 1
|
|
; DE = BUFFER POINTER
|
|
;
|
|
|
|
PUSH DE
|
|
PUSH HL
|
|
|
|
; COMPUTE INTERLEAVE STEP
|
|
LD H,-1
|
|
LD A,(FCD_X)
|
|
LD B,A
|
|
LD A,(FCD_SC)
|
|
LOOP:
|
|
INC H
|
|
SUB B
|
|
JR NC,LOOP
|
|
|
|
LD DE,FXP_BUF ; DE POINTS TO START OF BUFFER
|
|
|
|
LD A,(FCD_SOT) ; GET FIRST SECTOR ID
|
|
LD B,A ; B = FIRST SECTOR ID FOR CURRENT INTERLEAVE PASS
|
|
LD C,A ; C = SECTOR ID
|
|
|
|
LD A,(FCD_SC) ; NUM SECTORS TO SET UP
|
|
ADD A,C
|
|
LD L,A ; L = LAST SECTOR ID + 1
|
|
|
|
FC_SETUPFMT1:
|
|
; CYLINDER
|
|
LD A,(FCD_C)
|
|
LD (DE),A
|
|
INC DE
|
|
|
|
; HEAD
|
|
LD A,(FCD_H)
|
|
LD (DE),A
|
|
INC DE
|
|
|
|
; SECTOR ID
|
|
LD A,C
|
|
LD (DE),A
|
|
INC DE
|
|
|
|
; SECTOR SIZE
|
|
LD A,(FCD_N)
|
|
LD (DE),A
|
|
INC DE
|
|
|
|
; INC SECTOR ID BY INTERLEAVE STEP
|
|
LD A,H
|
|
ADD A,C
|
|
LD C,A
|
|
|
|
; LOOP IF WE HAVE NOT GOTTEN PAST LAST SECTOR ID
|
|
CP L
|
|
JP M,FC_SETUPFMT1
|
|
|
|
; SETUP FOR NEXT INTERLEAVE PASS
|
|
INC B
|
|
LD C,B
|
|
|
|
; LOOP IF WE ARE NOT DONE
|
|
LD A,H
|
|
CP C
|
|
JP P,FC_SETUPFMT1
|
|
|
|
; DONE, FINALIZE BUFFER
|
|
LD A,(FCD_SC) ; GET SECTOR COUNT
|
|
RLCA ; MULTIPLY BY 4
|
|
RLCA
|
|
LD (FXP_BUFLEN),A ; STORE AS BUFFER LENGTH
|
|
|
|
POP HL
|
|
POP DE
|
|
RET
|
|
|
|
FC_SETUPSCAN:
|
|
CALL FC_SETUPIO ; START WITH GENERIC IO CMD
|
|
|
|
LD DE,FCP_BUF+8 ; REPLACE DTL WITH STP
|
|
LD A,(FCD_STP)
|
|
LD (DE),A
|
|
|
|
RET
|
|
|
|
FC_SETUPSEEK:
|
|
CALL FC_SETUPCMD ; START WITH GENERIC IO CMD
|
|
|
|
LD A,(FCD_C)
|
|
LD (DE),A
|
|
INC DE
|
|
|
|
LD DE,FCP_BUF ; REMOVE EXTRANEOUS BITS FROM CC0
|
|
LD A,(DE)
|
|
AND 0FH
|
|
LD (DE),A
|
|
|
|
LD A,3
|
|
LD (FCP_BUFLEN),A
|
|
|
|
RET
|
|
|
|
FC_SETUPSPECIFY:
|
|
CALL FC_SETUPCMD
|
|
DEC DE ; BACKUP 1 BYTE, WE ONLY WANT FIRST BYTE
|
|
|
|
LD A,(FCD_SRTHUT)
|
|
LD (DE),A ; SAVE THE BYTE
|
|
INC DE
|
|
|
|
LD A,(FCD_HLT)
|
|
AND 07FH
|
|
RLA
|
|
LD B,A
|
|
LD A,(FCD_ND)
|
|
AND 01H
|
|
OR B
|
|
LD (DE),A ; SAVE THE BYTE
|
|
INC DE
|
|
|
|
LD A,3
|
|
LD (FCP_BUFLEN),A
|
|
|
|
RET
|
|
;
|
|
; MAIN FDC COMMAND PROCESSOR
|
|
;
|
|
FC_CMDPROC:
|
|
CALL FOP
|
|
CALL FC_PRTRESULTS
|
|
RET
|
|
;
|
|
; FDC SEQUENCE INITIALIZATION
|
|
;
|
|
FC_INIT:
|
|
LD HL,FDCBM
|
|
LD A,(HL)
|
|
AND _DIO
|
|
JR NZ,FC_INIT1
|
|
LD A,(HL)
|
|
AND _ZETA | _DIO3
|
|
JR NZ,FC_INIT2
|
|
LD A,(HL)
|
|
AND _PCAT
|
|
JR NZ,FC_INIT3
|
|
LD A,(HL)
|
|
AND _RCSMC
|
|
JR NZ,FC_INIT4
|
|
RET
|
|
FC_INIT1: ; DIO
|
|
LD A,(FCD_DORA)
|
|
JR FC_INIT5
|
|
FC_INIT2: ; ZETA, DIO3
|
|
LD A,(FCD_DORB)
|
|
JR FC_INIT5
|
|
FC_INIT3: ; DIDE, N8, ZETA2, RCWDC, SMZ80, DYNO, EPFDC, MBC
|
|
LD A,(FCD_DORC)
|
|
JR FC_INIT5
|
|
FC_INIT4: ; WDSMC
|
|
LD A,(FCD_DORD)
|
|
JR FC_INIT5
|
|
|
|
FC_INIT5:
|
|
LD (FST_DOR),A
|
|
CALL FC_SETDOR
|
|
RET
|
|
;
|
|
; SET FST_DOR
|
|
;
|
|
FC_SETDOR:
|
|
PUSH AF
|
|
LD A,(FST_DOR)
|
|
LD C,(IY+CFG_DOR)
|
|
OUT (C),A
|
|
POP AF
|
|
RET
|
|
;
|
|
; RESET FDC BY PULSING BIT 7 OF DOR LOW
|
|
; NOTE: DIO HARDWARE HAS NO MECHANISM TO PULSE RESET VIA SOFTWARE
|
|
;
|
|
FC_RESETFDC:
|
|
LD C,(IY+CFG_DOR)
|
|
LD HL,FDCBM
|
|
LD A,(HL)
|
|
AND _ZETA | _DIO3 | _RCSMC
|
|
JR NZ,FC_RESETFDC1
|
|
LD A,(HL)
|
|
AND _PCAT
|
|
JR NZ,FC_RESETFDC2
|
|
RET
|
|
FC_RESETFDC1: ; ZETA, DIO3, RCSMC
|
|
LD A,(FST_DOR)
|
|
PUSH AF
|
|
RES 7,A
|
|
OUT (C),A
|
|
CALL DELAY
|
|
POP AF
|
|
OUT (C),A
|
|
JR FC_RESETFDC3
|
|
FC_RESETFDC2: ; DIDE, N8, ZETA2, RCWDC, SMZ80, DYNO, EPFDC, MBC
|
|
LD A,0
|
|
OUT (C),A
|
|
LD A,(FST_DOR)
|
|
OUT (C),A
|
|
JR FC_RESETFDC3
|
|
FC_RESETFDC3:
|
|
LD DE,156 ; DELAY: 16us * 156 = 2.5ms
|
|
CALL VDELAY
|
|
|
|
RET
|
|
;
|
|
; PULSE TERMCT TO TERMINATE ANY ACTIVE EXECUTION PHASE
|
|
;
|
|
FC_PULSETC:
|
|
; V5.3, USE EOT=R TO R/W ONLY ONE SECTOR
|
|
;LD A,(FDCBM)
|
|
;AND _PCAT
|
|
;JR NZ,FC_PULSETC1
|
|
;; NOT DIDE, N8, ZETA2, RCSMC, SMZ80
|
|
;LD C,(IY+CFG_DOR)
|
|
;LD A,(FST_DOR)
|
|
;SET 0,A
|
|
;OUT (C),A
|
|
;RES 0,A
|
|
;OUT (C),A
|
|
;JR FC_PULSETC2
|
|
;FC_PULSETC1: ; DIDE, N8, ZETA2, RCWDC, SMZ80, DYNO, EPFDC, MBC
|
|
;LD C,(IY+CFG_TC)
|
|
;IN A,(C)
|
|
;JR FC_PULSETC2
|
|
;FC_PULSETC2:
|
|
RET
|
|
;
|
|
; SET FST_DOR FOR MOTOR CONTROL ON
|
|
;
|
|
FC_MOTORON:
|
|
LD HL,FDCBM
|
|
LD A,(HL)
|
|
AND _DIO
|
|
JR NZ,FC_MOTORON1
|
|
LD A,(HL)
|
|
AND _ZETA | _DIO3
|
|
JR NZ,FC_MOTORON2
|
|
LD A,(HL)
|
|
AND _PCAT
|
|
JR NZ,FC_MOTORON3
|
|
LD A,(HL)
|
|
AND _RCSMC
|
|
JR NZ,FC_MOTORON4
|
|
RET
|
|
FC_MOTORON1: ; DIO
|
|
LD HL,FST_DOR ; POINT TO FDC_DOR
|
|
RES 1,(HL) ; SET MOTOR ON
|
|
JR FC_MOTORON5
|
|
FC_MOTORON2: ; ZETA, DIO3
|
|
LD HL,FST_DOR ; POINT TO FDC_DOR
|
|
SET 1,(HL)
|
|
JR FC_MOTORON5
|
|
FC_MOTORON3: ; DIDE, N8, ZETA2, RCWDC, SMZ80, DYNO, EPFDC, MBC
|
|
LD HL,FST_DOR ; POINT TO FDC_DOR
|
|
LD A,(HL) ; START WITH CURRENT DOR
|
|
AND 11111100B ; GET RID OF ANY ACTIVE DS BITS
|
|
LD C,A ; SAVE IT FOR NOW
|
|
LD A,(FCD_DS) ; NOW GET CURRENT DS
|
|
LD B,A ; PUT IN B FOR LATER
|
|
OR C ; COMBINE WITH SAVED DOR
|
|
LD C,A ; RE-SAVE IT
|
|
INC B ; SET UP B AS LOOP COUNTER (DS + 1)
|
|
LD A,00001000B ; STARTING BIT PATTERN FOR MOTOR
|
|
FC_MOTORON3A:
|
|
RLA ; SHIFT LEFT
|
|
DJNZ FC_MOTORON3A ; DS TIMES
|
|
OR C ; COMBINE WITH SAVED
|
|
LD (HL),A ; COMMIT THE NEW VALUE TO FST_DOR
|
|
JR FC_MOTORON5
|
|
FC_MOTORON4: ; RCSMC
|
|
LD A,(FCD_DS) ; GET CURRENT DS
|
|
LD C,00000010B ; ASSUME MOTORA (BIT 1)
|
|
OR A ; TEST FOR DS 0
|
|
JR Z,FC_MOTORON4A ; IF SO, CONTINUE W/ MOTORA
|
|
LD C,00000100B ; OTHERWISE, MOTORB (BIT 2)
|
|
FC_MOTORON4A:
|
|
LD A,(FST_DOR) ; GET CURRENT DOR VALUE
|
|
OR C ; APPLY NEW MOTOR BIT
|
|
LD (FST_DOR),A ; COMMIT NEW VALUE
|
|
JR FC_MOTORON5
|
|
FC_MOTORON5:
|
|
CALL FC_SETDOR ; OUTPUT TO CONTROLLER
|
|
CALL LDELAY ; WAIT 1/2 SEC ON MOTOR START FOR SPIN-UP
|
|
LD A,(FDCBM)
|
|
AND _PCAT
|
|
RET Z
|
|
LD A,(FCD_DCR)
|
|
LD C,(IY+CFG_DCR)
|
|
OUT (C),A
|
|
RET
|
|
;
|
|
; SET FST_DOR FOR MOTOR CONTROL OFF
|
|
;
|
|
FC_MOTOROFF:
|
|
LD HL,FDCBM
|
|
LD A,(HL)
|
|
AND _DIO
|
|
JR NZ,FC_MOTOROFF1
|
|
LD A,(HL)
|
|
AND _ZETA | _DIO3
|
|
JR NZ,FC_MOTOROFF2
|
|
LD A,(HL)
|
|
AND _PCAT
|
|
JR NZ,FC_MOTOROFF3
|
|
LD A,(HL)
|
|
AND _RCSMC
|
|
JR NZ,FC_MOTOROFF4
|
|
RET
|
|
FC_MOTOROFF1: ; DIO
|
|
LD HL,FST_DOR ; POINT TO FDC_DOR
|
|
SET 1,(HL) ; SET MOTOR OFF
|
|
JR FC_MOTOROFF5
|
|
FC_MOTOROFF2: ; ZETA, DIO3
|
|
LD HL,FST_DOR ; POINT TO FDC_DOR
|
|
RES 1,(HL)
|
|
JR FC_MOTOROFF5
|
|
FC_MOTOROFF3: ; DIDE, N8, ZETA2, RCWDC, SMZ80, DYNO, EPFDC, MBC
|
|
LD HL,FST_DOR ; POINT TO FDC_DOR
|
|
LD A,DORC_INIT
|
|
LD (HL),A
|
|
JR FC_MOTOROFF5
|
|
FC_MOTOROFF4: ; RCSMC
|
|
LD HL,FST_DOR ; POINT TO FDC_DOR
|
|
RES 1,(HL) ; CLEAR MOTORA
|
|
RES 2,(HL) ; CLEAR MOTORB
|
|
JR FC_MOTOROFF5
|
|
|
|
FC_MOTOROFF5:
|
|
CALL FC_SETDOR ; OUTPUT TO CONTROLLER
|
|
RET
|
|
;
|
|
;===============================================================================
|
|
; FDC OPERATIONS
|
|
;===============================================================================
|
|
;
|
|
FOP:
|
|
;
|
|
; INITIALIZATION
|
|
;
|
|
LD A,0
|
|
LD (FRB_LEN),A
|
|
|
|
LD A,FRC_OK
|
|
LD (FST_RC),A
|
|
|
|
LD B,0 ; B IS LOOP COUNTER
|
|
LD C,(IY+CFG_MSR) ; SET C TO MSR PORT
|
|
FOP_CLR1:
|
|
CALL DELAY ; FDC MAY TAKE UP TO 12us TO UPDATE MSR
|
|
IN A,(C) ; GET STATUS
|
|
LD (FST_MSR),A ; SAVE IT FOR POTENTIAL LATER DIAGNOSIS
|
|
AND 0C0H ; ISOLATE HIGH NIBBLE, RQM/DIO/EXM/CB
|
|
CP 0C0H ; LOOKING FOR RQM=1, DIO=1, BYTES PENDING
|
|
JP NZ,FOP_CMD1 ; NO BYTES PENDING, GO TO NEXT PHASE
|
|
INC C ; SWITCH TO DATA PORT
|
|
IN A,(C) ; GET THE PENDING BYTE AND DISCARD
|
|
DEC C ; SWITCH BACK TO MSR PORT
|
|
DJNZ FOP_CLR1 ; KEEP CHECKING TILL COUNTER EXHAUSTER
|
|
JP FOP_TOFDCRDY ; OTHERWISE, TIMEOUT
|
|
;
|
|
; SEND COMMAND
|
|
;
|
|
FOP_CMD1:
|
|
LD HL,FCP_BUF
|
|
LD A,(FCP_BUFLEN)
|
|
LD D,A ; D = CMD BYTES TO SEND
|
|
|
|
FOP_CMD2: ; START OF LOOP TO SEND NEXT BYTE
|
|
LD B,0 ; B IS LOOP COUNTER
|
|
|
|
FOP_CMD4: ; START OF STATUS LOOP, WAIT FOR FDC TO BE READY FOR BYTE
|
|
CALL DELAY ; FDC MAY TAKE UP TO 12us TO UPDATE MSR
|
|
; TYPICAL MSR TRANSITIONS: <ENTRY> 80 <AFTER FIRST BYTE> 10 90 <AFTER SECOND/SUBSEQUENT BYTES> 90
|
|
LD C,(IY+CFG_MSR) ; SET C TO MSR PORT
|
|
IN A,(C) ; READ MAIN STATUS REGISTER
|
|
LD (FST_MSR),A ; SAVE IT FOR POTENTIAL LATER DIAGNOSIS
|
|
AND 0C0H ; ISOLATE RQM/DIO
|
|
CP 080H ; LOOKING FOR RQM=1, DIO=0 (FDC READY FOR A BYTE)
|
|
JP Z,FOP_CMD6 ; GOOD, GO TO SEND BYTE
|
|
CP 0C0H ; HMMMM... RQM=1 & DIO=1, FDC WANTS TO SEND US DATA, UNEXPECTED
|
|
JP Z,FOP_RES ; GO IMMEDIATELY TO RESULTS???
|
|
DJNZ FOP_CMD4 ; LOOP TILL COUNTER EXHAUSTED
|
|
JP FOP_TOSNDCMD ; COUNTER EXHAUSTED, TIMEOUT / EXIT
|
|
|
|
FOP_CMD6: ; SEND NEXT BYTE
|
|
LD A,(HL) ; POINT TO NEXT BYTE TO SEND
|
|
LD C,(IY+CFG_DATA) ; SET C TO DATA PORT
|
|
OUT (C),A ; PUSH IT TO FDC
|
|
INC HL ; INCREMENT POINTER FOR NEXT TIME
|
|
DEC D ; DECREMENT NUM BYTES LEFT TO SEND
|
|
JP NZ,FOP_CMD2 ; DO NEXT BYTE
|
|
|
|
;
|
|
; EXECUTION PHASE
|
|
;
|
|
FOP_X1:
|
|
LD HL,(FXP_XR) ; LOAD THE EXECUTION ROUTINE ADDRESS
|
|
CALL JPHL ; CALL INDIRECTLY VIA HL
|
|
|
|
LD A,(FST_RC) ; CURRENT RESULT CODE
|
|
;CALL PC_SPACE
|
|
;CALL PRTHEXBYTE
|
|
CP FRC_OK ; ERROR?
|
|
RET NZ ; IF SO, ALL DONE
|
|
|
|
; JP FOP_RES ; CONTINUE WITH GETRESULTS
|
|
|
|
;
|
|
; RESULTS PHASE
|
|
;
|
|
FOP_RES:
|
|
LD B,0 ; B = BYTES RECEIVED
|
|
LD HL,FRB_LEN ; POINT TO BUFFER LENGTH
|
|
LD (HL),B ; UPDATE NUMBER OF BYTES RECEIVED
|
|
LD HL,FRB ; POINT TO RECEIVE BUFFER
|
|
|
|
FOP_RES0:
|
|
LD DE,0 ; DE IS LOOP COUNTER
|
|
LD C,(IY+CFG_MSR) ; SET C TO MSR PORT
|
|
|
|
FOP_RES1:
|
|
CALL DELAY ; FDC MAY TAKE UP TO 12us TO UPDATE MSR
|
|
IN A,(C) ; READ MAIN STATUS REGISTER
|
|
;CALL PC_SPACE
|
|
;CALL PRTHEXBYTE
|
|
LD (FST_MSR),A ; SAVE IT FOR POTENTIAL LATER DIAGNOSIS
|
|
AND $F0 ; REMOVE SEEK BITS
|
|
CP $D0 ; LOOKING FOR RQM=1, DIO=1, BUSY=1 (FDC BYTE PENDING)
|
|
JR Z,FOP_RES2 ; GOOD, GO TO RECEIVE BYTE
|
|
CP $80 ; DONE?
|
|
JR Z,FOP_EVAL ; IF SO, GO TO EVAL
|
|
DEC DE
|
|
LD A,D
|
|
OR E
|
|
JP NZ,FOP_RES1
|
|
JP FOP_TOGETRES ; OTHERWISE TIMEOUT ERROR
|
|
|
|
FOP_RES2: ; PROCESS NEXT PENDING BYTE
|
|
LD A,FRB_SIZ ; GET BUF SIZE
|
|
CP B ; REACHED MAX?
|
|
JP Z,FOP_BUFMAX ; HANDLE BUF MAX/EXIT
|
|
INC C ; SWITCH TO DATA PORT
|
|
IN A,(C) ; GET THE BYTE
|
|
DEC C ; SWITCH TO MSR PORT
|
|
LD (HL),A ; SAVE VALUE
|
|
INC HL ; INCREMENT BUF POS
|
|
INC B ; INCREMENT BYTES RECEIVED
|
|
PUSH HL ; SAVE HL
|
|
LD HL,FRB_LEN ; POINT TO BUFFER LENGTH
|
|
LD (HL),B ; UPDATE NUMBER OF BYTES RECEIVED
|
|
POP HL ; RESTORE HL
|
|
JR FOP_RES0 ; CONTINUE READ LOOP
|
|
|
|
;
|
|
; EXIT POINTS
|
|
;
|
|
FOP_NOTIMPL:
|
|
LD A,FRC_NOTIMPL
|
|
JP FOP_ERR
|
|
|
|
FOP_CMDERR:
|
|
LD A,FRC_CMDERR
|
|
JP FOP_ERR
|
|
|
|
FOP_ERROR:
|
|
LD A,FRC_ERROR
|
|
JP FOP_ERR
|
|
|
|
FOP_ABORT:
|
|
LD A,FRC_ABORT
|
|
JP FOP_ERR
|
|
|
|
FOP_BUFMAX:
|
|
LD A,FRC_BUFMAX
|
|
JP FOP_ERR
|
|
|
|
FOP_TOFDCRDY:
|
|
LD A,FRC_TOFDCRDY
|
|
JP FOP_ERR
|
|
|
|
FOP_TOSNDCMD:
|
|
LD A,FRC_TOSNDCMD
|
|
JP FOP_ERR
|
|
|
|
FOP_TOGETRES:
|
|
LD A,FRC_TOGETRES
|
|
JP FOP_ERR
|
|
|
|
FOP_TOEXEC:
|
|
LD A,FRC_TOEXEC
|
|
JP FOP_ERR
|
|
|
|
FOP_ERR:
|
|
LD (FST_RC),A
|
|
|
|
FOP_EVAL:
|
|
LD A,(FCP_CMD)
|
|
; DRVSTAT IS WEIRD, HAS ONLY ST3, NOTHING TO EVAL
|
|
CP CMD_DRVSTAT
|
|
JP Z,FOP_EXIT
|
|
; DO WE HAVE ST0?
|
|
LD A,(FRB_LEN)
|
|
CP 1
|
|
JP M,FOP_EXIT
|
|
|
|
FOP_EVALST0:
|
|
LD A,(FRB_ST0)
|
|
AND 11000000B
|
|
CP 01000000B ; ABTERM
|
|
JR Z,FOP_ABTERM
|
|
CP 10000000B ; INVCMD
|
|
JR Z,FOP_INVCMD
|
|
CP 11000000B ; DSKCHG
|
|
JR Z,FOP_DSKCHG
|
|
JR FOP_EXIT
|
|
|
|
FOP_ABTERM:
|
|
; SENSEINT DOES NOT USE ST1
|
|
LD A,(FCP_CMD)
|
|
CP CMD_SENSEINT
|
|
JR Z,FOP_ABTERM1
|
|
; DO WE HAVE ST1?
|
|
LD A,(FRB_LEN)
|
|
CP 2
|
|
JP M,FOP_ABTERM1
|
|
JR FOP_EVALST1
|
|
FOP_ABTERM1: ; NO FURTHER DATA, SET FST TO ABTERM
|
|
LD A,FRC_ABTERM
|
|
JP FOP_SETFST
|
|
|
|
FOP_INVCMD:
|
|
LD A,FRC_INVCMD
|
|
JP FOP_SETFST
|
|
|
|
FOP_DSKCHG:
|
|
LD A,FRC_DSKCHG
|
|
JP FOP_SETFST
|
|
|
|
FOP_EVALST1:
|
|
LD A,(FRB_ST1)
|
|
BIT 7,A
|
|
JP NZ,FOP_ENDCYL
|
|
BIT 5,A
|
|
JP NZ,FOP_DATAERR
|
|
BIT 4,A
|
|
JP NZ,FOP_OVERRUN
|
|
BIT 2,A
|
|
JP NZ,FOP_NODATA
|
|
BIT 1,A
|
|
JP NZ,FOP_NOTWRIT
|
|
BIT 0,A
|
|
JP NZ,FOP_MISADR
|
|
JP FOP_EXIT
|
|
|
|
FOP_ENDCYL:
|
|
; V5.3, USE EOT=R TO R/W ONLY ONE SECTOR
|
|
;LD A,FRC_ENDCYL
|
|
;JP FOP_SETFST
|
|
JP FOP_EXIT
|
|
|
|
FOP_DATAERR:
|
|
LD A,FRC_DATAERR
|
|
JP FOP_SETFST
|
|
|
|
FOP_OVERRUN:
|
|
LD A,FRC_OVERRUN
|
|
JP FOP_SETFST
|
|
|
|
FOP_NODATA:
|
|
LD A,FRC_NODATA
|
|
JP FOP_SETFST
|
|
|
|
FOP_NOTWRIT:
|
|
LD A,FRC_NOTWRIT
|
|
JP FOP_SETFST
|
|
|
|
FOP_MISADR:
|
|
LD A,FRC_MISADR
|
|
JP FOP_SETFST
|
|
|
|
FOP_SETFST:
|
|
LD (FST_RC),A
|
|
|
|
FOP_EXIT:
|
|
RET
|
|
|
|
;
|
|
; EXECUTION ROUTINES
|
|
;
|
|
FXR_READID:
|
|
JP FXRX
|
|
|
|
FXR_READ:
|
|
LD HL,BUFFER ; POINT TO SECTOR BUFFER START
|
|
LD DE,(FCD_SECSZ)
|
|
|
|
LD A,(DCD_MD) ; FIX: SHOULD NOT BE USING DCD HERE
|
|
CP MD_POLL
|
|
JP Z,FXRR
|
|
CP MD_INT
|
|
JP Z,IFXRR
|
|
CP MD_INTFAST
|
|
JP Z,FFXRR
|
|
CP MD_INTWAIT
|
|
JP Z,WFXRR
|
|
CP MD_DRQWAIT
|
|
JP Z,WFXRR
|
|
JP FXR_NOTIMPL
|
|
|
|
FXR_WRITE:
|
|
LD HL,BUFFER ; POINT TO SECTOR BUFFER START
|
|
LD DE,(FCD_SECSZ)
|
|
|
|
LD A,(DCD_MD) ; FIX: SHOULD NOT BE USING DCD HERE
|
|
CP MD_POLL
|
|
JP Z,FXRW
|
|
CP MD_INT
|
|
JP Z,IFXRW
|
|
CP MD_INTFAST
|
|
JP Z,FFXRW
|
|
CP MD_INTWAIT
|
|
JP Z,WFXRW
|
|
CP MD_DRQWAIT
|
|
JP Z,WFXRW
|
|
JP FXR_NOTIMPL
|
|
|
|
FXR_FMTTRK:
|
|
LD HL,FXP_BUF ; POINT TO BUFFER START
|
|
LD D,0
|
|
LD A,(FXP_BUFLEN) ; GET BYTE COUNT TO WRITE
|
|
LD E,A
|
|
|
|
LD A,(DCD_MD) ; FIX: SHOULD NOT BE USING DCD HERE
|
|
CP MD_POLL
|
|
JP Z,FXRW
|
|
CP MD_INT
|
|
JP Z,IFXRW
|
|
CP MD_INTFAST
|
|
JP Z,IFXRW ; CAN'T USE FFXRW BECAUSE IT IS NOT 512 BYTES
|
|
CP MD_INTWAIT
|
|
JP Z,WFXRW
|
|
CP MD_DRQWAIT
|
|
JP Z,WFXRW
|
|
JP FXR_NOTIMPL
|
|
|
|
FXR_NOTIMPL:
|
|
FXR_READDEL:
|
|
FXR_WRITEDEL:
|
|
FXR_READTRK:
|
|
FXR_SCANEQ:
|
|
FXR_SCANLOEQ:
|
|
FXR_SCANHIEQ:
|
|
LD A,FRC_NOTIMPL
|
|
LD (FST_RC),A
|
|
; FALL THROUGH TO RET BELOW
|
|
FXR_NOP:
|
|
FXR_RECAL:
|
|
FXR_SENSEINT:
|
|
FXR_SPECIFY:
|
|
FXR_DRVSTAT:
|
|
FXR_SEEK:
|
|
FXR_VERSION:
|
|
RET
|
|
;
|
|
; NULL EXECUTION, NO DATA TO READ/WRITE (USED BY READID)
|
|
;
|
|
FXRX:
|
|
LD DE,1000H ; DE IS LOOP COUNTER, 4096 ITERATIONS OF 25ms
|
|
LD C,(IY+CFG_MSR) ; SET C TO MSR PORT
|
|
FXRX1:
|
|
CALL DELAY
|
|
IN A,(C) ; GET MSR
|
|
;AND 0E0H ; ISOLATE RQM/DIO/EXM
|
|
CP $D0 ; WE WANT RQM=1,DIO=1,EXM=0 (READY TO READ A BYTE W/ EXEC INACTIVE)
|
|
JP Z,FXR_END ; GOT IT, EXIT CLEAN
|
|
DEC DE ; DECREMENT COUNTER (16 BIT)
|
|
LD A,D ; CHECK FOR ZERO
|
|
OR E ; "
|
|
JR NZ,FXRX1 ; NOT ZERO YET, KEEP CHECKING
|
|
JP FXR_TO ; OTHERWISE, TIMEOUT ERROR
|
|
RET
|
|
|
|
;
|
|
; READ DATA
|
|
;
|
|
FXRR: LD A,E ; LOW BYTE OF COUNT TO ACCUM
|
|
OR A ; TEST FOR ZERO
|
|
JR Z,FXRR1 ; IF ZERO, DO NOT ADJUST ITERATIONS
|
|
INC D ; OTHERWISE, ITERATIONS IS ONE MORE THAN HIGH BYTE
|
|
FXRR1: LD B,E ; LOW BYTE OF COUNT TO B
|
|
LD A,D ; HIGH BYTE OF COUNT
|
|
LD (FXP_ITER),A ; ... IS ITERATION COUNT
|
|
LD A,(CPUSPD) ; CPU SPEED SCALER
|
|
LD (FXP_TO),A ; SAVE IT AS OUTER LOOP TIMEOUT
|
|
LD IX,FXP_TO ; (IX) IS FXP_TO, (IX+1) IS FCP_ITER
|
|
LD C,(IY+CFG_DATA) ; SET C TO DATA PORT
|
|
LD DE,0
|
|
DI ; DISABLE INTERRUPTS TO AVOID OVERRUN
|
|
FXRR2: DEC C ; [04] SET C TO MSR PORT
|
|
FXRR3: LD DE,0 ; [10] TIMEOUT COUNTER
|
|
FXRR4: IN A,(C) ; [12] GET MSR
|
|
CP $F0 ; [07] BYTE READY?
|
|
JR Z,FXRR5 ; [12/7] GET IT
|
|
;LD (FST_MSR),A ; [13] *DEBUG* SAVE MSR FOR LATER
|
|
DEC E ; [04] DEC LSB OF INNER TIMEOUT COUNTER
|
|
JR NZ,FXRR4 ; [12/7] LOOP IF LSB IS NOT EXHAUSTED
|
|
CP $D0 ; [07] IF RQM=1, DIO=1, EXM=0, CB=1, EXECUTION ABORTED
|
|
JP Z,FXR_ABORT ; [10] IF NOT SET, EXECUTION ABORTED
|
|
DEC D ; [04] DEC MSB OF INNER TIMEOUT COUNTER
|
|
JR NZ,FXRR4 ; [12/7] LOOP IF MSB IS NOT EXHAUSTED
|
|
DEC (IX) ; [23] DECREMENT OUTER LOOP COUNTER
|
|
JR NZ,FXRR3 ; [12/7] LOOP IF NOT EXHAUSTED
|
|
JP FXR_TO ; [10] OTHERWISE, HANDLE TIMEOUT
|
|
FXRR5: INC C ; [04] POINT TO DATA PORT
|
|
INI ; [16] (HL) := (C), HL++, B--
|
|
JR NZ,FXRR2 ; [12/7] LOOP
|
|
DEC (IX+1) ; [23] DECREMENT ITERATION COUNT
|
|
JR NZ,FXRR2 ; [12] IF MORE ITERATIONS, LOOP
|
|
JP FXR_END ; [10] ELSE DONE
|
|
|
|
;
|
|
; INT READ DATA - SAFE VERSION
|
|
; HANDLES FDC ERRORS, BUT NO TIMEOUT
|
|
;
|
|
; AVOID RETURN FROM HALT IN PROBLEMATIC ADDRESS RANGE XX30-XX3F!!!
|
|
.IF ((($ & 0F0H) == 20H) | (($ & 0F0H) == 30H))
|
|
.FILL (($ & 0FF00H) + 40H) - $
|
|
; .ORG (($ & 0FF00H) + 40H)
|
|
.ENDIF
|
|
;
|
|
IFXRR:
|
|
DI
|
|
LD C,(IY+CFG_MSR) ; SET C TO MSR PORT
|
|
IFXRR2:
|
|
EI
|
|
IFXRRX .EQU $ - IFXRR
|
|
HALT
|
|
IN A,(C)
|
|
BIT 5,A
|
|
JP Z,FXR_ABORT
|
|
INC C ; SWITCH C TO DATA PORT
|
|
INI
|
|
DEC C ; SWITCH C BACK TO MSR PORT
|
|
DEC DE
|
|
LD A,E
|
|
OR D
|
|
JP NZ,IFXRR2
|
|
JP FXR_END
|
|
;
|
|
; INT READ DATA - FAST VERSION
|
|
; FIXED SECTOR SIZE OF 512 BYTES
|
|
; HANGS ON FDC ERRORS, NO TIMEOUT
|
|
;
|
|
; AVOID RETURN FROM HALT IN PROBLEMATIC ADDRESS RANGE XX30-XX3F!!!
|
|
.IF ((($ & 0F0H) == 20H) | (($ & 0F0H) == 30H))
|
|
.FILL (($ & 0FF00H) + 40H) - $
|
|
; .ORG (($ & 0FF00H) + 40H)
|
|
.ENDIF
|
|
;
|
|
FFXRR:
|
|
DI
|
|
LD C,(IY+CFG_DATA) ; SET C TO DATA PORT FOR INI
|
|
FFXRR2 EI
|
|
HALT
|
|
FFXRRX1 .EQU $ - FFXRR
|
|
INI
|
|
JP NZ,FFXRR2
|
|
FFXRR3 EI
|
|
HALT
|
|
FFXRRX2 .EQU $ - FFXRR
|
|
INI
|
|
JP NZ,FFXRR3
|
|
JP FXR_END
|
|
;
|
|
; WAIT READ DATA
|
|
; HANGS ON FDC ERRORS, NO TIMEOUT
|
|
;
|
|
WFXRR:
|
|
DI
|
|
LD C,(IY+CFG_DMA)
|
|
WFXRR2:
|
|
INI ; GET PENDING BYTE
|
|
DEC DE ; DECREMENT BYTE COUNT
|
|
LD A,D
|
|
OR E
|
|
JP NZ,WFXRR2 ; IF NOT ZERO, REPEAT LOOP
|
|
JP FXR_END ; CLEAN EXIT
|
|
|
|
;
|
|
; WRITE DATA
|
|
;
|
|
FXRW: LD A,E ; LOW BYTE OF COUNT TO ACCUM
|
|
OR A ; TEST FOR ZERO
|
|
JR Z,FXRW1 ; IF ZERO, DO NOT ADJUST ITERATIONS
|
|
INC D ; OTHERWISE, ITERATIONS IS ONE MORE THAN HIGH BYTE
|
|
FXRW1: LD B,E ; LOW BYTE OF COUNT TO B
|
|
LD A,D ; HIGH BYTE OF COUNT
|
|
LD (FXP_ITER),A ; ... IS ITERATION COUNT
|
|
LD A,(CPUSPD) ; CPU SPEED SCALER
|
|
LD (FXP_TO),A ; SAVE IT AS OUTER LOOP TIMEOUT
|
|
LD IX,FXP_TO ; (IX) IS FXP_TO, (IX+1) IS FCP_ITER
|
|
LD C,(IY+CFG_DATA) ; SET C TO DATA PORT
|
|
LD DE,0
|
|
DI ; DISABLE INTERRUPTS TO AVOID OVERRUN
|
|
FXRW2: DEC C ; [04] SET C TO MSR PORT
|
|
FXRW3: LD DE,0 ; [10] TIMEOUT COUNTER
|
|
FXRW4: IN A,(C) ; [12] GET MSR
|
|
CP $B0 ; [07] BYTE READY?
|
|
JR Z,FXRW5 ; [12/7] GET IT
|
|
;LD (FST_MSR),A ; [13] *DEBUG* SAVE MSR FOR LATER
|
|
DEC E ; [04] DEC LSB OF INNER TIMEOUT COUNTER
|
|
JR NZ,FXRW4 ; [12/7] LOOP IF LSB IS NOT EXHAUSTED
|
|
CP $D0 ; [07] IF RQM=1, DIO=1, EXM=0, CB=1, EXECUTION ABORTED
|
|
JP Z,FXR_ABORT ; [10] IF NOT SET, EXECUTION ABORTED
|
|
DEC D ; [04] DEC MSB OF INNER TIMEOUT COUNTER
|
|
JR NZ,FXRW4 ; [12/7] LOOP IF MSB IS NOT EXHAUSTED
|
|
DEC (IX) ; [23] DECREMENT OUTER LOOP COUNTER
|
|
JR NZ,FXRW3 ; [12/7] LOOP IF NOT EXHAUSTED
|
|
JP FXR_TO ; [10] OTHERWISE, HANDLE TIMEOUT
|
|
FXRW5: INC C ; [04] POINT TO DATA PORT
|
|
OUTI ; [16] (C) := (HL), HL++, B--
|
|
JR NZ,FXRW2 ; [12/7] LOOP
|
|
DEC (IX+1) ; [23] DECREMENT ITERATION COUNT
|
|
JR NZ,FXRW2 ; [12] IF MORE ITERATIONS, GO DO IT
|
|
JP FXR_END ; [10] ELSE DONE
|
|
|
|
|
|
|
|
;
|
|
; INT WRITE DATA - SAFE VERSION
|
|
; HANDLES FDC ERRORS, BUT NO TIMEOUT
|
|
;
|
|
; AVOID RETURN FROM HALT IN PROBLEMATIC ADDRESS RANGE XX30-XX3F!!!
|
|
.IF ((($ & 0F0H) == 20H) | (($ & 0F0H) == 30H))
|
|
.FILL (($ & 0FF00H) + 40H) - $
|
|
; .ORG (($ & 0FF00H) + 40H)
|
|
.ENDIF
|
|
;
|
|
IFXRW:
|
|
DI
|
|
LD C,(IY+CFG_MSR) ; SET C TO MSR PORT
|
|
IFXRW2: EI
|
|
HALT
|
|
IN A,(C)
|
|
BIT 5,A
|
|
JP Z,FXR_ABORT
|
|
INC C ; SWITCH TO DATA PORT
|
|
OUTI
|
|
DEC C ; SWITCH BACK TO MSR PORT
|
|
DEC DE
|
|
LD A,E
|
|
OR D
|
|
JP NZ,IFXRW2
|
|
JP FXR_END
|
|
;
|
|
; INT WRITE DATA - FAST VERSION
|
|
; FIXED SECTOR SIZE OF 512 BYTES
|
|
; HANGS ON FDC ERRORS, NO TIMEOUT
|
|
;
|
|
; AVOID RETURN FROM HALT IN PROBLEMATIC ADDRESS RANGE XX30-XX3F!!!
|
|
.IF ((($ & 0F0H) == 20H) | (($ & 0F0H) == 30H))
|
|
.FILL (($ & 0FF00H) + 40H) - $
|
|
; .ORG (($ & 0FF00H) + 40H)
|
|
.ENDIF
|
|
;
|
|
FFXRW:
|
|
DI
|
|
LD C,(IY+CFG_DATA) ; SET C TO DATA PORT
|
|
FFXRW2 EI
|
|
HALT
|
|
OUTI
|
|
JP NZ,FFXRW2
|
|
FFXRW3 EI
|
|
HALT
|
|
OUTI
|
|
JP NZ,FFXRW3
|
|
JP FXR_END
|
|
;
|
|
; WAIT WRITE DATA
|
|
; HANGS ON FDC ERRORS, NO TIMEOUT
|
|
;
|
|
WFXRW:
|
|
DI
|
|
LD C,(IY+CFG_DMA)
|
|
WFXRW2:
|
|
OUTI ; WRITE IT 16ts
|
|
DEC DE ; DECREMENT BYTE COUNT 6ts
|
|
LD A,D ; 4ts
|
|
OR E ; 4ts
|
|
JP NZ,WFXRW2 ; IF NOT ZERO, REPEAT LOOP 10ts = 40
|
|
JP FXR_END ; CLEAN EXIT
|
|
|
|
;
|
|
; COMMON COMPLETION CODE FOR ALL EXECUTION ROUTINES
|
|
;
|
|
|
|
FXR_TO:
|
|
; SAVE CURRENT MSR VALUE
|
|
;LD C,(IY+CFG_MSR) ; SET C TO MSR PORT
|
|
;IN A,(C)
|
|
LD (FST_MSR),A
|
|
; SET ERROR AND GET OUT W/O PULSING TC
|
|
LD A,FRC_TOEXEC
|
|
LD (FST_RC),A
|
|
JR FXR_END2
|
|
|
|
FXR_ABORT:
|
|
; SAVE CURRENT MSR VALUE
|
|
;LD C,(IY+CFG_MSR) ; SET C TO MSR PORT
|
|
;IN A,(C)
|
|
LD (FST_MSR),A
|
|
; LET RESULTS PHASE HANDLE ERROR, DO NOT PULSE TC, COMMAND ALREADY TERMINATED
|
|
;LD A,FRC_ABORT
|
|
;LD (FST_RC),A
|
|
JR FXR_END2
|
|
|
|
FXR_END:
|
|
; SAVE CURRENT MSR VALUE
|
|
;LD C,(IY+CFG_MSR) ; SET C TO MSR PORT
|
|
;IN A,(C)
|
|
LD (FST_MSR),A
|
|
; DO NOT PULSE TC AT END OF FORMAT OR READID, THOSE COMMANDS SELF-TERMINATE
|
|
;LD A,(FCP_CMD)
|
|
;CP CMD_FMTTRK
|
|
;JR Z,FXR_END2
|
|
;CP CMD_READID
|
|
;JR Z,FXR_END2
|
|
|
|
CALL FC_PULSETC
|
|
|
|
FXR_END2:
|
|
#IF 0
|
|
LD (FXP_A),A
|
|
LD (FXP_BC),BC
|
|
LD (FXP_DE),DE
|
|
LD (FXP_HL),HL
|
|
|
|
CALL FXR_DUMP
|
|
#ENDIF
|
|
|
|
EI ; I/O FINISHED, INTS BACK ON
|
|
RET
|
|
|
|
;
|
|
;===============================================================================
|
|
; COMMAND PROCESSING STATUS DISPLAY
|
|
;===============================================================================
|
|
;
|
|
; PRINT STATUS
|
|
;
|
|
FC_PRTFST:
|
|
PUSH AF
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
LD A,(FST_RC) ; A GETS FST_RC
|
|
LD B,FSST_COUNT ; B GETS TABLE ENTRY COUNT
|
|
LD HL,FSST
|
|
LD DE,FSST_ENTSIZ ; TABLE ENTRY LENGTH
|
|
|
|
FC_PRTFST0: ; START OF LOOP
|
|
LD C,(HL)
|
|
CP C
|
|
JP Z,FC_PRTFST1 ; FOUND CODE
|
|
|
|
ADD HL,DE ; POINT TO NEXT ENTRY
|
|
DJNZ FC_PRTFST0 ; CHECK NEXT ENTRY TILL COUNT IS ZERO
|
|
|
|
; NO MATCHING ENTRY, PRINT THE HEX VALUE
|
|
CALL PC_SPACE
|
|
CALL PC_LBKT
|
|
CALL PRTHEXBYTE
|
|
CALL PC_RBKT
|
|
JP FC_PRTFSTX
|
|
|
|
FC_PRTFST1: ; ENTRY FOUND, PRINT IT
|
|
CALL PC_SPACE
|
|
INC HL
|
|
LD E,(HL)
|
|
INC HL
|
|
LD D,(HL)
|
|
CALL PC_LBKT
|
|
CALL WRITESTR
|
|
CALL PC_RBKT
|
|
|
|
FC_PRTFSTX:
|
|
POP HL
|
|
POP DE
|
|
POP BC
|
|
POP AF
|
|
RET
|
|
;
|
|
; PRINT COMMAND
|
|
;
|
|
FC_PRTCMD:
|
|
PUSH AF
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
LD A,(FCP_CMD) ; A GETS THE COMMAND CODE
|
|
LD B,FCT_COUNT ; B GETS TABLE ENTRY COUNT
|
|
LD HL,FCT
|
|
LD DE,FCT_ENTSIZ ; TABLE ENTRY LENGTH
|
|
|
|
FCPC_LOOP: ; START OF LOOP
|
|
LD C,(HL)
|
|
CP C
|
|
JP Z,FCPC_MATCH ; FOUND CODE
|
|
|
|
ADD HL,DE ; POINT TO NEXT ENTRY
|
|
DJNZ FCPC_LOOP ; CHECK NEXT ENTRY TILL COUNT IS ZERO
|
|
|
|
; NO MATCHING ENTRY, PRINT THE HEX VALUE
|
|
CALL PC_SPACE
|
|
CALL PC_LBKT
|
|
CALL PRTHEXBYTE
|
|
CALL PC_RBKT
|
|
JP FCPC_EXIT
|
|
|
|
FCPC_MATCH: ; ENTRY FOUND, PRINT IT
|
|
INC HL
|
|
LD E,(HL)
|
|
INC HL
|
|
LD D,(HL)
|
|
CALL WRITESTR
|
|
|
|
FCPC_EXIT:
|
|
POP HL
|
|
POP DE
|
|
POP BC
|
|
POP AF
|
|
RET
|
|
;
|
|
; PRINT RESULTS
|
|
;
|
|
FC_PRTRESULTS:
|
|
; IF TRACE IS SET, FORCE PRINT RESULTS
|
|
LD A,(FCD_TRACE)
|
|
OR A
|
|
JP NZ,FCPR2
|
|
|
|
; IF RC=OK, GET OUT, NOTHING TO PRINT
|
|
LD A,(FST_RC)
|
|
CP FRC_OK
|
|
RET Z
|
|
|
|
; SPECIAL CASE, DON'T PRINT IF SENSEINT & INVCMD/DSK CHG/ABTERM
|
|
LD A,(FCP_CMD)
|
|
CP CMD_SENSEINT
|
|
JP NZ,FCPR2
|
|
|
|
LD A,(FST_RC)
|
|
CP FRC_INVCMD
|
|
JP Z,FCPR_EXIT
|
|
CP FRC_DSKCHG
|
|
JP Z,FCPR_EXIT
|
|
CP FRC_ABTERM
|
|
JP Z,FCPR_EXIT
|
|
JP FCPR_EXIT
|
|
|
|
FCPR2:
|
|
CALL NEWLINE
|
|
|
|
CALL FC_PRTCMD
|
|
CALL PC_COLON
|
|
|
|
LD A,(FCP_BUFLEN)
|
|
LD DE,FCP_BUF
|
|
CALL PRTHEXBUF
|
|
|
|
LD DE,STR_ARROW
|
|
CALL WRITESTR
|
|
|
|
LD A,(FRB_LEN)
|
|
LD DE,FRB
|
|
CALL PRTHEXBUF
|
|
|
|
LD A,(FDCBM)
|
|
AND _ZETA | _DIO3
|
|
JR Z,FCPR3
|
|
LD DE,STR_DSKCHG
|
|
CALL WRITESTR
|
|
LD C,(IY+CFG_DIR)
|
|
IN A,(C)
|
|
AND 01H
|
|
CALL PRTHEXBYTE
|
|
|
|
FCPR3:
|
|
LD A,(FST_RC)
|
|
CALL FC_PRTFST
|
|
|
|
FCPR_EXIT:
|
|
RET
|
|
;
|
|
; DUMP EXECUTION INFO
|
|
;
|
|
FXR_DUMP:
|
|
CALL NEWLINE
|
|
LD DE,STR_OP
|
|
CALL WRITESTR
|
|
CALL PC_COLON
|
|
LD DE,STR_MSR
|
|
CALL WRITESTR
|
|
LD A,(FST_MSR)
|
|
CALL PRTHEXBYTE
|
|
|
|
LD DE,STR_A
|
|
CALL WRITESTR
|
|
LD A,(FXP_A)
|
|
CALL PRTHEXBYTE
|
|
|
|
LD DE,STR_BC
|
|
CALL WRITESTR
|
|
LD BC,(FXP_BC)
|
|
LD A,B
|
|
CALL PRTHEXBYTE
|
|
LD A,C
|
|
CALL PRTHEXBYTE
|
|
|
|
LD DE,STR_DE
|
|
CALL WRITESTR
|
|
LD BC,(FXP_DE)
|
|
LD A,B
|
|
CALL PRTHEXBYTE
|
|
LD A,C
|
|
CALL PRTHEXBYTE
|
|
|
|
LD DE,STR_HL
|
|
CALL WRITESTR
|
|
LD BC,(FXP_HL)
|
|
LD A,B
|
|
CALL PRTHEXBYTE
|
|
LD A,C
|
|
CALL PRTHEXBYTE
|
|
|
|
LD DE,STR_ITER
|
|
CALL WRITESTR
|
|
LD A,(FXP_ITER)
|
|
CALL PRTHEXBYTE
|
|
|
|
LD DE,STR_TO
|
|
CALL WRITESTR
|
|
LD A,(FXP_TO)
|
|
CALL PRTHEXBYTE
|
|
|
|
RET
|
|
;
|
|
; DOR BITS (3AH)
|
|
;
|
|
; DISKIO 250KBPS 500KBPS
|
|
; ------- ------- -------
|
|
;D7 /DC/RDY 1 (N/A) 1 (N/A)
|
|
;D6 /REDWC (DENSITY) 0 (DD) 1 (HD)
|
|
;D5 P0* (PRECOMP BIT 0) 1 \ 0 \
|
|
;D4 P1* (PRECOMP BIT 1) 0 (125NS) 1 (125NS)
|
|
;D3 P2* (PRECOMP BIT 2) 0 / 0 /
|
|
;D2 MINI (BITRATE) 1 (250KBPS) 0 (500KBPS)
|
|
;D1 /MOTOR (ACTIVE LO) 1 (OFF) 1 (OFF)
|
|
;D0 TC (TERMINAL COUNT) 0 (OFF) 0 (OFF)
|
|
;
|
|
; *NOTE: FOR 9229 DATA SEPARATOR USED IN DISKIO, VALUE OF PRECOMP BITS CHANGES WITH MINI
|
|
; IF MINI=1 (250KBPS), USE 001 FOR 125NS PRECOMP, IF MINI=0, USE 010 FOR 125NS PRECOMP
|
|
;
|
|
DORA_BR250 .EQU 10100110B ; 250KBPS
|
|
DORA_BR500 .EQU 11010010B ; 500KBPS
|
|
;
|
|
DORA_INIT .EQU DORA_BR250
|
|
;
|
|
; ZETA/DISKIO3 250KBPS 500KBPS
|
|
; ------------ ------- -------
|
|
;D7 /FDC_RST 1 (RUN) 1 (RUN)
|
|
;D6 DENSEL 1 (DD) 0 (HD)
|
|
;D5 P0 (PRECOMP BIT 0) 1 \ 1 \
|
|
;D4 P1 (PRECOMP BIT 1) 0 (125NS) 0 (125NS)
|
|
;D3 P2 (PRECOMP BIT 2) 0 / 0 /
|
|
;D2 MINI (BITRATE) 1 (250KBPS) 0 (500KBPS)
|
|
;D1 MOTOR 0 (OFF) 0 (OFF)
|
|
;D0 TC 0 (OFF) 0 (OFF)
|
|
;
|
|
; MOTOR AND DENSITY SELECT ARE INVERTED ON ZETA/DISKIO3
|
|
;
|
|
DORB_BR250 .EQU 11100100B ; 250KBPS
|
|
DORB_BR500 .EQU 10100000B ; 500KBPS
|
|
;
|
|
DORB_INIT .EQU DORB_BR250
|
|
;
|
|
; *** DIDE/N8/ZETA2/RCWDC/SMZ80/DYNO/EPFDC/MBC ***
|
|
;
|
|
DORC_INIT .EQU 00001100B ; SOFT RESET INACTIVE, DMA ENABLED
|
|
;
|
|
DORC_BR250 .EQU DORC_INIT
|
|
DORC_BR500 .EQU DORC_INIT
|
|
;
|
|
; *** RCSMC ***
|
|
;
|
|
DORD_BR250 .EQU 10100000B ; 250KBPS
|
|
DORD_BR500 .EQU 11100000B ; 500KBPS
|
|
;
|
|
DORD_INIT .EQU DORB_BR250
|
|
;
|
|
; DCR (ONLY APPLIES TO DIDE, N8, AND ZETA2)
|
|
;
|
|
DCR_BR250 .EQU 01H ; 250KBPS
|
|
DCR_BR500 .EQU 00H ; 500KBPS
|
|
;
|
|
;===============================================================================
|
|
; GENERAL UTILITY ROUTINES
|
|
;===============================================================================
|
|
;
|
|
; INITIALIZE BUFFER WITH FILLER BYTE
|
|
; HL = ADDRESS OF BUFFER
|
|
; DE = SIZE OF BUFFER
|
|
; B = FILLER BYTE VALUE
|
|
;
|
|
FILL_BUFFER:
|
|
LD A,B
|
|
LD (HL),A
|
|
INC HL
|
|
DEC DE
|
|
LD A,D
|
|
OR E
|
|
JP NZ,FILL_BUFFER
|
|
RET
|
|
;
|
|
; INITIALIZE BUFFER WITH PATTERN
|
|
; HL = ADDRESS OF BUFFER
|
|
; DE = SIZE OF BUFFER
|
|
; B = STARTING BYTE VALUE
|
|
;
|
|
PAT_BUFFER:
|
|
LD A,B
|
|
LD (HL),A
|
|
INC HL
|
|
DEC DE
|
|
INC B
|
|
LD A,D
|
|
OR E
|
|
JP NZ,PAT_BUFFER
|
|
RET
|
|
;
|
|
; PRINT A BLOCK OF MEMORY NICELY FORMATTED
|
|
;
|
|
DUMP_BUFFER:
|
|
CALL NEWLINE ;
|
|
BLKRD:
|
|
CALL PHL ; PRINT START LOCATION
|
|
LD C,16 ; SET FOR 16 LOCS
|
|
PUSH HL ; SAVE STARTING HL
|
|
NXTONE:
|
|
LD A,(HL) ; GET BYTE
|
|
CALL PRTHEXBYTE ; PRINT IT
|
|
CALL PC_SPACE ;
|
|
UPDH:
|
|
INC HL ; POINT NEXT
|
|
DEC C ; DEC. LOC COUNT
|
|
JR NZ,NXTONE ; IF LINE NOT DONE
|
|
; NOW PRINT 'DECODED' DATA TO RIGHT OF DUMP
|
|
PCRLF:
|
|
CALL PC_SPACE ; SPACE IT
|
|
LD C,16 ; SET FOR 16 CHARS
|
|
POP HL ; GET BACK START
|
|
PCRLF0:
|
|
LD A,(HL) ; GET BYTE
|
|
AND 060H ; SEE IF A 'DOT'
|
|
LD A,(HL) ; O.K. TO GET
|
|
JR NZ,PDOT ;
|
|
DOT:
|
|
LD A,2EH ; LOAD A DOT
|
|
PDOT:
|
|
CALL COUT ; PRINT IT
|
|
INC HL ;
|
|
LD A,D ;
|
|
CP H ;
|
|
JR NZ,UPDH1 ;
|
|
LD A,E ;
|
|
CP L ;
|
|
JP Z,DUMP_END ;
|
|
;
|
|
;IF BLOCK NOT DUMPED, DO NEXT CHARACTER OR LINE
|
|
UPDH1:
|
|
DEC C ; DEC. CHAR COUNT
|
|
JR NZ,PCRLF0 ; DO NEXT
|
|
CONTD:
|
|
CALL NEWLINE ;
|
|
JP BLKRD ;
|
|
|
|
DUMP_END:
|
|
RET ;
|
|
;
|
|
; UTILITY PROCS TO PRINT SINGLE CHARACTERS
|
|
;
|
|
PC_SPACE:
|
|
PUSH AF ; Store AF
|
|
LD A,' ' ; LOAD A "SPACE"
|
|
CALL COUT ; SCREEN IT
|
|
POP AF ; RESTORE AF
|
|
RET ; DONE
|
|
|
|
PC_HYPHEN:
|
|
PUSH AF ; Store AF
|
|
LD A,'-' ; LOAD A COLON
|
|
CALL COUT ; SCREEN IT
|
|
POP AF ; RESTORE AF
|
|
RET ; DONE
|
|
|
|
PC_COLON:
|
|
PUSH AF ; Store AF
|
|
LD A,':' ; LOAD A COLON
|
|
CALL COUT ; SCREEN IT
|
|
POP AF ; RESTORE AF
|
|
RET ; DONE
|
|
|
|
PC_EQUAL:
|
|
PUSH AF ; Store AF
|
|
LD A,'=' ; LOAD A COLON
|
|
CALL COUT ; SCREEN IT
|
|
POP AF ; RESTORE AF
|
|
RET ; DONE
|
|
|
|
PC_CR:
|
|
PUSH AF ; Store AF
|
|
LD A,CHR_CR ; LOAD A <CR>
|
|
CALL COUT ; SCREEN IT
|
|
POP AF ; RESTORE AF
|
|
RET ; DONE
|
|
|
|
PC_LF:
|
|
PUSH AF ; Store AF
|
|
LD A,CHR_LF ; LOAD A <LF>
|
|
CALL COUT ; SCREEN IT
|
|
POP AF ; RESTORE AF
|
|
RET ; DONE
|
|
|
|
PC_LBKT:
|
|
PUSH AF ; Store AF
|
|
LD A,'[' ; LOAD A COLON
|
|
CALL COUT ; SCREEN IT
|
|
POP AF ; RESTORE AF
|
|
RET ; DONE
|
|
|
|
PC_RBKT:
|
|
PUSH AF ; Store AF
|
|
LD A,']' ; LOAD A COLON
|
|
CALL COUT ; SCREEN IT
|
|
POP AF ; RESTORE AF
|
|
RET ; DONE
|
|
|
|
PC_LPAREN:
|
|
PUSH AF ; Store AF
|
|
LD A,'(' ; LOAD A COLON
|
|
CALL COUT ; SCREEN IT
|
|
POP AF ; RESTORE AF
|
|
RET ; DONE
|
|
|
|
|
|
PC_RPAREN:
|
|
PUSH AF ; Store AF
|
|
LD A,')' ; LOAD A COLON
|
|
CALL COUT ; SCREEN IT
|
|
POP AF ; RESTORE AF
|
|
RET ; DONE
|
|
|
|
PC_BS:
|
|
PUSH AF ; Store AF
|
|
LD A,CHR_BS ; LOAD A <BS>
|
|
CALL COUT ; SCREEN IT
|
|
POP AF ; RESTORE AF
|
|
RET ; DONE
|
|
|
|
NEWLINE_USED .DB 1
|
|
NEWLINE:
|
|
CALL PC_CR
|
|
CALL PC_LF
|
|
LD A,1
|
|
PUSH AF
|
|
LD (NEWLINE_USED),A
|
|
POP AF ; RESTORE AF
|
|
RET ; DONE
|
|
|
|
COPYSTR:
|
|
LD A,(HL)
|
|
CP '$'
|
|
RET Z
|
|
LDI
|
|
JR COPYSTR
|
|
|
|
;
|
|
;__COUT_________________________________________________________________________________________________________________________
|
|
;
|
|
; PRINT CONTENTS OF A
|
|
;________________________________________________________________________________________________________________________________
|
|
;
|
|
COUT:
|
|
PUSH BC ;
|
|
PUSH AF ;
|
|
PUSH HL ;
|
|
PUSH DE ;
|
|
|
|
LD C,2 ; BDOS FUNC: CONSOLE WRITE CHAR
|
|
LD E,A ; CHARACTER TO E
|
|
CALL $0005 ; CALL BDOS
|
|
|
|
POP DE ;
|
|
POP HL ;
|
|
POP AF ;
|
|
POP BC ;
|
|
RET ; DONE
|
|
;
|
|
;__PHL_________________________________________________________________________________________________________________________
|
|
;
|
|
; PRINT THE HL REG ON THE SERIAL PORT
|
|
;________________________________________________________________________________________________________________________________
|
|
;
|
|
PHL:
|
|
LD A,H ; GET HI BYTE
|
|
CALL PRTHEXBYTE ; DO HEX OUT ROUTINE
|
|
LD A,L ; GET LOW BYTE
|
|
CALL PRTHEXBYTE ; HEX IT
|
|
CALL PC_SPACE ;
|
|
RET ; DONE
|
|
;
|
|
; GET A LINE BUFFER WITH 2 HEX CHARS, HL=ADDRESS OF LINE BUFFER
|
|
; EXIT WITH C = NUMBER OF CHARS, C=0 MEANS NOTHING ENTERED
|
|
;
|
|
GETLNHEX:
|
|
LD C,0 ; C = CHAR COUNT
|
|
GLH_LOOP:
|
|
CALL GETKEYUC
|
|
OR A
|
|
JP Z,GLH_LOOP
|
|
CP CHR_CR
|
|
JP Z,GLH_CHK
|
|
CP CHR_BS
|
|
JP Z,GLH_BS
|
|
CP '0'
|
|
JP M,GLH_LOOP
|
|
CP '9' + 1
|
|
JP M,GLH_APPEND
|
|
CP 'A'
|
|
JP M,GLH_LOOP
|
|
CP 'F' + 1
|
|
JP M,GLH_APPEND
|
|
JP GLH_LOOP
|
|
GLH_BS:
|
|
LD A,C
|
|
OR A
|
|
JP Z,GLH_LOOP
|
|
CALL PC_BS
|
|
CALL PC_SPACE
|
|
CALL PC_BS
|
|
DEC C
|
|
DEC HL
|
|
JP GLH_LOOP
|
|
GLH_APPEND:
|
|
LD B,A
|
|
LD A,C
|
|
CP 2
|
|
JP P,GLH_LOOP
|
|
LD A,B
|
|
CALL COUT
|
|
LD (HL),A
|
|
INC C
|
|
INC HL
|
|
JP GLH_LOOP
|
|
GLH_CHK:
|
|
LD A,C
|
|
CP 2
|
|
JP Z,GLH_EXIT
|
|
CP 0
|
|
JP Z,GLH_EXIT
|
|
JP GLH_LOOP
|
|
GLH_EXIT:
|
|
RET
|
|
;
|
|
;__HEXIN__________________________________________________________________________________________________________________________
|
|
;
|
|
; GET ONE BYTE OF HEX DATA FROM BUFFER IN HL, RETURN IN A
|
|
;________________________________________________________________________________________________________________________________
|
|
;
|
|
HEXIN:
|
|
PUSH BC ; SAVE BC REGS.
|
|
CALL NIBL ; DO A NIBBLE
|
|
RLC A ; MOVE FIRST BYTE UPPER NIBBLE
|
|
RLC A ;
|
|
RLC A ;
|
|
RLC A ;
|
|
LD B,A ; SAVE ROTATED BYTE
|
|
CALL NIBL ; DO NEXT NIBBLE
|
|
ADD A,B ; COMBINE NIBBLES IN ACC.
|
|
POP BC ; RESTORE BC
|
|
RET ; DONE
|
|
NIBL:
|
|
LD A,(HL) ; GET K.B. DATA
|
|
INC HL ; INC KB POINTER
|
|
CP 40H ; TEST FOR ALPHA
|
|
JR NC,ALPH ;
|
|
AND 0FH ; GET THE BITS
|
|
RET ;
|
|
ALPH:
|
|
AND 0FH ; GET THE BITS
|
|
ADD A,09H ; MAKE IT HEX A-F
|
|
RET ;
|
|
;
|
|
; COPY A $ TERMINATED STRING FROM ADDRESS IN DE TO ADDRESS IN HL
|
|
; DE = ADDRESS OF SOURCE STRING
|
|
; LH = ADDRESS OF TARGET LOCATION
|
|
;
|
|
STRCPY:
|
|
LD A,(DE)
|
|
CP '$'
|
|
JP Z,STRCPYX
|
|
LD (HL),A
|
|
INC HL
|
|
INC DE
|
|
JP STRCPY
|
|
|
|
STRCPYX:
|
|
RET
|
|
;
|
|
; GET A HEX BYTE VALUE FROM THE USER
|
|
; WILL UPDATE STORED VALUE, EMPTY RESPONSE LEAVES VALUE ALONE
|
|
; DE = ADDRESS OF PROMPT STRING
|
|
; HL = ADDRESS OF VALUE
|
|
; BC = HI/BO ALLOWABLE RANGE OF VALID VALUES
|
|
;
|
|
GHB_PROMPTP .DW 0
|
|
GHB_RANGE .DW 0
|
|
GHB_VALUEP .DW 0
|
|
GHB_CLEAR .DB " \b\b$"
|
|
|
|
GETHEXBYTE:
|
|
LD BC,000FFH
|
|
GETHEXBYTERNG:
|
|
LD (GHB_PROMPTP),DE
|
|
LD (GHB_RANGE),BC
|
|
LD (GHB_VALUEP),HL
|
|
CALL NEWLINE
|
|
GHB_LOOP:
|
|
CALL PC_CR
|
|
LD DE,STR_ENTER
|
|
CALL WRITESTR
|
|
CALL PC_SPACE
|
|
LD DE,(GHB_PROMPTP)
|
|
CALL WRITESTR
|
|
CALL PC_SPACE
|
|
LD BC,(GHB_RANGE)
|
|
CALL PC_LBKT
|
|
LD A,B
|
|
CALL PRTHEXBYTE
|
|
CALL PC_HYPHEN
|
|
LD A,C
|
|
CALL PRTHEXBYTE
|
|
CALL PC_RBKT
|
|
CALL PC_SPACE
|
|
CALL PC_LPAREN
|
|
LD HL,(GHB_VALUEP)
|
|
LD A,(HL)
|
|
CALL PRTHEXBYTE
|
|
CALL PC_RPAREN
|
|
CALL PC_COLON
|
|
CALL PC_SPACE
|
|
LD DE,GHB_CLEAR
|
|
CALL WRITESTR
|
|
LD HL,KEYBUF
|
|
CALL GETLNHEX
|
|
LD A,C
|
|
CP 0 ; RETAIN CURRENT VALUE
|
|
JP Z,GHB_EXIT
|
|
CP 2 ; INPUT LOOKS OK, UPDATE IT
|
|
JP Z,GHB_CHK
|
|
JP GHB_LOOP ; ANYTHING ELSE, BAD INPUT, DO OVER
|
|
GHB_CHK:
|
|
LD HL,KEYBUF
|
|
CALL HEXIN
|
|
LD BC,(GHB_RANGE)
|
|
CP B
|
|
JP C,GHB_LOOP
|
|
CP C
|
|
JP Z,GHB_OK
|
|
JP NC,GHB_LOOP
|
|
GHB_OK:
|
|
LD HL,(GHB_VALUEP)
|
|
LD (HL),A
|
|
GHB_EXIT:
|
|
RET
|
|
|
|
;
|
|
; PRINT THE HEX BYTE VALUE IN A
|
|
;
|
|
HEXSTRBUF .TEXT "XX$"
|
|
;
|
|
PRTHEXBYTE:
|
|
PUSH AF
|
|
PUSH DE
|
|
LD DE,HEXSTRBUF
|
|
CALL HEXSTRBYTE
|
|
LD A,'$'
|
|
LD (DE),A
|
|
LD DE,HEXSTRBUF
|
|
CALL WRITESTR
|
|
POP DE
|
|
POP AF
|
|
RET
|
|
;
|
|
; PRINT THE HEX WORD VALUE IN BC
|
|
;
|
|
PRTHEXWORD:
|
|
PUSH AF
|
|
LD A,B
|
|
CALL PRTHEXBYTE
|
|
LD A,C
|
|
CALL PRTHEXBYTE
|
|
POP AF
|
|
RET
|
|
;
|
|
; CONVERT VALUE IN A TO A 2 CHARACTER HEX STRING AT DE
|
|
;
|
|
HEXCHR .TEXT "0123456789ABCDEF"
|
|
;
|
|
HEXSTRBYTE:
|
|
PUSH BC
|
|
PUSH HL
|
|
PUSH AF
|
|
LD BC,0
|
|
RRA
|
|
RRA
|
|
RRA
|
|
RRA
|
|
AND 0FH
|
|
LD C,A
|
|
LD HL,HEXCHR
|
|
ADD HL,BC
|
|
LD A,(HL)
|
|
LD (DE),A
|
|
INC DE
|
|
POP AF
|
|
PUSH AF
|
|
LD BC,0
|
|
AND 0FH
|
|
LD C,A
|
|
LD HL,HEXCHR
|
|
ADD HL,BC
|
|
LD A,(HL)
|
|
LD (DE),A
|
|
INC DE
|
|
POP AF
|
|
POP HL
|
|
POP BC
|
|
RET
|
|
;
|
|
; CONVERT VALUE IN BC TO A 4 CHARACTER HEX STRING AT DE
|
|
;
|
|
HEXSTRWORD:
|
|
LD A,B
|
|
CALL HEXSTRBYTE
|
|
LD A,C
|
|
CALL HEXSTRBYTE
|
|
RET
|
|
|
|
;
|
|
; PRINT A BYTE BUFFER IN HEX POINTED TO BY DE
|
|
; REGISTER A HAS SIZE OF BUFFER
|
|
;
|
|
PRTHEXBUF:
|
|
CP 0 ; EMPTY BUFFER?
|
|
JP Z,PRTHEXBUF2
|
|
|
|
LD B,A
|
|
PRTHEXBUF1:
|
|
CALL PC_SPACE
|
|
LD A,(DE)
|
|
CALL PRTHEXBYTE
|
|
INC DE
|
|
DJNZ PRTHEXBUF1
|
|
JP PRTHEXBUFX
|
|
|
|
PRTHEXBUF2:
|
|
CALL PC_SPACE
|
|
LD DE,STR_EMPTY
|
|
CALL WRITESTR
|
|
|
|
PRTHEXBUFX:
|
|
RET
|
|
;
|
|
; JP TO ADDRESS IN HL IN HEX POINTED TO BY DE
|
|
; MOSTLY USEFUL TO PERFORM AN INDIRECT CALL LIKE:
|
|
; LD HL,xxxx
|
|
; CALL JPHL
|
|
;
|
|
JPHL JP (HL)
|
|
;
|
|
; GENERATE A RANDOM BYTE
|
|
;
|
|
; RETURNS PSEUDO RANDOM 8 BIT NUMBER IN A. ONLY AFFECTS A.
|
|
; (SEED) IS THE BYTE FROM WHICH THE NUMBER IS GENERATED AND MUST BE
|
|
; INITIALIZED TO A NON ZERO VALUE OR THIS FUNCTION WILL ALWAYS RETURN
|
|
; ZERO.
|
|
;
|
|
RB_SEED .DB 1 ; RNDBYTE SEED (MUST NOT BE ZERO)
|
|
;
|
|
RNDBYTE:
|
|
LD A,(RB_SEED) ; GET SEED
|
|
AND 0B8H ; MASK NON-FEEDBACK BITS
|
|
SCF ; SET CARRY
|
|
JP PO,RB_NC ; SKIP CLEAR IF ODD
|
|
CCF ; COMPLEMENT CARRY (CLEAR IT)
|
|
RB_NC LD A,(RB_SEED) ; GET SEED BACK
|
|
RLA ; ROTATE CARRY INTO BYTE
|
|
LD (RB_SEED),A ; SAVE BACK FOR NEXT
|
|
RET ; DONE
|
|
;
|
|
; ADD HL,A
|
|
;
|
|
; A REGISTER IS DESTROYED!
|
|
;
|
|
ADDHLA:
|
|
ADD A,L
|
|
LD L,A
|
|
RET NC
|
|
INC H
|
|
RET
|
|
;
|
|
; OUTPUT A '$' TERMINATED STRING
|
|
;
|
|
WRITESTR:
|
|
PUSH AF
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
LD C,09H
|
|
CALL 0005H
|
|
POP HL
|
|
POP DE
|
|
POP BC
|
|
POP AF
|
|
RET
|
|
;
|
|
; READ A KEY, RETURN VALUE IN A
|
|
;
|
|
GETKEY:
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
LD C,06H
|
|
LD E,0FFH
|
|
CALL 0005H
|
|
POP HL
|
|
POP DE
|
|
POP BC
|
|
|
|
CP 03
|
|
JP Z,EXIT
|
|
|
|
RET
|
|
|
|
GETKEYUC:
|
|
CALL GETKEY
|
|
CP 'a'
|
|
JP M,GETKEYUC_EXIT
|
|
CP 'z' + 1
|
|
JP M,GETKEYUC_FIX
|
|
JP GETKEYUC_EXIT
|
|
GETKEYUC_FIX:
|
|
AND 11011111B
|
|
GETKEYUC_EXIT:
|
|
RET
|
|
;
|
|
; DELAY 16US (CPU SPEED COMPENSATED) INCUDING CALL/RET INVOCATION
|
|
; REGISTER A AND FLAGS DESTROYED
|
|
; NO COMPENSATION FOR Z180 MEMORY WAIT STATES
|
|
; THERE IS AN OVERHEAD OF 3TS PER INVOCATION
|
|
; IMPACT OF OVERHEAD DIMINISHES AS CPU SPEED INCREASES
|
|
;
|
|
; CPU SCALER (CPUSCL) = (CPUHMZ - 2) FOR 16US + 3TS DELAY
|
|
; NOTE: CPUSCL MUST BE >= 1!
|
|
;
|
|
; EXAMPLE: 8MHZ CPU (DELAY GOAL IS 16US)
|
|
; LOOP = ((6 * 16) - 5) = 91TS
|
|
; TOTAL COST = (91 + 40) = 131TS
|
|
; ACTUAL DELAY = (131 / 8) = 16.375US
|
|
;
|
|
; --- TOTAL COST = (LOOP COST + 40) TS -----------------+
|
|
DELAY: ; 17TS (FROM INVOKING CALL) |
|
|
LD A,(CPUSCL) ; 13TS |
|
|
; |
|
|
DELAY1: ; |
|
|
; --- LOOP = ((CPUSCL * 16) - 5) TS ------------+ |
|
|
DEC A ; 4TS | |
|
|
#IFDEF CPU_Z180 ; | |
|
|
OR A ; +4TS FOR Z180 | |
|
|
#ENDIF ; | |
|
|
JR NZ,DELAY1 ; 12TS (NZ) / 7TS (Z) | |
|
|
; ----------------------------------------------+ |
|
|
; |
|
|
RET ; 10TS (RETURN) |
|
|
;-------------------------------------------------------+
|
|
;
|
|
; DELAY 16US * DE (CPU SPEED COMPENSATED)
|
|
; REGISTER DE, A, AND FLAGS DESTROYED
|
|
; NO COMPENSATION FOR Z180 MEMORY WAIT STATES
|
|
; THERE IS A 27TS OVERHEAD FOR CALL/RET PER INVOCATION
|
|
; IMPACT OF OVERHEAD DIMINISHES AS DE AND/OR CPU SPEED INCREASES
|
|
;
|
|
; CPU SCALER (CPUSCL) = (CPUHMZ - 2) FOR 16US OUTER LOOP COST
|
|
; NOTE: CPUSCL MUST BE > 0!
|
|
;
|
|
; EXAMPLE: 8MHZ CPU, DE=6250 (DELAY GOAL IS .1 SEC OR 100,000US)
|
|
; INNER LOOP = ((16 * 6) - 5) = 91TS
|
|
; OUTER LOOP = ((91 + 37) * 6250) = 800,000TS
|
|
; ACTUAL DELAY = ((800,000 + 27) / 8) = 100,003US
|
|
;
|
|
; --- TOTAL COST = (OUTER LOOP + 27) TS ------------------------+
|
|
VDELAY: ; 17TS (FROM INVOKING CALL) |
|
|
; |
|
|
; --- OUTER LOOP = ((INNER LOOP + 37) * DE) TS ---------+ |
|
|
LD A,(CPUSCL) ; 13TS | |
|
|
; | |
|
|
VDELAY1: ; | |
|
|
; --- INNER LOOP = ((CPUSCL * 16) - 5) TS ------+ | |
|
|
#IFDEF CPU_Z180 ; | | |
|
|
OR A ; +4TS FOR Z180 | | |
|
|
#ENDIF ; | | |
|
|
DEC A ; 4TS | | |
|
|
JR NZ,VDELAY1 ; 12TS (NZ) / 7TS (Z) | | |
|
|
; ----------------------------------------------+ | |
|
|
; | |
|
|
DEC DE ; 6TS | |
|
|
#IFDEF CPU_Z180 ; | |
|
|
OR A ; +4TS FOR Z180 | |
|
|
#ENDIF ; | |
|
|
LD A,D ; 4TS | |
|
|
OR E ; 4TS | |
|
|
JP NZ,VDELAY ; 10TS | |
|
|
;-------------------------------------------------------+ |
|
|
; |
|
|
RET ; 10TS (FINAL RETURN) |
|
|
;---------------------------------------------------------------+
|
|
;
|
|
; DELAY ABOUT 0.5 SECONDS
|
|
; 500000US / 16US = 31250
|
|
;
|
|
LDELAY:
|
|
PUSH AF
|
|
PUSH DE
|
|
LD DE,31250
|
|
CALL VDELAY
|
|
POP DE
|
|
POP AF
|
|
RET
|
|
|
|
;
|
|
; HANDLE USER INPUT FOR A MENU BASED ON TABLE OF MENU DATA. DISPATCH MENU FUNCTIONS.
|
|
; ON INPUT, HL=ADDRESS OF MENU TABLE, B=COUNT OF MENU ENTRIES
|
|
;
|
|
.module MenuInfo
|
|
MenuInfo ; TRANSIENT STORAGE FOR CURRENT MENU
|
|
_DrawProc .dw 0 ; ADDRESS OF MENU DRAW ROUTINE
|
|
_TableAdr .dw 0 ; ADDRESS OF MENU TABLE DATA
|
|
_EntryInfo .dw 0 ; ENTRY COUNT / ENTRY SIZE
|
|
_Size .equ $ - MenuInfo
|
|
;
|
|
RUNMENU:
|
|
push hl ; save address of menu info data
|
|
|
|
_Run:
|
|
pop hl ; restore/resave menu init address
|
|
push hl
|
|
|
|
ld de,MenuInfo
|
|
ld bc,_Size
|
|
ldir
|
|
|
|
ld hl,(_DrawProc)
|
|
call JPHL ; call menu draw routine
|
|
|
|
_GetKey:
|
|
call GETKEYUC ; GET USER KEYPRESS
|
|
ld hl,(_TableAdr)
|
|
ld bc,(_EntryInfo) ; B=COUNT, C=ENTRY SIZE
|
|
ld d,0 ; put entry size in de
|
|
ld e,c ; "
|
|
|
|
; a=key pressed, hl=menu table address, b=entry count, de=entry size
|
|
_Loop:
|
|
ld c,(hl)
|
|
cp c
|
|
jp z,_Match ; found code
|
|
|
|
add hl,de ; point to next entry
|
|
djnz _Loop ; check next entry till count is zero
|
|
jp _GetKey ; keep trying
|
|
|
|
_Match:
|
|
inc hl ; load string
|
|
ld e,(hl)
|
|
inc hl
|
|
ld d,(hl)
|
|
call WRITESTR ; display it
|
|
|
|
inc hl ; load code address
|
|
ld e,(hl)
|
|
inc hl
|
|
ld d,(hl)
|
|
|
|
ld a,d ; check for zero
|
|
or e
|
|
jp z,_Exit ; zero means exit
|
|
|
|
ex de,hl
|
|
call JPHL ; indirect call to menu function
|
|
jp _Run
|
|
|
|
_Exit:
|
|
pop hl
|
|
ret
|
|
;
|
|
; CONTROL CHARACTERS
|
|
;
|
|
CHR_CR .EQU 0DH
|
|
CHR_LF .EQU 0AH
|
|
CHR_BS .EQU 08H
|
|
CHR_ESC .EQU 1BH
|
|
;
|
|
STR_DRIVERESET .TEXT "RESET DRIVE...$"
|
|
STR_EXECUTE .TEXT "EXECUTION$"
|
|
STR_OP .TEXT "OPERATION$"
|
|
STR_FORMAT .TEXT "FORMAT$"
|
|
STR_SENDCMD .TEXT "SEND COMMAND$"
|
|
STR_GETRESULTS .TEXT "GET RESULTS$"
|
|
STR_SEEKWAIT .TEXT "SEEK WAIT$"
|
|
STR_DOR .TEXT "SET DOR$"
|
|
STR_PROGRESS .TEXT "PROGRESS$"
|
|
STR_MISMATCH .TEXT "DATA MISMATCH AT $"
|
|
STR_RESET .TEXT "FDCRESET...$"
|
|
STR_NOTIMPL .TEXT "*** NOT IMPLEMENTED ***$"
|
|
STR_NORESP .TEXT "*** DRIVE NOT RESPONDING ***$"
|
|
STR_EOD .TEXT "<EOD>$"
|
|
STR_EMPTY .TEXT "<EMPTY>$"
|
|
STR_TIMEOUT .TEXT "<TIMEOUT>$"
|
|
STR_ARROW .TEXT " -->$"
|
|
STR_ENTER .TEXT "ENTER$"
|
|
STR_ON .TEXT "ON $"
|
|
STR_OFF .TEXT "OFF$"
|
|
STR_DRV720 .TEXT "720KB $"
|
|
STR_DRV144 .TEXT "1.44MB$"
|
|
STR_MODEPOLL .TEXT "POLLING $"
|
|
STR_MODEINT .TEXT "INTERRUPT $"
|
|
STR_MODEDMA .TEXT "DMA $"
|
|
STR_CC0 .TEXT " CC0=$"
|
|
STR_CC1 .TEXT " CC1=$"
|
|
STR_CC2 .TEXT " CC2=$"
|
|
STR_N .TEXT " N=$"
|
|
STR_SC .TEXT " SC=$"
|
|
STR_GPL .TEXT " GPL=$"
|
|
STR_D .TEXT " D=$"
|
|
STR_ST0 .TEXT " ST0=$"
|
|
STR_ST1 .TEXT " ST1=$"
|
|
STR_ST2 .TEXT " ST2=$"
|
|
STR_CYL .TEXT " CYL=$"
|
|
STR_UNIT .TEXT " UNIT=$"
|
|
STR_HEAD .TEXT " HD=$"
|
|
STR_REC .TEXT " SEC=$"
|
|
STR_NUM .TEXT " NUM=$"
|
|
STR_DENS .TEXT " DENS=$"
|
|
STR_EOTSEC .TEXT " EOTSEC=$"
|
|
STR_GAP .TEXT " GAP=$"
|
|
STR_DTL .TEXT " DTL=$"
|
|
STR_SN .TEXT " SN=$"
|
|
STR_NCN .TEXT " NCN=$"
|
|
STR_PCN .TEXT " PCN=$"
|
|
STR_MSR .TEXT " MSR=$"
|
|
STR_A .TEXT " A=$"
|
|
STR_BC .TEXT " BC=$"
|
|
STR_DE .TEXT " DE=$"
|
|
STR_HL .TEXT " HL=$"
|
|
STR_TO .TEXT " TO=$"
|
|
STR_ITER .TEXT " ITER=$"
|
|
STR_DSKCHG .TEXT " DC=$"
|
|
;
|
|
KEYBUFLEN .EQU 80
|
|
KEYBUF .FILL KEYBUFLEN,' '
|
|
;
|
|
STACKSAV .DW 0
|
|
STACKSIZ .EQU 40H ; WE ARE A STACK PIG
|
|
.FILL STACKSIZ,0
|
|
STACK .EQU $
|
|
;
|
|
BUFFER .EQU 4000H
|
|
VFYBUF .EQU 5000H
|
|
BUFSIZ .EQU 0200H
|
|
.END
|
|
|