forked from MirrorRepos/RomWBW
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2107 lines
51 KiB
2107 lines
51 KiB
;
|
|
;==================================================================================================
|
|
; 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
|
|
#IF (FDMODE == FDMODE_DYNO)
|
|
FDC_BASE .EQU $84
|
|
FDC_MSR .EQU FDC_BASE + $00 ; 8272 MAIN STATUS REGISTER
|
|
FDC_DATA .EQU FDC_BASE + $01 ; 8272 DATA PORT
|
|
FDC_DOR .EQU FDC_BASE + $02 ; DIGITAL OUTPUT REGISTER
|
|
FDC_DCR .EQU FDC_BASE + $03 ; CONFIGURATION CONTROL REGISTER
|
|
FDC_TC .EQU FDC_BASE + $02 ; TERMINAL COUNT (W/ DACK)
|
|
#ENDIF
|
|
#IF (FDMODE == FDMODE_EPFDC)
|
|
FDC_MSR .EQU $48 ; 8272 MAIN STATUS REGISTER
|
|
FDC_DATA .EQU $49 ; 8272 DATA PORT
|
|
FDC_DOR .EQU $4A ; DIGITAL OUTPUT REGISTER
|
|
FDC_DCR .EQU $4B ; CONFIGURATION CONTROL REGISTER
|
|
FDC_TC .EQU $4C ; TERMINAL COUNT (W/ DACK)
|
|
#ENDIF
|
|
#IF (FDMODE == FDMODE_MBC)
|
|
FDC_MSR .EQU $30 ; 8272 MAIN STATUS REGISTER
|
|
FDC_DATA .EQU $31 ; 8272 DATA PORT
|
|
FDC_DOR .EQU $36 ; DIGITAL OUTPUT REGISTER
|
|
FDC_DCR .EQU $35 ; CONFIGURATION CONTROL REGISTER
|
|
FDC_TC .EQU $37 ; 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 FDCNT ; 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) | (FDMODE == FDMODE_DYNO) | (FDMODE == FDMODE_EPFDC) | (FDMODE == FDMODE_MBC))
|
|
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:
|
|
SYSCHKERR(ERR_NOTIMPL) ; INVALID SUB-FUNCTION
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
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
|
|
LD H,FDMODE ; H := MODE
|
|
LD L,FDC_MSR ; L := BASE I/O ADDRESS
|
|
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
|
|
LD A,ERR_NOMEDIA ; SIGNAL ERROR
|
|
OR A ; SET FLAGS
|
|
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: MODE=$")
|
|
;
|
|
#IF (FDMODE == FDMODE_DIO)
|
|
PRTS("DIO$")
|
|
#ENDIF
|
|
;
|
|
#IF (FDMODE == FDMODE_ZETA)
|
|
PRTS("ZETA$")
|
|
#ENDIF
|
|
;
|
|
#IF (FDMODE == FDMODE_DIO3)
|
|
PRTS("DIO3$")
|
|
#ENDIF
|
|
;
|
|
#IF (FDMODE == FDMODE_ZETA2)
|
|
PRTS("ZETA2$")
|
|
#ENDIF
|
|
;
|
|
#IF (FDMODE == FDMODE_DIDE)
|
|
PRTS("DIDE$")
|
|
#ENDIF
|
|
;
|
|
#IF (FDMODE == FDMODE_N8)
|
|
PRTS("N8$")
|
|
#ENDIF
|
|
;
|
|
#IF (FDMODE == FDMODE_RCSMC)
|
|
PRTS("RCSMC$")
|
|
#ENDIF
|
|
;
|
|
#IF (FDMODE == FDMODE_RCWDC)
|
|
PRTS("RCWDC$")
|
|
#ENDIF
|
|
;
|
|
#IF (FDMODE == FDMODE_DYNO)
|
|
PRTS("DYNO$")
|
|
#ENDIF
|
|
;
|
|
#IF (FDMODE == FDMODE_EPFDC)
|
|
PRTS("EPFDC$")
|
|
#ENDIF
|
|
;
|
|
#IF (FDMODE == FDMODE_MBC)
|
|
PRTS("MBC$")
|
|
#ENDIF
|
|
;
|
|
PRTS(" IO=0x$")
|
|
LD A,FDC_MSR
|
|
CALL PRTHEXBYTE
|
|
CALL FD_DETECT ; CHECK FOR FDC
|
|
JR Z,FD_INIT00 ; CONTINUE IF FOUND
|
|
PRTS(" NOT PRESENT$") ; NOT ZERO, H/W NOT PRESENT
|
|
OR $FF ; SIGNAL FAILURE
|
|
RET ; BAIL OUT
|
|
;
|
|
FD_INIT00:
|
|
PRTS(" UNITS=$")
|
|
LD A, FD_DEVCNT + '0'
|
|
CALL COUT
|
|
;
|
|
; 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
|
|
;
|
|
; HARDWARE PRESENCE DETECTION
|
|
;
|
|
; CURRENTLY JUST DETERMINES IF FDC EXISTS AT PRE-DEFINED ADDRESS,
|
|
; DOES NOT ATTEMPT TO DETERMINE THE ACTUAL VARIANT.
|
|
;
|
|
FD_DETECT:
|
|
; BLINDLY RESET FDC (WHICH MAY OR MAY NOT EXIST)
|
|
LD A,DOR_INIT ; MAKE SURE INITIAL DOR VALUE IS SETUP
|
|
LD (FST_DOR),A ; AND PUT IN SHADOW REGISTER
|
|
CALL FC_RESETFDC ; RESET FDC
|
|
|
|
IN A,(FDC_MSR) ; READ MSR
|
|
;CALL PC_SPACE ; *DEBUG*
|
|
;CALL PRTHEXBYTE ; *DEBUG*
|
|
CP $80
|
|
JR Z,FD_DETECT1 ; $80 IS OK
|
|
CP $D0
|
|
JR Z,FD_DETECT1 ; $D0 IS OK
|
|
RET ; NOPE, ABORT WITH ZF=NZ
|
|
;
|
|
FD_DETECT1:
|
|
CALL DLY32 ; WAIT A BIT FOR FDC
|
|
IN A,(FDC_MSR) ; READ MSR AGAIN
|
|
;CALL PC_SPACE ; *DEBUG*
|
|
;CALL PRTHEXBYTE ; *DEBUG*
|
|
CP $80
|
|
RET ; $80 OK, ELSE NOT PRESENT
|
|
;
|
|
; 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 CURRENTLY $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
|
|
|
|
; RETURN APPROPRIATE HBIOS ERROR
|
|
LD A,(FST_RC)
|
|
CP FRC_NOTWRIT
|
|
LD A,ERR_READONLY ; ASSUME WRITE PROTECTED ERROR
|
|
JR Z,FD_RETRY1
|
|
LD A,ERR_IO ; OTHERWISE I/O ERROR
|
|
FD_RETRY1:
|
|
OR A ; SET FLAGS
|
|
RET ; AND GIVE UP
|
|
;
|
|
;
|
|
;
|
|
FD_START:
|
|
;
|
|
#IF (DSKYENABLE)
|
|
LD A,4
|
|
CALL LDHLIYA
|
|
CALL HB_DSKACTCHS ; SHOW ACTIVITY
|
|
#ENDIF
|
|
;
|
|
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
|
|
SYSCHKERR(ERR_NOFUNC)
|
|
RET
|
|
|
|
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) | (FDMODE == FDMODE_DYNO) | (FDMODE == FDMODE_EPFDC) | (FDMODE == FDMODE_MBC))
|
|
;
|
|
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) | (FDMODE == FDMODE_DYNO) | (FDMODE == FDMODE_EPFDC) | (FDMODE == FDMODE_MBC))
|
|
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) | (FDMODE == FDMODE_DYNO) | (FDMODE == FDMODE_EPFDC) | (FDMODE == FDMODE_MBC))
|
|
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,50H
|
|
; LD (FCD_IDLECNT),BC
|
|
|
|
LD A,(CB_CPUMHZ)
|
|
RLCA
|
|
LD (FCD_IDLECNT),A
|
|
|
|
#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) | (FDMODE == FDMODE_DYNO) | (FDMODE == FDMODE_EPFDC) | (FDMODE == FDMODE_MBC))
|
|
; 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
|