mirror of
https://github.com/wwarthen/RomWBW.git
synced 2026-02-06 14:11:48 -06:00
Floppy I/O was failing for slower CPUs when the timer interrupts were active. Now fixed. Credit to Jorge Jorge Rodrigues for finding this problem and pointing me in the right direction for the fix.
1980 lines
48 KiB
NASM
1980 lines
48 KiB
NASM
;
|
|
;==================================================================================================
|
|
; FLOPPY DISK DRIVER
|
|
;==================================================================================================
|
|
;
|
|
; TODO:
|
|
;
|
|
;
|
|
; PORTS
|
|
;
|
|
#IF ((FDMODE == FDMODE_DIO) | (FDMODE == FDMODE_ZETA) | (FDMODE == FDMODE_DIO3))
|
|
FDC_MSR .EQU $36 ; 8272 MAIN STATUS REGISTER
|
|
FDC_DATA .EQU $37 ; 8272 DATA PORT
|
|
FDC_DIR .EQU $38 ; DATA INPUT REGISTER
|
|
FDC_DOR .EQU $3A ; DIGITAL OUTPUT REGISTER (LATCH)
|
|
FDC_DMA .EQU $3C ; PSEUDO DMA DATA PORT
|
|
#ENDIF
|
|
#IF (FDMODE = FDMODE_ZETA2)
|
|
FDC_MSR .EQU $30 ; 8272 MAIN STATUS REGISTER
|
|
FDC_DATA .EQU $31 ; 8272 DATA PORT
|
|
FDC_DOR .EQU $38 ; DIGITAL OUTPUT REGISTER
|
|
FDC_DCR .EQU $28 ; CONFIGURATION CONTROL REGISTER
|
|
FDC_TC .EQU $38 ; TERMINAL COUNT (W/ DACK)
|
|
#ENDIF
|
|
#IF (FDMODE == FDMODE_DIDE)
|
|
FDC_BID .EQU $20 ; IO RANGE 20H-3FH
|
|
FDC_MSR .EQU $2A ; 8272 MAIN STATUS REGISTER
|
|
FDC_DATA .EQU $2B ; 8272 DATA PORT
|
|
FDC_DOR .EQU $2C ; DOR
|
|
FDC_DCR .EQU $2D ; DCR
|
|
FDC_DACK .EQU $3C ; DACK
|
|
FDC_TC .EQU $3D ; TERMINAL COUNT (W/ DACK)
|
|
FDC_DMA .EQU $3C ; NOT USED BY DIDE
|
|
#ENDIF
|
|
#IF (FDMODE == FDMODE_N8)
|
|
FDC_MSR .EQU $8C ; 8272 MAIN STATUS REGISTER
|
|
FDC_DATA .EQU $8D ; 8272 DATA PORT
|
|
FDC_DOR .EQU $92 ; DOR
|
|
FDC_DCR .EQU $91 ; DCR
|
|
FDC_DACK .EQU $90 ; DACK
|
|
FDC_TC .EQU $93 ; TERMINAL COUNT (W/ DACK)
|
|
FDC_DMA .EQU $3C ; NOT USED BY N8
|
|
#ENDIF
|
|
#IF (FDMODE == FDMODE_RCSMC)
|
|
FDC_MSR .EQU $50 ; 8272 MAIN STATUS REGISTER
|
|
FDC_DATA .EQU $51 ; 8272 DATA PORT
|
|
FDC_DOR .EQU $58 ; DIGITAL OUTPUT REGISTER (LATCH)
|
|
#ENDIF
|
|
#IF (FDMODE = FDMODE_RCWDC)
|
|
FDC_MSR .EQU $50 ; 8272 MAIN STATUS REGISTER
|
|
FDC_DATA .EQU $51 ; 8272 DATA PORT
|
|
FDC_DOR .EQU $58 ; DIGITAL OUTPUT REGISTER
|
|
FDC_DCR .EQU $48 ; CONFIGURATION CONTROL REGISTER
|
|
FDC_TC .EQU $58 ; TERMINAL COUNT (W/ DACK)
|
|
#ENDIF
|
|
;
|
|
; DISK OPERATIONS
|
|
;
|
|
DOP_READ .EQU 0 ; READ OPERATION
|
|
DOP_WRITE .EQU 1 ; WRITE OPERATION
|
|
DOP_FORMAT .EQU 2 ; FORMAT OPERATION
|
|
DOP_READID .EQU 3 ; READ ID OPERATION
|
|
;
|
|
; 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
|
|
;
|
|
; FD DEVICE CONFIGURATION
|
|
;
|
|
FD_DEVCNT .EQU 2 ; 2 DEVICES SUPPORTED
|
|
FD_CFGSIZ .EQU 8 ; SIZE OF CFG TBL ENTRIES
|
|
;
|
|
; PER DEVICE DATA OFFSETS
|
|
; ; OFFSET OF...
|
|
FD_DEV .EQU 0 ; DEVICE NUMBER (BYTE)
|
|
FD_STAT .EQU 1 ; LAST STATUS (BYTE)
|
|
FD_MEDTYP .EQU 2 ; MEDIA TYPE FDM... (BYTE)
|
|
FD_CURTRK .EQU 3 ; CURRENT TRACK (BYTE)
|
|
FD_HST .EQU 4 ; HOSTS SEEK POSITION
|
|
FD_HSTTRK .EQU FD_HST + 0 ; HOST TRACK (WORD)
|
|
FD_HSTSEC .EQU FD_HST + 2 ; HOST SECTOR (BYTE)
|
|
FD_HSTHD .EQU FD_HST + 3 ; HOST HEAD (BYTE)
|
|
;
|
|
FD_CFGTBL:
|
|
; DEVICE 0, PRIMARY MASTER
|
|
.DB 0 ; DEVICE NUMBER
|
|
.DB 0 ; DEVICE STATUS
|
|
.DB FDMEDIA ; MEDIA TYPE
|
|
.DB $FF ; CURRENT TRACK
|
|
.DW 0 ; HOST TRACK
|
|
.DB 0 ; HOST SECTOR
|
|
.DB 0 ; HOST HEAD
|
|
#IF (FD_DEVCNT >= 2)
|
|
; DEVICE 1, PRIMARY SLAVE
|
|
.DB 1 ; DRIVER DEVICE NUMBER
|
|
.DB 0 ; DEVICE STATUS
|
|
.DB FDMEDIA ; MEDIA TYPE
|
|
.DB $FF ; CURRENT TRACK
|
|
.DW 0 ; HOST TRACK
|
|
.DB 0 ; HOST SECTOR
|
|
.DB 0 ; HOST HEAD
|
|
#ENDIF
|
|
;
|
|
#IF ($ - FD_CFGTBL) != (FD_DEVCNT * FD_CFGSIZ)
|
|
.ECHO "*** INVALID FD CONFIG TABLE ***\n"
|
|
#ENDIF
|
|
;
|
|
.DB $FF ; END MARKER
|
|
;
|
|
#IF (FDTRACE > 0)
|
|
;
|
|
; 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
|
|
#ENDIF
|
|
;
|
|
; FDC COMMANDS
|
|
;
|
|
CFD_READ .EQU 00000110B ; CMD,HDS/DS,C,H,R,N,EOT,GPL,DTL --> ST0,ST1,ST2,C,H,R,N
|
|
CFD_READDEL .EQU 00001100B ; CMD,HDS/DS,C,H,R,N,EOT,GPL,DTL --> ST0,ST1,ST2,C,H,R,N
|
|
CFD_WRITE .EQU 00000101B ; CMD,HDS/DS,C,H,R,N,EOT,GPL,DTL --> ST0,ST1,ST2,C,H,R,N
|
|
CFD_WRITEDEL .EQU 00001001B ; CMD,HDS/DS,C,H,R,N,EOT,GPL,DTL --> ST0,ST1,ST2,C,H,R,N
|
|
CFD_READTRK .EQU 00000010B ; CMD,HDS/DS,C,H,R,N,EOT,GPL,DTL --> ST0,ST1,ST2,C,H,R,N
|
|
CFD_READID .EQU 00001010B ; CMD,HDS/DS --> ST0,ST1,ST2,C,H,R,N
|
|
CFD_FMTTRK .EQU 00001101B ; CMD,HDS/DS,N,SC,GPL,D --> ST0,ST1,ST2,C,H,R,N
|
|
CFD_SCANEQ .EQU 00010001B ; CMD,HDS/DS,C,H,R,N,EOT,GPL,STP --> ST0,ST1,ST2,C,H,R,N
|
|
CFD_SCANLOEQ .EQU 00011001B ; CMD,HDS/DS,C,H,R,N,EOT,GPL,STP --> ST0,ST1,ST2,C,H,R,N
|
|
CFD_SCANHIEQ .EQU 00011101B ; CMD,HDS/DS,C,H,R,N,EOT,GPL,STP --> ST0,ST1,ST2,C,H,R,N
|
|
CFD_RECAL .EQU 00000111B ; CMD,DS --> <EMPTY>
|
|
CFD_SENSEINT .EQU 00001000B ; CMD --> ST0,PCN
|
|
CFD_SPECIFY .EQU 00000011B ; CMD,SRT/HUT,HLT/ND --> <EMPTY>
|
|
CFD_DRVSTAT .EQU 00000100B ; CMD,HDS/DS --> ST3
|
|
CFD_SEEK .EQU 00001111B ; CMD,HDS/DS --> <EMPTY>
|
|
CFD_VERSION .EQU 00010000B ; CMD --> ST0
|
|
;
|
|
;
|
|
; 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)
|
|
;
|
|
FCD_MT .EQU 000H ; MULTI-TRACK, WE DON'T USE, SET TO 0
|
|
FCD_MFM .EQU 001H ; MFM, 0=FM, 1=MFM, WE USE MFM ALWAYS
|
|
FCD_SK .EQU 000H ; SKIP MODE, WE DON'T USE, SET TO 0
|
|
FCD_N .EQU 002H ; SECTOR SIZE, N=2 FOR 512 BYTES
|
|
FCD_DTL .EQU 0FFH ; DATA LENGTH (WHEN N=0, SET TO FF OTHERWISE)
|
|
FCD_STP .EQU 001H ; SECTOR SCAN TYPE, 1=CONTIG, 2=ALTERNATING
|
|
;
|
|
FCD_PC720 .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)
|
|
.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 << 1) | 1 ; HLT = 16ms, ND = YES
|
|
.DB DOR_BR250 ; DOR
|
|
.DB DCR_BR250 ; DCR
|
|
.IF (($ - FCD_PC720) != FCD_LEN)
|
|
.ECHO "*** FCD_PC720 SIZE ERROR!!! ***\n"
|
|
.ENDIF
|
|
;
|
|
FCD_PC144 .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)
|
|
.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 << 1) | 1 ; HLT = 16ms, ND = YES
|
|
.DB DOR_BR500 ; DOR
|
|
.DB DCR_BR500 ; DCR
|
|
.IF (($ - FCD_PC144) != FCD_LEN)
|
|
.ECHO "*** FCD_PC144 SIZE ERROR!!! ***\n"
|
|
.ENDIF
|
|
;
|
|
FCD_PC360 .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)
|
|
.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 << 1) | 1 ; HLT = 16ms, ND = YES
|
|
.DB DOR_BR250 ; DOR
|
|
.DB DCR_BR250 ; DCR
|
|
.IF (($ - FCD_PC360) != FCD_LEN)
|
|
.ECHO "*** FCD_PC360 SIZE ERROR!!! ***\n"
|
|
.ENDIF
|
|
;
|
|
FCD_PC120 .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)
|
|
.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 << 1) | 1 ; HLT = 16ms, ND = YES
|
|
.DB DOR_BR500 ; DOR
|
|
.DB DCR_BR500 ; DCR
|
|
.IF (($ - FCD_PC120) != FCD_LEN)
|
|
.ECHO "*** FCD_PC120 SIZE ERROR!!! ***\n"
|
|
.ENDIF
|
|
;
|
|
FCD_PC111 .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)
|
|
.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 << 1) | 1 ; HLT = 50ms, ND = YES
|
|
.DB DOR_BR500 ; DOR
|
|
.DB DCR_BR500 ; DCR
|
|
.IF (($ - FCD_PC111) != FCD_LEN)
|
|
.ECHO "*** FCD_PC111 SIZE ERROR!!! ***\n"
|
|
.ENDIF
|
|
;
|
|
; FCD LOOKUP TABLE (CALLED TO SET HL TO ADDRESS OF MEDIA DATA ABOVE)
|
|
; ENTRIES BELOW MUST MATCH COUNT AND VALUES OF FDMXXX IN STD.ASM
|
|
;
|
|
FCD_TBL:
|
|
LD HL,FCD_PC720 \ RET ; FDM720 = 0
|
|
LD HL,FCD_PC144 \ RET ; FDM144 = 1
|
|
LD HL,FCD_PC360 \ RET ; FDM360 = 2
|
|
LD HL,FCD_PC120 \ RET ; FDM120 = 3
|
|
LD HL,FCD_PC111 \ RET ; FDM111 = 4
|
|
;
|
|
; 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
|
|
;
|
|
#IF (FDMODE == FDMODE_DIO)
|
|
DOR_BR250 .EQU 10100100B ; 250KBPS W/ MOTOR ON
|
|
DOR_BR500 .EQU 11010000B ; 500KBPS W/ MOTOR ON
|
|
DOR_INIT .EQU 11010010B ; INITIAL DEFAULT LATCH VALUE
|
|
#ENDIF
|
|
;
|
|
; 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 VS. DIO
|
|
;
|
|
#IF ((FDMODE == FDMODE_ZETA) | (FDMODE == FDMODE_DIO3))
|
|
DOR_BR250 .EQU 11100110B ; 250KBPS W/ MOTOR ON
|
|
DOR_BR500 .EQU 10100010B ; 500KBPS W/ MOTOR ON
|
|
DOR_INIT .EQU 10100000B ; INITIAL DEFAULT LATCH VALUE
|
|
#ENDIF
|
|
;
|
|
; RCSMC 250KBPS 500KBPS
|
|
; ------------ ------- -------
|
|
;D7 /FDC_RST 1 (RUN) 1 (RUN)
|
|
;D6 DENSEL 0 (DD) 1 (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 MOTORB 0 (OFF) 0 (OFF)
|
|
;D1 MOTORA 0 (OFF) 0 (OFF)
|
|
;D0 TC 0 (OFF) 0 (OFF)
|
|
;
|
|
; MOTOR INVERTED VS. DIO, DENSITY SELECT LIKE DIO
|
|
;
|
|
#IF (FDMODE == FDMODE_RCSMC)
|
|
; RCSMC HAS NO MINI (BITRATE) LATCH AT D2. INSTEAD, D1 AND
|
|
; D2 PROVIDE INDEPENDENT MOTOR CONTROL FOR EACH DRIVE.
|
|
; MINI (BITRATE) IS A HARDWARE JUMPER (JP3)
|
|
; JP3: 1-2 IS DD (MINI HIGH) AND 2-3 IS HD (MINI LOW)
|
|
; JP3 *MUST* BE SET CORRECTLY FOR MEDIA USED
|
|
; THE CORRECT MOTOR BIT IS SET IN MOTOR ON, NEITHER SET HERE
|
|
DOR_BR250 .EQU 10100000B ; 250KBPS W/ MOTOR OFF!
|
|
DOR_BR500 .EQU 11100000B ; 500KBPS W/ MOTOR OFF!
|
|
DOR_INIT .EQU 11100000B ; INITIAL DEFAULT LATCH VALUE
|
|
#ENDIF
|
|
;
|
|
; *** DIDE/N8/ZETA V2 ***
|
|
;
|
|
#IF ((FDMODE == FDMODE_DIDE) | (FDMODE == FDMODE_N8) | (FDMODE == FDMODE_ZETA2) | (FDMODE == FDMODE_RCWDC))
|
|
DOR_INIT .EQU 00001100B ; SOFT RESET INACTIVE, DMA ENABLED
|
|
DOR_BR250 .EQU DOR_INIT
|
|
DOR_BR500 .EQU DOR_INIT
|
|
#ENDIF
|
|
;
|
|
; DCR (ONLY APPLIES TO DIDE, N8, AND ZETA V2)
|
|
;
|
|
DCR_BR250 .EQU 01H ; 250KBPS
|
|
DCR_BR500 .EQU 00H ; 500KBPS
|
|
;
|
|
#IF (FDTRACE > 0)
|
|
;
|
|
; FDC COMMAND STRINGS
|
|
;
|
|
FCS_NOP .DB "NOP$"
|
|
FCS_READ .DB "READ$"
|
|
FCS_READDEL .DB "READDEL$"
|
|
FCS_WRITE .DB "WRITE$"
|
|
FCS_WRITEDEL .DB "WRITEDEL$"
|
|
FCS_READTRK .DB "READTRK$"
|
|
FCS_READID .DB "READID$"
|
|
FCS_FMTTRK .DB "FMTTRK$"
|
|
FCS_SCANEQ .DB "SCANEQ$"
|
|
FCS_SCANLOEQ .DB "SCANLOEQ$"
|
|
FCS_SCANHIEQ .DB "SCANHIEQ$"
|
|
FCS_RECAL .DB "RECAL$"
|
|
FCS_SENSEINT .DB "SENSEINT$"
|
|
FCS_SPECIFY .DB "SPECIFY$"
|
|
FCS_DRVSTAT .DB "DRVSTAT$"
|
|
FCS_SEEK .DB "SEEK$"
|
|
FCS_VERSION .DB "VER$"
|
|
;
|
|
; FDC COMMAND TABLE
|
|
;
|
|
FCT .DB CFD_READ \ .DW FCS_READ
|
|
FCT_ENTSIZ .EQU $ - FCT
|
|
.DB CFD_READDEL \ .DW FCS_READDEL
|
|
.DB CFD_WRITE \ .DW FCS_WRITE
|
|
.DB CFD_WRITEDEL \ .DW FCS_WRITEDEL
|
|
.DB CFD_READTRK \ .DW FCS_READTRK
|
|
.DB CFD_READID \ .DW FCS_READID
|
|
.DB CFD_FMTTRK \ .DW FCS_FMTTRK
|
|
.DB CFD_SCANEQ \ .DW FCS_SCANEQ
|
|
.DB CFD_SCANLOEQ \ .DW FCS_SCANLOEQ
|
|
.DB CFD_SCANHIEQ \ .DW FCS_SCANHIEQ
|
|
.DB CFD_RECAL \ .DW FCS_RECAL
|
|
.DB CFD_SENSEINT \ .DW FCS_SENSEINT
|
|
.DB CFD_SPECIFY \ .DW FCS_SPECIFY
|
|
.DB CFD_DRVSTAT \ .DW FCS_DRVSTAT
|
|
.DB CFD_SEEK \ .DW FCS_SEEK
|
|
.DB CFD_VERSION \ .DW FCS_VERSION
|
|
FCT_COUNT .EQU (($ - FCT) / FCT_ENTSIZ) ; # ENTRIES IN TABLE
|
|
#ENDIF
|
|
;
|
|
; DRIVER FUNCTION TABLE
|
|
;
|
|
FD_FNTBL:
|
|
.DW FD_STATUS
|
|
.DW FD_RESET
|
|
.DW FD_SEEK
|
|
.DW FD_READ
|
|
.DW FD_WRITE
|
|
.DW FD_VERIFY
|
|
.DW FD_FORMAT
|
|
.DW FD_DEVICE
|
|
.DW FD_MEDIA
|
|
.DW FD_DEFMED
|
|
.DW FD_CAP
|
|
.DW FD_GEOM
|
|
#IF (($ - FD_FNTBL) != (DIO_FNCNT * 2))
|
|
.ECHO "*** INVALID FD FUNCTION TABLE ***\n"
|
|
#ENDIF
|
|
;
|
|
FD_VERIFY:
|
|
FD_FORMAT:
|
|
FD_DEFMED:
|
|
CALL PANIC ; INVALID SUB-FUNCTION
|
|
;
|
|
;
|
|
;
|
|
FD_DEVICE:
|
|
LD D,DIODEV_FD ; D := DEVICE TYPE
|
|
LD E,(IY+FD_DEV) ; E := PHYSICAL DEVICE NUMBER
|
|
#IF (FDMEDIA == FDM720)
|
|
LD C,%11010100 ; 3.5" DS/DD
|
|
#ENDIF
|
|
#IF (FDMEDIA == FDM144)
|
|
LD C,%11011000 ; 3.5" DS/HD
|
|
#ENDIF
|
|
#IF (FDMEDIA == FDM360)
|
|
LD C,%10110100 ; 5.25" DS/DD
|
|
#ENDIF
|
|
#IF (FDMEDIA == FDM120)
|
|
LD C,%10111000 ; 5.25" DS/HD
|
|
#ENDIF
|
|
#IF (FDMEDIA == FDM111)
|
|
LD C,%10010100 ; 8" DS/DD
|
|
#ENDIF
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
; FD_MEDIA
|
|
;
|
|
FD_MEDIA:
|
|
LD A,E ; GET FLAGS
|
|
OR A ; SET FLAGS
|
|
JR Z,FD_MEDIA4 ; JUST REPORT CURRENT STATUS AND MEDIA
|
|
|
|
#IF (FDMAUTO)
|
|
; SETUP TO READ TRK 0, HD 0, SEC 0
|
|
;LD A,C ; C STILL HAS REQUESTED DRIVE
|
|
LD A,(IY+FD_DEV) ; GET DRIVE UNIT
|
|
;AND 0FH
|
|
LD (FCD_DS),A
|
|
LD A,0
|
|
LD (FCD_C),A
|
|
LD (FCD_H),A
|
|
INC A
|
|
LD (FCD_R),A
|
|
LD A,DOP_READID
|
|
LD (FCD_DOP),A
|
|
|
|
#IF (FDTRACE < 3)
|
|
; SUPPRESS TRACING FOR MEDIA TESTS
|
|
LD A,0
|
|
LD (FCD_TRACE),A
|
|
#ENDIF
|
|
|
|
LD B,5
|
|
|
|
FD_MEDIARETRY:
|
|
; TRY PRIMARY MEDIA CHOICE FIRST
|
|
LD A,FDMEDIA
|
|
CALL FD_TESTMEDIA
|
|
JR Z,FD_MEDIA3 ; IF SUCCESS, WE ARE DONE
|
|
|
|
; TRY ALTERNATE MEDIA CHOICE
|
|
LD A,FDMEDIAALT
|
|
CALL FD_TESTMEDIA
|
|
JR Z,FD_MEDIA3 ; IF SUCCESS, WE ARE DONE
|
|
|
|
DJNZ FD_MEDIARETRY
|
|
|
|
; NO JOY, RETURN WITH E=0 (NO MEDIA)
|
|
;LD HL,(FDDS_MEDIAADR)
|
|
;LD (HL),0 ; SET TO NO MEDIA
|
|
LD (IY+FD_MEDTYP),0 ; SET DRIVE = NO MEDIA
|
|
LD E,0
|
|
OR $FF ; SIGNAL ERROR
|
|
RET
|
|
|
|
FD_TESTMEDIA:
|
|
;LD HL,(FDDS_MEDIAADR)
|
|
;LD (HL),A
|
|
LD (IY+FD_MEDTYP),A
|
|
PUSH BC
|
|
CALL FD_START
|
|
POP BC
|
|
RET
|
|
|
|
FD_MEDIA3:
|
|
|
|
#IF (FDTRACE < 3)
|
|
; RESTORE TRACING FOR MEDIA TESTS
|
|
LD A,FDTRACE
|
|
LD (FCD_TRACE),A
|
|
#ENDIF
|
|
#ENDIF
|
|
|
|
FD_MEDIA4:
|
|
|
|
#IF (FDTRACE >= 3)
|
|
LD DE,FDSTR_SELECT
|
|
CALL WRITESTR
|
|
;LD BC,(FDDS_MEDIAADR)
|
|
;CALL PRTHEXWORD
|
|
#ENDIF
|
|
|
|
; LOAD THE MEDIA BYTE
|
|
;LD HL,(FDDS_MEDIAADR)
|
|
;LD A,(HL)
|
|
LD A,(IY+FD_MEDTYP) ; GET CURRENT MEDIA TYPE
|
|
ADD A,MID_FD720 ; ASSUMES MID_ VALUES ARE IN SAME ORDER AS FDM VALUES
|
|
|
|
#IF (FDTRACE >= 3)
|
|
CALL PC_SPACE
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
LD E,A ; MOVE MEDIA VALUE TO E
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
FD_CAP:
|
|
CALL FD_GEOM ; GET GEOMETRY
|
|
; HL=TRACKS, D=HEADS, E=SECTORS
|
|
PUSH HL ; SAVE TRACK COUNT
|
|
LD H,D ; HEADS COUNT TO H
|
|
RES 7,H ; MAKE SURE LBA CAPABILITY BIT IS CLEARED
|
|
CALL MULT8 ; HL := H * E FOR SECTORS / CYL
|
|
POP DE ; RECOVER TRACKS, E == TRACK COUNT
|
|
LD H,L ; MOVE WORKING COUNT L --> H
|
|
CALL MULT8 ; HL := H * E FOR TOTAL SECTORS
|
|
LD DE,0 ; HI WORD ALWAYS ZERO
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; DONE
|
|
;
|
|
;
|
|
;
|
|
FD_GEOM:
|
|
LD A,(IY+FD_MEDTYP) ; GET CURRENT MEDIA TYPE
|
|
RLCA ; TABLE IS 4 BYTE ENTRIES
|
|
RLCA ; A = A * 4
|
|
LD HL,FCD_TBL ; HL = START OF TABLE
|
|
LD D,0 ; SET DE TO TABLE OFFSET
|
|
LD E,A
|
|
ADD HL,DE ; OFFSET BASED ON DESIRED MEDIA
|
|
CALL JPHL ; CALL THE TABLE ENTRY (SEE FCD_TBL)
|
|
; HL NOW POINTS TO START OF DESIRED MEDIA INFO
|
|
LD A,(HL) ; GET TRACKS
|
|
INC HL ; POINT TO HEADS
|
|
LD D,(HL) ; GET HEADS
|
|
SET 7,D ; SET LBA CAPABILITY BIT
|
|
INC HL ; POINT TO SECTORS
|
|
LD E,(HL) ; GET SECTORS
|
|
LD L,A ; L := TRACKS
|
|
LD H,0 ; HI WORD OF TRACKS IS ALWAYS ZERO
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; DONE
|
|
;
|
|
; FD_INIT
|
|
;
|
|
FD_INIT:
|
|
CALL NEWLINE ; FORMATTING
|
|
PRTS("FD: IO=0x$")
|
|
LD A,FDC_MSR
|
|
CALL PRTHEXBYTE
|
|
PRTS(" UNITS=2$")
|
|
;
|
|
; SETUP THE DISPATCH TABLE ENTRIES
|
|
;
|
|
LD B,FD_DEVCNT ; LOOP CONTROL
|
|
LD IY,FD_CFGTBL ; START OF CFG TABLE
|
|
FD_INIT0:
|
|
PUSH BC ; SAVE LOOP CONTROL
|
|
LD BC,FD_FNTBL ; BC := FUNC TABLE ADR
|
|
PUSH IY ; CFG ENTRY POINTER
|
|
POP DE ; COPY TO DE
|
|
CALL DIO_ADDENT ; ADD ENTRY, BC IS NOT DESTROYED
|
|
CALL FD_INITUNIT ; DO UNIT INITIALIZATION
|
|
LD BC,FD_CFGSIZ ; SIZE OF CFG ENTRY
|
|
ADD IY,BC ; BUMP IY TO NEXT ENTRY
|
|
POP BC ; RESTORE BC
|
|
DJNZ FD_INIT0 ; LOOP AS NEEDED
|
|
;
|
|
LD A,FDTRACE
|
|
LD (FCD_TRACE),A
|
|
;
|
|
LD BC,0
|
|
LD (FCD_IDLECNT),BC
|
|
;
|
|
LD A,DOR_INIT
|
|
LD (FST_DOR),A
|
|
;
|
|
CALL FC_RESETFDC
|
|
CALL FD_CLRDSKCHG
|
|
;
|
|
LD A,TRUE
|
|
LD (FCD_FDCRDY),A
|
|
;
|
|
RET
|
|
;
|
|
; UNIT INITIALIZATION
|
|
;
|
|
FD_INITUNIT:
|
|
LD (IY+FD_STAT),0 ; CLEAR STATUS
|
|
LD (IY+FD_MEDTYP),FDMEDIA ; SET DEFAULT MEDIA TYPE
|
|
LD (IY+FD_CURTRK),$FE ; SPECIAL VALUE FOR CURTRK
|
|
RET
|
|
;
|
|
; FD_IDLE QUIESCES THE FLOPPY SUBSYSTEM (MOTOR OFF)
|
|
; AFTER BEING CALLED ENOUGH TIMES...
|
|
; SHOULD IT INVALIDATE THE BUFFER???
|
|
;
|
|
FD_IDLE:
|
|
LD BC,(FCD_IDLECNT)
|
|
LD A,B
|
|
OR C
|
|
RET Z ; COUNTER ALREADY FIRED
|
|
|
|
DEC BC ; DECREMENT COUNTER
|
|
LD (FCD_IDLECNT),BC ; SAVE IT
|
|
LD A,B
|
|
OR C
|
|
RET NZ ; STILL COUNTING DOWN, RETURN
|
|
|
|
CALL FC_MOTOROFF ; COUNTER JUST EXPIRED, SHUTDOWN MOTOR!
|
|
RET
|
|
;
|
|
; FD_STATUS
|
|
;
|
|
FD_STATUS:
|
|
LD A,(IY+FD_CURTRK) ; A = CURRENT TRACK
|
|
|
|
CP 0FFH ; IS CURRENT TRACK = $FF?
|
|
JR Z,FD_STATUS1 ; IF SO, NOT READY
|
|
|
|
XOR A ; A = 0 = OK
|
|
RET ; RETURN
|
|
|
|
FD_STATUS1:
|
|
OR A ; A ALREADY = $FF, JUST SET FLAGS
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
FD_RESET:
|
|
XOR A ; ALWAYS OK
|
|
RET
|
|
;
|
|
; FD_CLRDSKCHG
|
|
;
|
|
FD_CLRDSKCHG:
|
|
; PROCESS ANY PENDING DISK CHANGE NOTIFICATIONS
|
|
LD B,5
|
|
FD_CLRDSKCHG1:
|
|
PUSH BC
|
|
CALL FC_SENSEINT
|
|
POP BC
|
|
LD A,(FST_RC)
|
|
CP FRC_DSKCHG
|
|
RET NZ ; NO MORE DISK CHANGE NOTIFICATIONS
|
|
DJNZ FD_CLRDSKCHG1
|
|
;
|
|
; FD_WTSEEK
|
|
;
|
|
; WAIT FOR PENDING SEEK OPERATION TO COMPLETE BY POLLING SENSEINT
|
|
; AND WAITING FOR ABTERM OR OK.
|
|
;
|
|
FD_WTSEEK:
|
|
LD BC,1000H
|
|
|
|
FD_WTSEEKLOOP:
|
|
PUSH BC
|
|
CALL FC_SENSEINT
|
|
POP BC
|
|
|
|
LD A,(FST_RC) ; CHECK RC
|
|
CP FRC_ABTERM ; ABTERM = DONE/FAILED
|
|
JR Z,FD_RETRC
|
|
CP FRC_OK ; OK = DONE/SUCCESS
|
|
JR Z,FD_RETRC
|
|
|
|
DEC BC ; CHECK LOOP COUNTER IN BC
|
|
LD A,B ; "
|
|
OR C ; "
|
|
JR NZ,FD_WTSEEKLOOP ; LOOP UNTIL COUNTER EXHAUSTED
|
|
|
|
FD_RETRC:
|
|
LD A,(FST_RC)
|
|
OR A
|
|
RET ; TIMEOUT/FAILED
|
|
;
|
|
; FD_FDCRESET
|
|
;
|
|
FD_FDCRESET:
|
|
CALL FC_RESETFDC
|
|
|
|
CALL FD_CLRDSKCHG
|
|
|
|
LD A,TRUE
|
|
LD (FCD_FDCRDY),A
|
|
|
|
; MARK ALL DRIVES AS NEEDING RECALIBRATION
|
|
; NOTE THAT IF THE VALUE IS CURRENT $FF,
|
|
; WE NEED TO LEAVE IT ALONE, SO WE 'OR' IN THE
|
|
; $FE TO AVOID THIS SCENARIO.
|
|
|
|
PUSH IY ; SAVE CURRENT IY
|
|
LD B,FD_DEVCNT ; LOOP CONTROL
|
|
LD DE,FD_CFGSIZ ; SIZE OF CFG ENTRY
|
|
LD IY,FD_CFGTBL ; START OF CFG TABLE
|
|
FD_FDCRESET1:
|
|
LD A,(IY+FD_CURTRK) ; GET CURRENT TRACK
|
|
OR $FE ; APPLY NEW VALUE
|
|
LD (IY+FD_CURTRK),A ; UPDATE TRACK
|
|
ADD IY,DE ; BUMP IY TO NEXT ENTRY
|
|
DJNZ FD_FDCRESET1 ; LOOP AS NEEDED
|
|
POP IY ; RESTORE IY
|
|
|
|
RET
|
|
;
|
|
; FD_DRIVERESET
|
|
;
|
|
; ATTEMPT TO FULLY RESET FLOPPY DRIVE, PRIMARILY RECALIBRATE
|
|
;
|
|
FD_DRIVERESET:
|
|
CALL FC_SPECIFY
|
|
RET NZ ; ERROR, BAIL OUT
|
|
|
|
CALL FC_RECAL
|
|
RET NZ ; ERROR, BAIL OUT
|
|
|
|
; FIRST RECAL MAY FAIL TO REACH TRACK 0
|
|
; SO WE TRY ONCE MORE IN CASE OF A FAILURE
|
|
CALL FD_WTSEEK
|
|
RET Z
|
|
|
|
; SECOND TRY, ONLY IF NEEDED
|
|
CALL FC_RECAL
|
|
RET NZ ; ERROR, BAIL OUT
|
|
|
|
CALL FD_WTSEEK
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
FD_SEEK:
|
|
; DE:HL CONTAINS EITHER LBA OR CHS
|
|
BIT 7,D ; TEST LBA BIT
|
|
JR Z,FD_SEEK9 ; IF NOT LBA, JUST SAVE INCOMING VALUE
|
|
; NEED TO CONVERT LBA IN DE:HL TO CHS
|
|
; NOTE: FLOPPY LBA WILL NEVER EXCEED 16 BITS, SO WE IGNORE DE ENTIRELY
|
|
PUSH HL ; SAVE HL
|
|
CALL FD_GEOM ; E := SPT, D := HDS
|
|
POP HL ; RESTORE HL
|
|
RET NZ ; BAIL OUT ON ERROR
|
|
RES 7,D ; MAKE SURE LBA BIT IS CLEARED
|
|
LD (FD_CURGEOM),DE ; SAVE AS FD_CURSPT & FD_CURHDS
|
|
LD A,(FD_CURSPT) ; A := SECTORS PER TRACK
|
|
LD D,0 ; DE := SPT
|
|
LD E,A
|
|
CALL DIV16 ; DIVIDE, REMAINDER (SECTOR #) IN HL
|
|
PUSH HL ; SAVE SECTOR #
|
|
PUSH BC ; CYLINDERS AND HEADS BACK TO HL
|
|
POP HL
|
|
LD A,(FD_CURHDS) ; A := HEADS PER CYLINDER
|
|
LD D,0 ; DE : = HEADS PER CYLINDER
|
|
LD E,A
|
|
CALL DIV16 ; DIVIDE, BC := TRACK, REMAINDER (HEAD #) IN HL
|
|
PUSH HL ; SAVE HEAD #
|
|
PUSH BC ; COPY TRACK # TO HL
|
|
POP HL
|
|
POP BC ; RECOVER HEAD #
|
|
LD D,C ; HEAD # TO D
|
|
POP BC ; RECOVER SECTOR #
|
|
LD E,C ; SECTOR # TO E
|
|
FD_SEEK9: ; NOT LBA, JUST SAVE THE CHS VALUE IN CFG ENTRY
|
|
PUSH HL ; SAVE INCOMING HL TO (SP)
|
|
LD A,FD_HST ; A := HST OFFSET IN CFG ENTRY
|
|
CALL LDHLIYA ; HL := HST VALUE ADR
|
|
EX (SP),HL ; RESTORE INCOMING HL, HST ADR TO (SP)
|
|
POP BC ; HST ADR TO BC
|
|
CALL ST32 ; SAVE HST IN CFG ENTRY
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
FD_READ:
|
|
CALL HB_DSKREAD ; HOOK HBIOS DISK READ SUPERVISOR
|
|
LD (FD_DSKBUF),HL ; SAVE DISK BUFFER ADDRESS
|
|
LD A,DOP_READ
|
|
JR FD_RW
|
|
;
|
|
FD_WRITE:
|
|
CALL HB_DSKWRITE ; HOOK HBIOS DISK WRITE SUPERVISOR
|
|
LD (FD_DSKBUF),HL ; SAVE DISK BUFFER ADDRESS
|
|
LD A,DOP_WRITE
|
|
JR FD_RW
|
|
;
|
|
FD_RW:
|
|
LD (FCD_DOP),A ; SAVE REQUESTED DISK OPERATION
|
|
LD A,E ; BLOCK COUNT TO A
|
|
OR A ; SET FLAGS
|
|
RET Z ; ZERO SECTOR I/O, RETURN W/ E=0 & A=0
|
|
LD B,A ; INIT SECTOR DOWNCOUNTER
|
|
LD C,0 ; INIT SECTOR READ/WRITE COUNT
|
|
|
|
PUSH BC ; SAVE COUNTERS
|
|
CALL FD_GEOM ; E := SPT, D := HDS
|
|
POP BC ; RESTORE COUNTERS
|
|
JR NZ,FD_RW4 ; BAIL OUT ON ERROR
|
|
RES 7,D ; MAKE SURE LBA BIT IS CLEARED
|
|
LD (FD_CURGEOM),DE ; SAVE AS FD_CURSPT & FD_CURHDS
|
|
|
|
FD_RW1:
|
|
PUSH BC ; SAVE COUNTERS
|
|
CALL FD_RUN ; PERFORM SECTOR READ/WRITE
|
|
JR NZ,FD_RW3 ; IF ERROR, SKIP INCREMENT
|
|
|
|
; INCREMENT SECTOR AND CHECK FOR TRACK OVERFLOW
|
|
LD A,FD_HSTSEC ; HST SECTOR OFFSET IN CFG
|
|
CALL LDHLIYA ; HL := ADR OF HST SECTOR
|
|
INC (HL) ; INCREMENT SECTOR
|
|
LD A,(FD_CURSPT) ; A := SECTORS PER TRACK
|
|
CP (HL) ; COMPARE SPT TO CURRENT SECTOR
|
|
JR NZ,FD_RW2 ; IF NO OVERFLOW, DONE
|
|
|
|
; RESET SECTOR, INCREMENT HEAD, AND CHECK FOR CYLINDER OVERFLOW
|
|
LD (HL),0 ; RESET SECTOR TO ZERO
|
|
INC HL ; POINT TO HST HEAD
|
|
INC (HL) ; INCREMENT HEAD
|
|
LD A,(FD_CURHDS) ; A : = HEADS
|
|
CP (HL) ; COMPARE HEADS TO HST HEAD
|
|
JR NZ,FD_RW2 ; IF NO OVERFLOW, DONE
|
|
|
|
; RESET HEAD AND INCREMENT TRACK
|
|
LD (HL),0 ; RESET HEAD TO ZERO
|
|
DEC HL ; POINT TO HST TRACK
|
|
DEC HL ; ...
|
|
DEC HL ; ...
|
|
INC (HL) ; INCREMENT HST TRACK LSB
|
|
|
|
FD_RW2:
|
|
LD HL,FD_DSKBUF+1 ; POINT TO MSB OF BUFFER ADR
|
|
INC (HL) ; BUMP DMA BY
|
|
INC (HL) ; ... 512 BYTES
|
|
XOR A ; SIGNAL SUCCESS
|
|
FD_RW3:
|
|
POP BC ; RECOVER COUNTERS
|
|
JR NZ,FD_RW4 ; IF ERROR, BAIL OUT
|
|
INC C ; BUMP COUNT OF SECTORS READ
|
|
DJNZ FD_RW1 ; LOOP AS NEEDED
|
|
FD_RW4:
|
|
LD E,C ; SECTOR READ COUNT TO E
|
|
LD HL,(FD_DSKBUF) ; CURRENT DMA TO HL
|
|
OR A ; SET FLAGS BASED ON RETURN CODE
|
|
RET ; AND RETURN, A HAS RETURN CODE
|
|
|
|
;
|
|
FD_RUN:
|
|
; UPDATE DRIVE SELECTION
|
|
LD A,(IY+FD_DEV) ; GET UNIT
|
|
LD (FCD_DS),A ; UPDATE FCD_DS TO NEW VALUE
|
|
|
|
; MAP HSTTRK TO FCD_H, FCD_C
|
|
LD A,(IY+FD_HSTTRK) ; GET TRACK VALUE (CYLINDER IS MORE ACCURATE)
|
|
LD (FCD_C),A ; ... AND MOVE IT TO CYL PARM
|
|
LD A,(IY+FD_HSTHD) ; GET HEAD VALUE
|
|
LD (FCD_H),A ; ... AND MOVE IT TO HEAD PARM
|
|
|
|
; MAP HSTSEC TO FCD_R
|
|
LD A,(IY+FD_HSTSEC)
|
|
INC A ; SWITCH FROM ZERO BASED TO ONE BASED
|
|
LD (FCD_R),A
|
|
|
|
; SET RETRY COUNTER
|
|
LD B,5
|
|
FD_RETRY:
|
|
PUSH BC
|
|
CALL FD_START
|
|
POP BC
|
|
|
|
LD A,(FST_RC) ; CHECK RESULT
|
|
OR A
|
|
RET Z ; SUCCESS
|
|
|
|
DJNZ FD_RETRY ; RETRY TILL COUNTER EXHAUSTED
|
|
|
|
#IF (FDTRACE == 1)
|
|
CALL FC_PRTRESULTS
|
|
#ENDIF
|
|
|
|
LD A,(FST_RC)
|
|
OR A ; OTHERWISE SET FLAGS BASED ON RC (IN A)
|
|
RET ; AND GIVE UP
|
|
;
|
|
;
|
|
;
|
|
FD_START:
|
|
LD A,(FCD_FDCRDY)
|
|
CP TRUE
|
|
CALL NZ,FD_FDCRESET
|
|
|
|
; COPY MEDIA CONFIG INTO FCD
|
|
; THIS IS HERE TO ACCOMMODATE DIFFERENT MEDIA
|
|
; IN DIFFERENT FLOPPY UNITS.
|
|
LD A,(IY+FD_MEDTYP) ; A = MEDIA BYTE
|
|
RLCA ; TABLE IS 4 BYTE ENTRIES
|
|
RLCA ; A = A * 4
|
|
LD HL,FCD_TBL ; HL = START OF TABLE
|
|
LD D,0 ; SET DE TO TABLE OFFSET
|
|
LD E,A
|
|
ADD HL,DE ; OFFSET BASED ON DESIRED MEDIA
|
|
CALL JPHL ; CALL THE TABLE ENTRY (SEE FCD_TBL)
|
|
LD DE,FCD ; DE = DESTINATION
|
|
LD BC,FCD_LEN ; BC = BYTES TO COPY
|
|
LDIR ; BYTES COPY FROM MDB TO FCD
|
|
|
|
CALL FC_MOTORON ; INCLUDES LATCH SETUP
|
|
|
|
LD A,(IY+FD_CURTRK)
|
|
CP 0FEH ; FF = DRIVE NEEDS TO BE RESET
|
|
JR C,FD_RUN0 ; NO RESET NEEDED, BYPASS
|
|
|
|
CALL FD_DRIVERESET
|
|
JR NZ,FD_RUNERR
|
|
|
|
LD (IY+FD_CURTRK),0 ; ZERO CUR TRACK POS
|
|
|
|
FD_RUN0:
|
|
; COMPARE CURRENT TRACK WITH REQUESTED TRACK TO SEE IF SEEK NEEDED
|
|
LD A,(FCD_C)
|
|
CP (IY+FD_CURTRK)
|
|
JR Z,FD_RUN1 ; FDDS_TRKADR == FCD_C, SKIP SEEK
|
|
|
|
; INITIATE SEEK TO NEW TRACK
|
|
CALL FC_SEEK
|
|
JR NZ,FD_RUNERR
|
|
|
|
; WAIT FOR SEEK TO COMPLETE
|
|
CALL FD_WTSEEK
|
|
JR NZ,FD_RUNERR
|
|
|
|
; RECORD NEW CURRENT TRACK
|
|
LD A,(FCD_C)
|
|
LD (IY+FD_CURTRK),A
|
|
|
|
FD_RUN1:
|
|
; GET THE REQUESTED OPERATION
|
|
LD A,(FCD_DOP)
|
|
|
|
; SETUP RETURN ADDRESS
|
|
LD HL,FD_RUNCHK
|
|
PUSH HL
|
|
|
|
; DISPATCH TO FUNCTION
|
|
CP DOP_READ
|
|
JR Z,FC_READ
|
|
CP DOP_WRITE
|
|
JR Z,FC_WRITE
|
|
CP DOP_READID
|
|
JR Z,FC_READID
|
|
CALL PANIC
|
|
|
|
FD_RUNCHK:
|
|
#IF (DSKYENABLE)
|
|
CALL FD_DSKY
|
|
#ENDIF
|
|
|
|
FD_RUNEXIT:
|
|
LD A,(FST_RC)
|
|
OR A
|
|
RET Z
|
|
|
|
FD_RUNERR:
|
|
; INDICATE THAT A CONTROLLER RESET IS DESIRED
|
|
LD A,FALSE
|
|
LD (FCD_FDCRDY),A
|
|
|
|
; FLAG DRIVE IN ERROR STATUS BY SETTING TRKADR == FF
|
|
LD (IY+FD_CURTRK),$FF
|
|
|
|
JP FD_RETRC
|
|
|
|
#IF (DSKYENABLE)
|
|
FD_DSKY:
|
|
LD HL,DSKY_HEXBUF
|
|
LD A,(FCD_C)
|
|
LD (HL),A
|
|
INC HL
|
|
LD A,(FCD_R)
|
|
LD (HL),A
|
|
INC HL
|
|
LD A,(FRB_ST0)
|
|
LD (HL),A
|
|
INC HL
|
|
LD A,(FRB_ST1)
|
|
LD (HL),A
|
|
CALL DSKY_HEXOUT
|
|
RET
|
|
#ENDIF
|
|
;
|
|
;===============================================================================
|
|
; FLOPPY DISK CONTROL SERVICES (PHYSICAL DEVICE CONTROL FOR FDC HARDWARE)
|
|
;===============================================================================
|
|
;
|
|
; ENTRY POINTS FOR FDC COMMANDS
|
|
;
|
|
FC_READ:
|
|
LD A,CFD_READ | 11100000B
|
|
CALL FC_SETUPIO
|
|
JP FOP
|
|
|
|
FC_WRITE:
|
|
LD A,CFD_WRITE | 11000000B
|
|
CALL FC_SETUPIO
|
|
JP FOP
|
|
|
|
FC_READID:
|
|
LD A,CFD_READID | 01000000B
|
|
CALL FC_SETUPCMD
|
|
JP FOP
|
|
|
|
FC_RECAL:
|
|
LD A,CFD_RECAL | 00000000B
|
|
CALL FC_SETUPCMD
|
|
JP FOP ; FIX: DO WE NEED TO REMOVE HDS BITS FROM SECOND BYTE?
|
|
|
|
FC_SENSEINT:
|
|
LD A,CFD_SENSEINT | 00000000B
|
|
CALL FC_SETUPCMD
|
|
LD A,1 ; GENERIC COMMAND, BUT JUST FIRST COMMAND CODE
|
|
LD (FCP_LEN),A
|
|
JP FOP
|
|
|
|
FC_SPECIFY:
|
|
LD A,CFD_SPECIFY | 00000000B
|
|
CALL FC_SETUPSPECIFY
|
|
JP FOP
|
|
|
|
FC_DRVSTAT:
|
|
LD A,CFD_DRVSTAT | 00000000B
|
|
CALL FC_SETUPCMD
|
|
JP FOP
|
|
|
|
FC_SEEK:
|
|
LD A,CFD_SEEK | 00000000B
|
|
CALL FC_SETUPSEEK
|
|
JP FOP
|
|
;
|
|
; HELPER FUNCTIONS TO SETUP CMDBUF
|
|
;
|
|
FC_SETUPCMD:
|
|
; TRICKY... THE INCOMING BYTE IN A MUST CONTAIN THE COMMAND CODE ITSELF
|
|
; IN THE LOW 5 BITS PLUS IT MUST SET WHICH OF THE DESIRED BITS IT WANTS
|
|
; IN THE HIGH 3 BITS. WE 'AND' THIS WITH THE TEMPATE BITS TO PRODUCE
|
|
; THE CORRECT FINAL COMMAND BYTE
|
|
LD DE,FCP_BUF
|
|
AND 5FH ; MT=0, MFM=1, SK=0, CMD=11111
|
|
LD (DE),A ; SAVE THE BYTE
|
|
AND 00011111B ; ISOLATE JUST THE COMMAND BITS
|
|
LD (FCP_CMD),A ; SAVE IT FOR LATER
|
|
INC DE
|
|
|
|
LD A,(FCD_H) ; START WITH HDS
|
|
AND 01H ; MASK TO REMOVE IRRELEVANT BITS FOR SAFETY
|
|
RLCA ; MAKE ROOM FOR DS BITS
|
|
RLCA ;
|
|
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 ; LENGTH IS 2 BYTES AT THIS POINT
|
|
LD (FCP_LEN),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
|
|
|
|
LD A,(FCD_EOT)
|
|
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_LEN),A
|
|
|
|
RET
|
|
|
|
FC_SETUPSEEK:
|
|
CALL FC_SETUPCMD ; START WITH GENERIC IO CMD
|
|
|
|
LD A,(FCD_C)
|
|
LD (DE),A
|
|
INC DE
|
|
|
|
LD A,3
|
|
LD (FCP_LEN),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_HLTND)
|
|
LD (DE),A ; SAVE THE BYTE
|
|
INC DE
|
|
|
|
LD A,3
|
|
LD (FCP_LEN),A
|
|
|
|
RET
|
|
;
|
|
; SET FST_DOR
|
|
;
|
|
FC_SETDOR
|
|
LD (FST_DOR),A
|
|
OUT (FDC_DOR),A
|
|
#IF (FDTRACE >= 3)
|
|
CALL NEWLINE
|
|
LD DE,FDSTR_DOR
|
|
CALL WRITESTR
|
|
LD DE,FDSTR_ARROW
|
|
CALL WRITESTR
|
|
CALL PC_SPACE
|
|
LD A,(FST_DOR)
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
RET
|
|
;
|
|
; SET FST_DCR
|
|
;
|
|
#IF ((FDMODE == FDMODE_DIDE) | (FDMODE == FDMODE_N8) | (FDMODE == FDMODE_ZETA2) | (FDMODE == FDMODE_RCWDC))
|
|
;
|
|
FC_SETDCR
|
|
LD (FST_DCR),A
|
|
OUT (FDC_DCR),A
|
|
#IF (FDTRACE >= 3)
|
|
CALL NEWLINE
|
|
LD DE,FDSTR_DCR
|
|
CALL WRITESTR
|
|
LD DE,FDSTR_ARROW
|
|
CALL WRITESTR
|
|
CALL PC_SPACE
|
|
LD A,(FST_DCR)
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
RET
|
|
;
|
|
#ENDIF
|
|
;
|
|
; RESET FDC BY PULSING BIT 7 OF LATCH LOW
|
|
;
|
|
FC_RESETFDC:
|
|
#IF (FDTRACE >= 3)
|
|
LD DE,FDSTR_RESETFDC
|
|
CALL WRITESTR
|
|
#ENDIF
|
|
LD A,(FST_DOR)
|
|
PUSH AF
|
|
|
|
#IF ((FDMODE == FDMODE_ZETA) | (FDMODE == FDMODE_DIO3) | (FDMODE == FDMODE_RCSMC))
|
|
RES 7,A
|
|
#ENDIF
|
|
#IF ((FDMODE == FDMODE_DIDE) | (FDMODE == FDMODE_N8) | (FDMODE == FDMODE_ZETA2) | (FDMODE == FDMODE_RCWDC))
|
|
LD A,0
|
|
#ENDIF
|
|
CALL FC_SETDOR
|
|
CALL DELAY
|
|
POP AF
|
|
CALL FC_SETDOR
|
|
|
|
LD DE,150 ; DELAY: 16us * 150 = 2.4ms
|
|
CALL VDELAY
|
|
RET
|
|
;
|
|
; PULSE TERMCT TO TERMINATE ANY ACTIVE EXECUTION PHASE
|
|
;
|
|
FC_PULSETC:
|
|
#IF ((FDMODE == FDMODE_DIDE) | (FDMODE == FDMODE_N8) | (FDMODE == FDMODE_ZETA2) | (FDMODE == FDMODE_RCWDC))
|
|
IN A,(FDC_TC)
|
|
#ELSE
|
|
LD A,(FST_DOR)
|
|
SET 0,A
|
|
OUT (FDC_DOR),A
|
|
RES 0,A
|
|
OUT (FDC_DOR),A
|
|
#ENDIF
|
|
RET
|
|
;
|
|
; SET FST_DOR FOR MOTOR CONTROL ON
|
|
;
|
|
FC_MOTORON:
|
|
LD BC,300H
|
|
; LD BC,10H
|
|
LD (FCD_IDLECNT),BC
|
|
|
|
#IF (FDTRACE >= 3)
|
|
LD DE,FDSTR_MOTON
|
|
CALL WRITESTR
|
|
#ENDIF
|
|
#IF ((FDMODE == FDMODE_DIO) | (FDMODE == FDMODE_ZETA) | (FDMODE == FDMODE_DIO3))
|
|
LD A,(FST_DOR)
|
|
PUSH AF
|
|
|
|
LD A,(FCD_DOR) ; GET NEW LATCH VALUE (W/ MOTOR ON)
|
|
CALL FC_SETDOR ; AND IMPLEMENT IT
|
|
|
|
POP AF
|
|
#IF ((FDMODE == FDMODE_ZETA) | (FDMODE == FDMODE_DIO3))
|
|
XOR 00000010B ; MOTOR BIT INVERTED ON ZETA
|
|
#ENDIF
|
|
BIT 1,A ; SET FLAGS SET BASED ON CURRENT MOTOR BIT
|
|
RET Z ; MOTOR WAS PREVIOUSLY ON, WE ARE DONE
|
|
#ENDIF
|
|
#IF (FDMODE == FDMODE_RCSMC)
|
|
LD A,(FCD_DS) ; GET DRIVE SELECTED (0 OR 1)
|
|
LD C,%00000010 ; MASK FOR MOTORA ON (BIT 1 IS MOTORA)
|
|
OR A ; SET FLAGS BASED ON FCD_DS
|
|
JR Z,FC_MOTORON1 ; IF FCD_DS == 0, MOTORA IS CORRECT
|
|
LD C,%00000100 ; ELSE MASK FOR MOTORB ON (BIT 2 IS MOTORB)
|
|
FC_MOTORON1:
|
|
LD A,(FST_DOR) ; GET CURRENT DOR VALUE
|
|
PUSH AF ; SAVE IT
|
|
LD A,(FCD_DOR) ; GET NEW DOR VALUE (W/O MOTOR BITS SET)
|
|
OR C ; ADD THE MOTOR BITS
|
|
CALL FC_SETDOR ; AND IMPLEMENT NEW VALUE
|
|
POP AF ; RECOVER PREVIOUS DOR VALUE
|
|
AND %00000110 ; ISOLATE PREVIOUS MOTOR BITS
|
|
CP C ; COMPARE TO NEW MOTOR BITS
|
|
RET Z ; SKIP DELAY, MOTOR WAS ALREADY ON
|
|
#ENDIF
|
|
#IF ((FDMODE == FDMODE_DIDE) | (FDMODE == FDMODE_N8) | (FDMODE == FDMODE_ZETA2) | (FDMODE == FDMODE_RCWDC))
|
|
; SETUP DCR FOR DIDE HARDWARE
|
|
LD A,(FCD_DCR) ; GET NEW DCR VALUE
|
|
CALL FC_SETDCR ; AND IMPLEMENT IT
|
|
|
|
LD HL,FST_DOR ; POINT TO FDC_DOR
|
|
LD A,(HL) ; START WITH CURRENT DOR
|
|
PUSH AF
|
|
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_MOTORON1:
|
|
RLA ; SHIFT LEFT
|
|
DJNZ FC_MOTORON1 ; DS TIMES
|
|
OR C ; COMBINE WITH SAVED
|
|
LD (HL),A ; COMMIT THE NEW VALUE TO FST_DOR
|
|
CALL FC_SETDOR ; OUTPUT TO CONTROLLER
|
|
|
|
LD C,A
|
|
POP AF
|
|
CP C
|
|
RET Z ; MOTOR WAS PREVIOUSLY ON
|
|
#ENDIF
|
|
|
|
#IF (FDTRACE >= 3)
|
|
LD DE,FDSTR_MOTDELAY
|
|
CALL WRITESTR
|
|
#ENDIF
|
|
CALL LDELAY ; DELAY FOR MOTOR SPINUP IF NOT PREVIOUSLY ON
|
|
RET
|
|
;
|
|
; SET FST_DOR FOR MOTOR CONTROL OFF
|
|
;
|
|
FC_MOTOROFF:
|
|
LD A,(FCD_FDCRDY)
|
|
CP TRUE
|
|
CALL NZ,FD_FDCRESET
|
|
|
|
LD A,DOR_INIT
|
|
CALL FC_SETDOR ; OUTPUT TO CONTROLLER
|
|
|
|
#IF (FDTRACE >= 3)
|
|
LD DE,FDSTR_MOTOFF
|
|
CALL WRITESTR
|
|
#ENDIF
|
|
RET
|
|
;
|
|
;===============================================================================
|
|
; FDC OPERATIONS
|
|
;===============================================================================
|
|
;
|
|
FOP:
|
|
;
|
|
; INITIALIZATION
|
|
;
|
|
LD A,0
|
|
LD (FRB_LEN),A
|
|
|
|
LD A,FRC_OK
|
|
LD (FST_RC),A
|
|
;
|
|
; CLEAR FDC, DISCARD ANY PENDING BYTES (GARBAGE?)
|
|
;
|
|
LD B,0 ; B IS LOOP COUNTER
|
|
FOP_CLR1:
|
|
CALL DELAY ; FDC MAY TAKE UP TO 12us TO UPDATE MSR
|
|
IN A,(FDC_MSR) ; GET STATUS
|
|
AND 0C0H ; ISOLATE HIGH NIBBLE, RQM/DIO/NDM/CB
|
|
CP 0C0H ; LOOKING FOR RQM=1, DIO=1, BYTES PENDING
|
|
JR NZ,FOP_CMD1 ; NO BYTES PENDING, GO TO NEXT PHASE
|
|
IN A,(FDC_DATA) ; GET THE PENDING BYTE AND DISCARD
|
|
DJNZ FOP_CLR1
|
|
JP FOP_TOFDCRDY ; OTHERWISE, TIMEOUT
|
|
;
|
|
; SEND COMMAND
|
|
;
|
|
FOP_CMD1:
|
|
LD HL,FCP_BUF
|
|
LD A,(FCP_LEN)
|
|
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
|
|
IN A,(FDC_MSR) ; READ MAIN STATUS REGISTER
|
|
AND 0C0H ; ISOLATE RQM/DIO
|
|
CP 080H ; LOOKING FOR RQM=1, DIO=0 (FDC READY FOR A BYTE)
|
|
JR 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
|
|
OUT (FDC_DATA),A ; PUSH IT TO FDC
|
|
INC HL ; INCREMENT POINTER FOR NEXT TIME
|
|
DEC D ; DECREMENT NUM BYTES LEFT TO SEND
|
|
JR NZ,FOP_CMD2 ; DO NEXT BYTE
|
|
;
|
|
; EXECUTION PHASE
|
|
;
|
|
FOP_X1:
|
|
LD A,(FCP_CMD)
|
|
|
|
CP CFD_READ
|
|
JR Z,FXR_READ
|
|
CP CFD_WRITE
|
|
JR Z,FXR_WRITE
|
|
CP CFD_READID
|
|
JR Z,FXR_NULL
|
|
JP FOP_RES
|
|
;;
|
|
;; EXECUTION ROUTINES
|
|
;;
|
|
;
|
|
; NULL EXECUTION, NO DATA TO READ/WRITE (USED BY SPECIFY, READID, ETC.)
|
|
;
|
|
; DO NOTHING, BUT WAIT FOR EXEC B IT TO CLEAR FDC READY.
|
|
; LOOP NEEDS TO ALLOW FOR 2 FULL ROTATIONS OF THE DISK
|
|
; WHICH IS 400ms AT 300RPM
|
|
;
|
|
FXR_NULL:
|
|
LD BC,$7000 ; LOOP COUNTER, $7000 * 16us = ~485ms
|
|
FXR_NULL1:
|
|
CALL DELAY ; FDC MAY TAKE UP TO 12us TO UPDATE MSR
|
|
IN A,(FDC_MSR) ; GET MSR
|
|
AND 0E0H ; ISOLATE RQM/DIO/NDM
|
|
CP 0C0H ; WE WANT RQM=1,DIO=1,NDM=0 (READY TO READ A BYTE W/ EXEC INACTIVE)
|
|
JP Z,FOP_RES ; EXEC DONE, EXIT CLEAN W/O PULSING TC
|
|
;JP Z,FXR_NULL2 ; *DEBUG*
|
|
DEC BC ; DECREMENT COUNTER (16 BIT)
|
|
LD A,B ; CHECK FOR ZERO
|
|
OR C ; "
|
|
JR NZ,FXR_NULL1 ; NOT ZERO YET, KEEP CHECKING
|
|
JP FOP_TOEXEC ; TIMEOUT EXIT
|
|
;FXR_NULL2: ; *DEBUG*
|
|
; CALL PRTHEXBYTE
|
|
; CALL PRTHEXWORD
|
|
; JP FOP_RES
|
|
;
|
|
; READ DATA
|
|
;
|
|
FXR_READ:
|
|
HB_DI ; TIME CRITICAL , INTERRUPTS WILL CAUSE I/O ERRS
|
|
LD HL,(FD_DSKBUF) ; POINT TO SECTOR BUFFER START
|
|
LD DE,(FCD_SECSZ)
|
|
; TIMEOUT COUNTER IS CPU MHZ / 4 (MAKING SURE IT IS AT LEAST 1)
|
|
; LD A,(CPUMHZ + 3) / 4
|
|
LD A,(CB_CPUMHZ) ; GET CPU SPEED IN MHZ
|
|
ADD A,3 ; ROUND UP
|
|
SRL A ; SHIFT RIGHT TWICE
|
|
;SRL A ; ... TO DIVIDE BY 4
|
|
;INC A ; MAKE SURE RESULT IS AT LEAST 1
|
|
LD (FCD_TO),A ; INIT TIMEOUT COUNTER
|
|
FXRR1 LD C,0 ; OUTER LOOP TIMEOUT COUNTER
|
|
FXRR2: LD B,0 ; SETUP FOR 256 ITERATIONS
|
|
FXRR3: IN A,(FDC_MSR) ; GET MSR
|
|
CP 0F0H ; WE WANT RQM=1,DIO=1,NDM=1,BUSY=1 (READY TO RECEIVE A BYTE W/ EXEC ACTIVE)
|
|
JR Z,FXRR4 ; GOT IT, DO BYTE READ
|
|
DJNZ FXRR3 ; NOT READY, LOOP IF COUNTER NOT ZERO
|
|
JR FXRR5 ; COUNTER ZERO, GO TO OUTER LOOP LOGIC
|
|
|
|
FXRR4: IN A,(FDC_DATA) ; GET PENDING BYTE
|
|
LD (HL),A ; STORE IT IN BUFFER
|
|
INC HL ; INCREMENT THE BUFFER POINTER
|
|
DEC DE ; DECREMENT BYTE COUNT
|
|
LD A,D
|
|
OR E
|
|
JR NZ,FXRR2 ; IF NOT ZERO, REPEAT LOOP
|
|
JR FXR_END ; CLEAN EXIT
|
|
|
|
FXRR5: ; OUTER LOOP, REALLY ONLY HAPPENS WHEN WAITING FOR FIRST BYTE OR ABORTED
|
|
AND 0E0H ; ISOLATE RQM/DIO/NDM
|
|
CP 0C0H ; IF RQM=1, DIO=1, NDM=0 (EXECUTION ABORTED)
|
|
JR Z,FXR_ABORT ; BAIL OUT TO ERR ROUTINE, FIX: GO TO SPECIFIC ROUTINE FOR THIS???
|
|
DEC C
|
|
JR NZ,FXRR2 ; IF NOT ZERO, LOOP SOME MORE
|
|
LD A,(FCD_TO)
|
|
DEC A
|
|
LD (FCD_TO),A
|
|
JR NZ,FXRR1
|
|
JR FXR_TO ; OTHERWISE, TIMEOUT ERROR
|
|
;
|
|
; WRITE DATA
|
|
;
|
|
FXR_WRITE:
|
|
HB_DI ; TIME CRITICAL , INTERRUPTS WILL CAUSE I/O ERRS
|
|
LD HL,(FD_DSKBUF) ; POINT TO SECTOR BUFFER START
|
|
LD DE,(FCD_SECSZ)
|
|
; TIMEOUT COUNTER IS CPU MHZ / 4 (MAKING SURE IT IS AT LEAST 1)
|
|
; LD A,(CPUMHZ + 3) / 4
|
|
LD A,(CB_CPUMHZ) ; GET CPU SPEED IN MHZ
|
|
ADD A,3 ; ROUND UP
|
|
SRL A ; SHIFT RIGHT TWICE
|
|
;SRL A ; ... TO DIVIDE BY 4
|
|
;INC A ; MAKE SURE RESULT IS AT LEAST 1
|
|
LD (FCD_TO),A
|
|
FXRW1 LD C,0 ; OUTER LOOP TIMEOUT COUNTER
|
|
FXRW2: LD B,0 ; SETUP FOR 256 ITERATIONS
|
|
FXRW3: IN A,(FDC_MSR) ; GET MSR
|
|
CP 0B0H ; WE WANT RQM=1,DIO=0,NDM=1,BUSY=1 (READY TO SEND A BYTE W/ EXEC ACTIVE)
|
|
JR Z,FXRW4 ; GOT IT, DO BYTE WRITE
|
|
DJNZ FXRW3 ; NOT READY, LOOP IF COUNTER NOT ZERO
|
|
JR FXRW5 ; COUNTER ZERO, GO TO OUTER LOOP LOGIC
|
|
FXRW4: LD A,(HL) ; GET NEXT BYTE TO WRITE
|
|
OUT (FDC_DATA),A ; WRITE IT
|
|
INC HL ; INCREMENT THE BUFFER POINTER
|
|
DEC DE ; DECREMENT LOOP COUNTER
|
|
LD A,D
|
|
OR E
|
|
JR NZ,FXRW2 ; IF NOT ZERO, REPEAT LOOP
|
|
JR FXR_END ; CLEAN EXIT
|
|
FXRW5: ; OUTER LOOP, REALLY ONLY HAPPENS WHEN WAITING FOR FIRST BYTE OR ABORTED
|
|
AND 0E0H ; ISOLATE RQM/DIO/NDM
|
|
CP 0C0H ; IF RQM=1, DIO=1, NDM=0 (EXECUTION ABORTED)
|
|
JR Z,FXR_ABORT ; BAIL OUT TO ERR ROUTINE
|
|
DEC C
|
|
JR NZ,FXRW2 ; IF NOT ZERO, LOOP SOME MORE
|
|
LD A,(FCD_TO)
|
|
DEC A
|
|
LD (FCD_TO),A
|
|
JR NZ,FXRW1
|
|
JR FXR_TO ; OTHERWISE, TIMEOUT ERROR
|
|
;
|
|
; COMMON COMPLETION CODE FOR ALL EXECUTION ROUTINES
|
|
;
|
|
FXR_TO: ; TIMEOUT
|
|
HB_EI ; INTERRUPTS OK AGAIN
|
|
JP FOP_TOEXEC ; EXEC TIMEOUT
|
|
;
|
|
FXR_ABORT: ; EXECUTION ABORTED
|
|
HB_EI ; INTERRUPTS OK AGAIN
|
|
JR FOP_RES ; GET RSEULTS, NO NEED TO PULSE TC
|
|
;
|
|
FXR_END: ; EXECUTION COMPLETED NORMALLY
|
|
CALL FC_PULSETC ; PULSE TC TO END EXECUTION
|
|
HB_EI ; INTERRUPTS OK AGAIN
|
|
JR FOP_RES ; GET RSEULTS
|
|
;
|
|
; RESULTS PHASE
|
|
;
|
|
FOP_RES:
|
|
LD HL,FRB ; POINT TO RECEIVE BUFFER
|
|
|
|
FOP_RES0:
|
|
LD BC,$7000 ; LOOP COUNTER, $7000 * 16us = ~458ms
|
|
|
|
FOP_RES1:
|
|
CALL DELAY ; FDC MAY TAKE UP TO 12us TO UPDATE MSR
|
|
IN A,(FDC_MSR) ; READ MAIN STATUS REGISTER
|
|
AND 0F0H ; ISOLATE RQM/DIO/EXEC/BUSY
|
|
CP 0D0H ; LOOKING FOR RQM/DIO/BUSY
|
|
JR Z,FOP_RES2 ; GOOD, GO TO RECEIVE BYTE
|
|
CP 080H ; CHECK FOR RQM=1, DIO=0 (NOTHING LEFT)
|
|
JR Z,FOP_EVAL ; IF NOTHING LEFT, ALL DONE, GO TO EOD/EXIT
|
|
DEC BC ; DECREMENT COUNTER (16 BIT)
|
|
LD A,B ; CHECK FOR ZERO
|
|
OR C ; ""
|
|
JR NZ,FOP_RES1 ; LOOP TILL COUNTER EXHAUSTED
|
|
;IN A,(FDC_MSR) ; *DEBUG*
|
|
;CALL PRTHEXBYTE ; *DEBUG*
|
|
JR FOP_TOGETRES ; OTHERWISE TIMEOUT ERROR
|
|
|
|
FOP_RES2: ; PROCESS NEXT PENDING BYTE
|
|
LD A,FRB_SIZ ; GET BUF SIZE
|
|
CP D ; REACHED MAX?
|
|
JR Z,FOP_BUFMAX ; HANDLE BUF MAX/EXIT
|
|
IN A,(FDC_DATA) ; GET THE BYTE
|
|
LD (HL),A ; SAVE VALUE
|
|
INC HL ; INCREMENT BUF POS
|
|
INC D ; INCREMENT BYTES RECEIVED
|
|
PUSH HL
|
|
LD HL,FRB_LEN ; POINT TO BUFFER LENGTH
|
|
LD (HL),D ; UPDATE NUMBER OF BYTES RECEIVED
|
|
POP HL
|
|
JR FOP_RES0 ; CONTINUE READ LOOP
|
|
;
|
|
; EXIT POINTS
|
|
;
|
|
FOP_NOTIMPL:
|
|
LD A,FRC_NOTIMPL
|
|
JR FOP_ERR
|
|
|
|
FOP_CMDERR:
|
|
LD A,FRC_CMDERR
|
|
JR FOP_ERR
|
|
|
|
FOP_ERROR:
|
|
LD A,FRC_ERROR
|
|
JR FOP_ERR
|
|
|
|
FOP_ABORT:
|
|
LD A,FRC_ABORT
|
|
JR FOP_ERR
|
|
|
|
FOP_BUFMAX:
|
|
LD A,FRC_BUFMAX
|
|
JR FOP_ERR
|
|
|
|
FOP_TOFDCRDY:
|
|
LD A,FRC_TOFDCRDY
|
|
JR FOP_ERR
|
|
|
|
FOP_TOSNDCMD:
|
|
LD A,FRC_TOSNDCMD
|
|
JR FOP_ERR
|
|
|
|
FOP_TOGETRES:
|
|
LD A,FRC_TOGETRES
|
|
JR FOP_ERR
|
|
|
|
FOP_TOEXEC:
|
|
LD A,FRC_TOEXEC
|
|
JR FOP_ERR
|
|
|
|
FOP_ERR:
|
|
LD (FST_RC),A
|
|
|
|
FOP_EVAL:
|
|
LD A,(FCP_CMD)
|
|
; DRVSTAT IS WEIRD, HAS ONLY ST3, NOTHING TO EVAL
|
|
CP CFD_DRVSTAT
|
|
JR 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 CFD_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 C,FRC_ABTERM
|
|
JR FOP_SETFST
|
|
|
|
FOP_INVCMD:
|
|
LD C,FRC_INVCMD
|
|
JR FOP_SETFST
|
|
|
|
FOP_DSKCHG:
|
|
LD C,FRC_DSKCHG
|
|
JR FOP_SETFST
|
|
|
|
FOP_EVALST1:
|
|
LD A,(FRB_ST1)
|
|
|
|
LD C,FRC_ENDCYL
|
|
BIT 7,A
|
|
JR NZ,FOP_SETFST
|
|
|
|
LD C,FRC_DATAERR
|
|
BIT 5,A
|
|
JR NZ,FOP_SETFST
|
|
|
|
LD C,FRC_OVERRUN
|
|
BIT 4,A
|
|
JR NZ,FOP_SETFST
|
|
|
|
LD C,FRC_NODATA
|
|
BIT 2,A
|
|
JR NZ,FOP_SETFST
|
|
|
|
LD C,FRC_NOTWRIT
|
|
BIT 1,A
|
|
JR NZ,FOP_SETFST
|
|
|
|
LD C,FRC_MISADR
|
|
BIT 0,A
|
|
JR NZ,FOP_SETFST
|
|
|
|
JR FOP_EXIT
|
|
|
|
FOP_SETFST:
|
|
LD A,C
|
|
LD (FST_RC),A
|
|
|
|
FOP_EXIT:
|
|
#IF (FDTRACE >= 2)
|
|
CALL FC_PRTRESULTS
|
|
#ENDIF
|
|
JP FD_RETRC
|
|
|
|
#IF (FDTRACE > 0)
|
|
;
|
|
;===============================================================================
|
|
; 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
|
|
JR 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
|
|
JR 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
|
|
JR 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
|
|
JR 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
|
|
RET Z ; IF TRACE = 0, BE SILENT!
|
|
|
|
CP 3 ; IS TRACE >= 3 ?
|
|
JR NC,FCPR2 ; YES, SO FORCE PRINT EVERYTHING!
|
|
|
|
; 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 CFD_SENSEINT
|
|
JR NZ,FCPR2
|
|
|
|
LD A,(FST_RC)
|
|
CP FRC_INVCMD
|
|
JR Z,FCPR_EXIT
|
|
CP FRC_DSKCHG
|
|
JR Z,FCPR_EXIT
|
|
CP FRC_ABTERM
|
|
JR Z,FCPR_EXIT
|
|
JR FCPR_EXIT
|
|
|
|
FCPR2:
|
|
CALL NEWLINE
|
|
|
|
LD DE,FDSTR_FD
|
|
CALL WRITESTR
|
|
CALL PC_COLON
|
|
CALL PC_SPACE
|
|
|
|
CALL FC_PRTCMD
|
|
|
|
LD A,(FCP_LEN)
|
|
LD DE,FCP_BUF
|
|
CALL PRTHEXBUF
|
|
|
|
LD DE,FDSTR_ARROW
|
|
CALL WRITESTR
|
|
|
|
LD A,(FRB_LEN)
|
|
LD DE,FRB
|
|
CALL PRTHEXBUF
|
|
|
|
LD A,(FST_RC)
|
|
CALL FC_PRTFST
|
|
|
|
FCPR_EXIT:
|
|
RET
|
|
;
|
|
; STRING CONSTANTS
|
|
;
|
|
FDSTR_ARROW .TEXT " -->$"
|
|
FDSTR_NORESP .TEXT "DRIVE NOT RESPONDING$"
|
|
FDSTR_FD .TEXT "FD$"
|
|
#IF (FDTRACE >= 3)
|
|
FDSTR_MOTON .TEXT "\r\nMOTOR ON$"
|
|
FDSTR_MOTOFF .TEXT "\r\nMOTOR OFF$"
|
|
FDSTR_MOTDELAY .TEXT "\r\nMOTOR DELAY$"
|
|
FDSTR_DOR .TEXT "DOR$"
|
|
FDSTR_DCR .TEXT "DCR$"
|
|
FDSTR_RESETFDC .TEXT "\r\nRESET FDC$"
|
|
FDSTR_SELECT .TEXT "\r\nSELECT: $"
|
|
#ENDIF ; (FDTRACE >= 3)
|
|
#ENDIF ; (FDTRACE > 0)
|
|
;
|
|
;
|
|
;==================================================================================================
|
|
; FLOPPY DISK DRIVER - DATA
|
|
;==================================================================================================
|
|
;
|
|
; FDC COMMAND PHASE
|
|
;
|
|
FCP_CMD .DB 000H
|
|
FCP_LEN .DB 00H
|
|
FCP_BUF:
|
|
FCP_CMDX .DB 0
|
|
FCP_HDSDS .DB 0
|
|
FCP_C .DB 0
|
|
FCP_H .DB 0
|
|
FCP_R .DB 0
|
|
FCP_N .DB 0
|
|
FCP_EOT .DB 0
|
|
FCP_GPL .DB 0
|
|
FCP_DTL .DB 0
|
|
FCP_BUFSIZ .EQU $-FCP_BUF
|
|
;
|
|
; FDC STATUS
|
|
;
|
|
FST_RC .DB 00H
|
|
FST_DOR .DB 00H
|
|
FST_DCR .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
|
|
FRB_SIZ .EQU $-FRB
|
|
;
|
|
; FDC COMMAND DATA
|
|
;
|
|
FCD: ; FLOPPY CONFIGURATION DATA (PUBLIC) MANAGED AS A "BLOCK"
|
|
FCD_NUMCYL .DB 000H ; NUMBER OF CYLINDERS
|
|
FCD_NUMHD .DB 000H ; NUMBER OF HEADS
|
|
FCD_NUMSEC .DB 000H ; NUMBER OF SECTORS
|
|
FCD_SOT .DB 000H ; START OF TRACK (ID OF FIRST SECTOR, USUALLY 1)
|
|
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_HLTND .DB 000H ; HEAD LOAD TIME, IBM PS/2 CALLS FOR 15ms 08H = 16ms HUT
|
|
FCD_DOR .DB 000H ; DOR VALUE
|
|
FCD_DCR .DB 000H ; DCR VALUE
|
|
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 ; DATA FILL BYTE
|
|
; STATUS MANAGEMENT
|
|
FCD_DOP .DB 0FFH ; CURRENT OPERATION (SEE DOP_...)
|
|
FCD_IDLECNT .DW 0 ; IDLE COUNT
|
|
FCD_TRACE .DB 0 ; TRACE LEVEL
|
|
FCD_TO .DB 0 ; TIMEOUT COUNTDOWN TIMER
|
|
FCD_FDCRDY .DB 0 ; FALSE MEANS FDC RESET NEEDED
|
|
;
|
|
; GENERAL WORKING STORAGE
|
|
;
|
|
FD_DSKBUF .DW 0
|
|
FD_CURGEOM .EQU $ ; TWO BYTES BELOW
|
|
FD_CURSPT .DB 0 ; CURRENT SECTORS PER TRACK
|
|
FD_CURHDS .DB 0 ; CURRENT HEADS |