Sprinter-BIOS/bios/exp/EXTENDED/IDE/ATA_DRV.ASM
2026-05-19 19:48:28 +10:00

735 lines
15 KiB
NASM
Raw Permalink Blame History

;========================================================
;R03 !25.07.2001! BUG FIX WITH RETURN ERROR CODE
;R02 !24.07.2001! ADD SECONDARY CHANEL
;R01 !16.08.2000! REMOVED "DI"
/*
;Write
IDE.Write.Command EQU #4153 ; #1F7 Command
IDE.Write.DeviceHead EQU #4152 ; #1F6 Drive Control
HDW_CLH EQU #0155 ; #1F5 Cylinder High
HDW_CLL EQU #0154 ; #1F4 Cylinder Low
HDW_SEC EQU #0153 ; #1F3 Sector
HDW_CNT EQU #0152 ; #1F2 Counter
HDW_ERR EQU #0151 ; #1F1 Error
HDW_DAT EQU #0150 ; #1F0 Data
;Read
IDE.Read.Status EQU #4053 ; #1F7 Status (Control)
HDR_DRV EQU #4052 ; #1F6 Drive Control
HDR_CLH EQU #0055 ; #1F5 Cylinder High
HDR_CLL EQU #0054 ; #1F4 Cylinder Low
HDR_SEC EQU #0053 ; #1F3 Sector
HDR_CNT EQU #0052 ; #1F2 Counter
HDR_ERR EQU #0051 ; #1F1 Error
HDR_DAT EQU #0050 ; #1F0 Data
;Bits for IDE.Read.Status
;---[]
BSY EQU 7
RDY EQU 6
DRQ EQU 3
ERR EQU 0
;---[]
HDD EQU 1
CDROM EQU 2
;EQU FOR IY+
IDE.HDD_INIT_TABLE.DRV_Flags EQU 0
IDE.HDD_INIT_TABLE.SectorsPerTrack EQU 1
IDE.HDD_INIT_TABLE.HeadsNumber EQU 2
IDE.HDD_INIT_TABLE.CylinderNumberLow EQU 3
IDE.HDD_INIT_TABLE.CylinderNumberHigh EQU 4
IDE.HDD_INIT_TABLE.SectorsPerCylinderLow EQU 5
IDE.HDD_INIT_TABLE.SectorsPerCylinderHigh EQU 6
DTYPE_H EQU 7
IDE0 EQU #C1C0
IDE1 EQU #C1C8
IDE2 EQU #C1D0
IDE3 EQU #C1D8
*/
;IDE0 DB #FF ;DRIVE/HEAD REGISTER ;00
; DB #FF ;SECTORS PER TRACK ;01
; DB #FF ;HEADS ;02
; DB #FF ;CYLINDERS LOW ;03
; DB #FF ;CYLINDERS HIGH ;04
; DB #FF ;SECTOR PER CYLINDER LOW ;05
; DB #FF ;SECTOR PER CYLINDER HIGH ;06
; DB #FF ;RESERVED ;07
;IDE1 DB #FF ;DRIVE/HEAD REGISTER ;00
; DB #FF ;SECTORS PER TRACK ;01
; DB #FF ;HEADS ;02
; DB #FF ;CYLINDERS LOW ;03
; DB #FF ;CYLINDERS HIGH ;04
; DB #FF ;SECTOR PER CYLINDER LOW ;05
; DB #FF ;SECTOR PER CYLINDER HIGH ;06
; DB #FF ;RESERVED ;07
WRITE_OUTI_DUPs EQU 32 ; bytes
;[]================================================================[#51]
;Function: Reset drive
ATA_5x_RESET: ; !FIXIT <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
;For non-ATAPI drives, the only method a driver has of resetting a drive
; after a major error is to do a "software reset" on the bus.
; Set bit 2 (SRST, value = 4) in the proper Control Register for the
; bus. This will reset both ATA devices on the bus. Then, you have to
; clear that bit again, yourself. The master drive on the bus is
; automatically selected.
XOR A
RET
;[]================================================================[#51]
;[]================================================================[#58]
;Function: Get Current Media Parameters
; A - Disk
;Return:
; H - Heads
; L - Sectors per cylinder
; DE - Cylinders
; IX - Capacity sector in bytes
; B - Flags: MASTER/SLAVE, LBA/CHS
ATA_5x_GET_PAR:
LD C,IDE.Device.HDD
CALL SELECT_DRIVE
RET C
IN A,(SLOT3)
EX AF,AF'
LD A,SYS_PAGE
OUT (SLOT3),A
LD A,(IY+IDE.HDD_INIT_TABLE.MediaParameters)
LD L,(IY+IDE.HDD_INIT_TABLE.SectorsPerTrack)
LD H,(IY+IDE.HDD_INIT_TABLE.HeadsNumber)
LD E,(IY+IDE.HDD_INIT_TABLE.CylinderNumberLow)
LD D,(IY+IDE.HDD_INIT_TABLE.CylinderNumberHigh)
LD B,(IY+IDE.HDD_INIT_TABLE.DRV_Flags)
LD IX,512 ;!HARDCODE ; [ ] sector size
EX AF,AF'
OUT (SLOT3),A
EX AF,AF'
AND A
RET
;[]================================================================[#58]
;[]================================================================[#59]
;Function: Set Current Media Parameters
; A - Disk
; H - Heads
; L - Sectors
; DE - Cylinders
; IX - Capacity sector in bytes
; B - Flags
;Return: None
ATA_5x_SET_PAR:
LD C,IDE.Device.HDD
CALL SELECT_DRIVE
RET C
IN A,(SLOT3)
EX AF,AF'
LD A,SYS_PAGE
OUT (SLOT3),A
LD (IY+IDE.HDD_INIT_TABLE.SectorsPerTrack),L
LD (IY+IDE.HDD_INIT_TABLE.HeadsNumber),H
LD (IY+IDE.HDD_INIT_TABLE.CylinderNumberLow),E
LD (IY+IDE.HDD_INIT_TABLE.CylinderNumberHigh),D
LD (IY+IDE.HDD_INIT_TABLE.DRV_Flags),B
;!TODO ; [ ] sector size
;!TODO ; [ ] UnitAttention
EX AF,AF'
OUT (SLOT3),A
;EX AF,AF'
;AND A
RET
;[]================================================================[#59]
;[]================================================================[#55]
;Function: Read Sectors
; A - Disk
; HL:IX - Sector
; DE - Address
; B - Sector counter
;Return:
; HL:IX - Sector + Sector counter
; DE - Address + (Sector counter * Size sector)
;READ SECTOR(S)
ATA_5x_READ: ;PUSH IY ; !FIXIT <20><>祬?
LD C,0 ; <20><EFBFBD><E0A8A7><EFBFBD> short
EX AF,AF'
IN A,(SLOT3)
EX AF,AF'
JP ATA_5x_LONG_READ.main
;[]================================================================[#52]
;Function: Long Read Sectors
; A - Disk
; HL:IX - Sector
; DE - Address
; B - Sector counter, 0 = 256
; A'- Memory Page Number
;Return:
; HL:IX - Sector + Sector counter
; DE - Address + (Sector counter * Size sector)
; A' - Last mem page in RAM Block used for readed data
;LONG READ SECTOR(S)
ATA_5x_LONG_READ:
;PUSH IY ; !FIXIT <20><>祬?
LD C,1 ; <20><EFBFBD><E0A8A7><EFBFBD> long
.main: SAFE_PORTY_2
PUSH BC
PUSH IX
PUSH HL
;
EX AF,AF'
AND A ;read
EX AF,AF'
CALL RW_ATA_SECTORs
;
.shared: EX DE,HL
JR C,.error
LD A,XH ; current page in mem block for SLOT3
EX AF,AF'
;
POP HL
POP IX
POP BC
; HL:IX + B. <20>᫨ B=0, <20><> B=256
XOR A
CP B
LD C,B
CCF
RLA
LD B,A
ADD IX,BC
JR NC,.exit
INC HL
CCF
;
.exit: RESTORE_PORTY
;POP IY
RET
;
.error: LD B,A ; A - <20><><EFBFBD><EFBFBD><EFBFBD> <20><EFBFBD><E8A8A1>
LD C,XL
LD A,XH ; current page in mem block for SLOT3
EX AF,AF'
POP HL
POP IX
PUSH BC
LD B,0
ADD IX,BC
;
;LD C,B
;ADC HL,BC
JR NC,.no_inc_hl
INC HL
.no_inc_hl: ;
POP BC
POP AF
SUB C
LD C,A
LD A,B
LD B,C
SCF ;R03
JR .exit
;[]===========================================================[#52, #55]
;[]================================================================[#56]
;Function: Write Sectors
; A - Disk
; HL:IX - Sector
; DE - Address
; B - Sector counter
;Return:
; HL:IX - Sector + Sector counter
; DE - Address + (Sector counter * Size sector)
;WRITE SECTOR(S)
ATA_5x_WRITE: ;PUSH IY ; !FIXIT <20><>祬?
LD C,0 ; <20><EFBFBD><E0A8A7><EFBFBD> short
EX AF,AF'
IN A,(SLOT3)
EX AF,AF'
JP ATA_5x_LONG_WRITE.main
;[]================================================================[#53]
;Function: Long Write Sectors
; A - Disk
; HL:IX - Sector
; DE - Address
; B - Sector counter
; A'- Memory Page Number
;Return:
; HL:IX - Sector + Sector counter
; DE - Address + (Sector counter * Size sector)
;WRITE SECTOR(S)
ATA_5x_LONG_WRITE:
;PUSH IY ; !FIXIT <20><>祬?
LD C,1 ; <20><EFBFBD><E0A8A7><EFBFBD> long
.main: SAFE_PORTY_2
PUSH BC
PUSH IX
PUSH HL
;
EX AF,AF'
SCF ;write
EX AF,AF'
CALL RW_ATA_SECTORs
;
JP ATA_5x_LONG_READ.shared
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;
; !TODO <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 8-bit data transfer mode <20><><EFBFBD> <20><EFBFBD><E0A5A2><EFBFBD> <20><><EFBFBD>
; A - Disk
; HL:IX - Sector
; DE - Address
; B - Sector counter
; C - short/long
; A'- Memory Page Number
; CF'=1 - write, CF'=0 - read
RW_ATA_SECTORs: PUSH BC ; <20><EFBFBD><E0A8A7><EFBFBD> short/long <20> C
LD C,IDE.Device.HDD
CALL SELECT_DRIVE
POP BC ; <20><EFBFBD><E0A8A7><EFBFBD> short/long <20> C
RET C
;
EXX
LD DE,256*(IDE.CtrlByte.Busy+IDE.CtrlByte.Ready) + IDE.CtrlByte.Ready
CALL WAITPRT.custom
EXX
RET C
;
EX AF,AF'
PUSH AF ; memory page number
PUSH BC ; <20><EFBFBD><E0A8A7><EFBFBD> short/long <20> C
PUSH DE ; Address
CALL PRESET
; IY <20><> SELECT_DRIVE <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><EFBFBD>
;
POP HL ; Address
POP IY ; <20><EFBFBD><E0A8A7><EFBFBD> short/long <20> YL
POP AF ; memory page number
LD XL,0
LD XH,A ; memory page number
LD BC,IDE.Write.Command
LD A,IDE.CMD.ATA.WriteSectorsWithRetry
JR C,.set_command ; CF = r/w
;
LD A,IDE.CMD.ATA.ReadSectorsWithRetry
.set_command: OUT (C),A
EX AF,AF'
EXX
LD DE,256*(IDE.CtrlByte.Busy+IDE.CtrlByte.DataRequest+IDE.CtrlByte.Error)+IDE.CtrlByte.DataRequest
CALL WAITPRT.custom
EXX
RET C
;DI ;R01 REMOVED "DI"
.big_loop: IN A,(SLOT3)
EX AF,AF' ;>-----------> \
LD A,XH
OUT (SLOT3),A
LD BC,IDE.Read.Data
JR C,.write_sector
;
; READ SECTOR 512 bytes ;!HARDCODE sector size
.loop_256_1: DUP 16
INI
EDUP
JP NZ,.loop_256_1
.loop_256_2: DUP 16
INI
EDUP
JP NZ,.loop_256_2
AND A
;EX AF,AF'
; ; ; ; ;
; CF=0
.return_rw: EX AF,AF' ;<-----------< /
INC XL ;INC LOADED SECTORS
OUT (SLOT3),A
;
LD A,H
OR L
JR NZ,.end_pass
; short/long
; A = 0
SUB YL
JR NC,.END_BUFFER
; next page in mem block
CALL CHANGE_MEM_BLK
; LD HL,#C000
; IN A,(SLOT3)
; EX AF,AF' ;>-----------> \
; LD A,SYS_PAGE
; OUT (SLOT3),A
; LD D,high SYS_PAGE.RAM_TABLE
; LD E,XH
; LD A,(DE)
; LD XH,A
; EX AF,AF' ;<-----------< /
; OUT (SLOT3),A
;
.end_pass: ;INC XL ;INC LOADED SECTORS
EXX
CALL WAITPRT
EXX
RET C
;
;INC XL ;INC LOADED SECTORS
LD BC,IDE.Read.Status
IN A,(C)
BIT IDE.CtrlBit.DataRequest,A
RET Z
;
JP .big_loop
;
.write_sector: ; WRITE SECTOR 512 bytes ;!HARDCODE sector size
INC B ; LD BC,IDE.Write.Data
LD D,512/WRITE_OUTI_DUPs ;!HARDCODE sector size
.loop: DUP WRITE_OUTI_DUPs
OUTI
EDUP
DEC D
JR NZ,.loop
SCF
JP .return_rw
; ;
.END_BUFFER: CALL ATA_IdlePasses.CHECK_DRV
JR NZ,ATA_IdlePasses.Enter
RET
;;;;;;;;;;;;;;;;;
ATA_IdlePasses: CALL .CHECK_DRV
JR NZ,.Enter
;
RET C
LD A,BIOS.Error.Failure
SCF
RET
;
.Enter: XOR A ; <20><><EFBFBD><EFBFBD><20><><EFBFBD> READ_ZEROS, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> .WrZeros
EX AF,AF'
LD BC,IDE.Read.Data
JR C,.WrZeros
; READ > /dev/null
EX AF,AF'
.RdLoop: IN F,(C) ; <20><><EFBFBD> <20><> 1 ࠧ<> <20> <20><><EFBFBD><E2ADAE> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><E2A0A5><EFBFBD> WORD
DEC A
JR NZ,.RdLoop
JR ATA_IdlePasses
; WRITE ZEROS
.WrZeros: EX AF,AF'
;
.WrLoop: OUT (C),A
DJNZ .WrLoop
;
.WrLoop2: OUT (C),A
DJNZ .WrLoop2
JR ATA_IdlePasses
;
.CHECK_DRV: EXX
CALL WAITPRT
EXX
RET C
;
LD BC,IDE.Read.Status
IN A,(C)
BIT IDE.CtrlBit.DataRequest,A
RET
;!TODO <09><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><E0AEA9><EFBFBD>
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;
/*
IFN OPTIMIZE_RW_PROCEDURE
WRITE_ATA_SECTORs:
LD C,IDE.Device.HDD
CALL SELECT_DRIVE
RET C
EXX
;LD DE,#C140 ;WAIT BUSY=0 & READY=1 & ERR=0
CALL WAITPRT
EXX
RET C
EX AF,AF'
PUSH AF
PUSH DE
CALL PRESET
POP HL
POP AF
LD XL,0
LD XH,A
LD BC,IDE.Write.Command
LD A,IDE.CMD.ATA.WriteSectorsWithRetry
OUT (C),A
; SAVE HL?!
EXX
LD DE,#8908 ;WAIT BUSY=0 & DRQ=1 & ERR=0
CALL WAITPRT.custom
EXX
RET C
;
.big_loop: IN A,(SLOT3)
EX AF,AF'
LD A,XH
OUT (SLOT3),A
; WRITE SECTOR 512 bytes ;!HARDCODE sector size
LD BC,IDE.Write.Data
LD D,512/WRITE_OUTI_DUPs ;!HARDCODE sector size
.loop: DUP WRITE_OUTI_DUPs
OUTI
EDUP
DEC D
JR NZ,.loop
; ; ; ; ;
EX AF,AF'
OUT (SLOT3),A
;EI
;
LD A,H
OR L
JR NZ,.W33
; next page in mem block
LD HL,#C000
IN A,(SLOT3)
EX AF,AF'
LD A,SYS_PAGE
OUT (SLOT3),A
LD D,high SYS_PAGE.RAM_TABLE
LD E,XH
LD A,(DE)
LD XH,A
EX AF,AF'
OUT (SLOT3),A
;
.W33: INC XL ;INC SAVED SECTORS
EXX
;LD DE,#C140 ;WAIT BUSY=0 & ERR=0 & READY=1
CALL WAITPRT
EXX
RET C
LD BC,IDE.Read.Status
IN A,(C)
BIT IDE.CtrlBit.DataRequest,A
;
RET Z
JP .big_loop
;JP NZ,.big_loop
;XOR A
;RET
;
ENDIF
*/
;[]===========================================================[#53, #56]
;[]================================================================[#54]
;Function: Verify Sectors
; A - Disk
; HL:IX - Sector
; B - Sector counter
;Return: CF - error
;VERIFY SECTOR(S)
ATA_5x_VERIFY: ;PUSH IY ; !FIXIT <20><>祬?
SAFE_PORTY_2
PUSH IX
PUSH HL
CALL .VERIFY
POP HL
POP IX
RESTORE_PORTY
;POP IY
RET
;VERIFY SECTOR(S)
.VERIFY: LD C,IDE.Device.HDD
CALL SELECT_DRIVE
RET C
EXX
LD DE,256*(IDE.CtrlByte.Busy+IDE.CtrlByte.Ready) + IDE.CtrlByte.Ready
CALL WAITPRT.custom
EXX
RET C
;PUSH DE
; IN A,(SLOT3)
; PUSH AF
CALL PRESET
; POP AF
; OUT (SLOT3),A
;POP HL
LD BC,IDE.Write.Command
LD A,IDE.CMD.ATA.ReadVerifySectorsWithRetry
OUT (C),A
LD BC,IDE.Read.Status
IN A,(C)
RRA ;BIT IDE.CtrlBit.Error,A : SCF : RET NZ
RET C
;
JP WAITPRT
;RET C
;XOR A
;RET
;[]================================================================[#54]
; HL:IX - LBA SECTOR
; B - SECTOR COUNTER
; <20><>室: SLOT3 = SYS_PAGE
PRESET: LD A,B
LD BC,IDE.Write.Counter
OUT (C),A
;
IN A,(SLOT3)
EX AF,AF'
LD A,SYS_PAGE
OUT (SLOT3),A
LD A,(IY+IDE.HDD_INIT_TABLE.DRV_Flags)
LD BC,IDE.Write.DeviceHead
OUT (C),A
;<3B><><EFBFBD> CHS/LBA ;!FIXIT ᤥ<><E1A4A5><EFBFBD><EFBFBD> <20><><EFBFBD><E2AAA0> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>
AND %0100'0000
LD E,XL
LD D,XH
CALL Z,LBA_CHS
LD BC,IDE.Write.Sector
OUT (C),E ;LBA 0..7
;
INC C ; LD BC,IDE.Write.CylinderLow
OUT (C),D ;LBA 8..15
INC C ; LD BC,IDE.Write.CylinderHigh
OUT (C),L ;LBA 16..23
LD BC,IDE.Read.Control
IN A,(C)
AND #F0 ;!HARDCODE DRIVE/HEAD REGISTER PHISICAL DISK bitmask
OR H ;LBA 24..27
INC B ; LD BC,IDE.Write.DeviceHead
;
OUT (C),A
EX AF,AF'
OUT (SLOT3),A
;AND A
RET
;PRESET ;
; HL:DE - SECTOR OFFSET
LBA_CHS: LD C,(IY+IDE.HDD_INIT_TABLE.SectorsPerCylinderLow)
LD B,(IY+IDE.HDD_INIT_TABLE.SectorsPerCylinderHigh)
;
DIV32X: ;HL:DE / BC => DE:IX HL-OSTATOK
LD XH,D
LD XL,E
EX DE,HL
LD HL,0
LD A,#20
;
.loop: ADD IX,IX
EX DE,HL
ADC HL,HL
EX DE,HL
ADC HL,HL
SBC HL,BC
JR NC,.DIV012
;
ADD HL,BC
DEC A
JR NZ,.loop
;
JR .DIV014
;
.DIV012: INC IX
DEC A
JR NZ,.loop
;
.DIV014: LD E,(IY+IDE.HDD_INIT_TABLE.SectorsPerTrack)
LD D,0
XOR A
;
.loop2: INC A
SBC HL,DE
JR NC,.loop2
;
ADD HL,DE
DEC A
LD H,A
LD E,L
INC E
LD D,XL
LD A,XH
LD L,A
RET
;----------------------------------------------------------------------;
; D - MASK
; E - PATTERN
; !!! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>㭪樨 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD> <20><> <20><><EFBFBD> <20><EFBFBD><E1A5A3> ZF
WAITPRT: LD DE,256*(IDE.CtrlByte.Busy+IDE.CtrlByte.Ready+IDE.CtrlByte.Error) + IDE.CtrlByte.Ready
.custom: LD BC,IDE.Read.Status
LD HL,#0000 ; <20><><EFBFBD><EFBFBD><EFBFBD> ;!HARDCODE
;
.loop: PUSH HL
;
.loop2: IN A,(C)
AND D
CP E
JR Z,.ok
DEC HL
LD A,L
OR H
JP NZ,.loop2
;
POP HL
DEC L
JR NZ,.loop
;
.error: LD A,BIOS.Error.NotReady
SCF
RET
;
.ok: POP HL
RET
;----------------------------------------------------------------------;
;[]================================================================[#57]
;[x] 18/12/2023. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> API CD-ROM (ATAPI)
; [ ] media change
;Function: Detect Disk
; A - Disk
;Return: CF=0 - A=Drive type
; CF=1 - error
ATA_5x_DETECT: LD C,IDE.Device.HDD
.shared: CALL SELECT_DRIVE
RET C
;
LD B,A
AND %0000'0011 ;[ ] media change <20><><EFBFBD><E0A5A4><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20> <20> <20><><EFBFBD>? ; !FIXIT
JR NZ,.notZero
LD A,C
RET
;
.notZero: AND %0000'0010
JR NZ,.UnitAttention
; C = DriveType
LD A,C
CP IDE.Device.ATAPI
JR Z,.AtapiCheckMedia
;!FIXIT AtaCheckMedia - <20><><><E1A4A5><EFBFBD><EFBFBD> ; [ ] media change
AND A
RET
;
.AtapiCheckMedia:
PUSH BC ; B - MediaParameters, C - DriveType
CALL ATAPI_CHECK_MEDIA_CHANGED
POP BC ; B - MediaParameters, C - DriveType
RET C
LD A,C
RET
;
.UnitAttention: LD A,BIOS.Error.ATAPI.UnitAttention
SCF
RET
;[]================================================================[#57]