
;========================================================
;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
HDD_5x_RESET:                      ; !FIXIT не ресетится?
;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
HDD_5x_GETMED:
	LD	C,IDE.Device.HDD
	CALL	SELECT_DRIVE
	RET	C
	IN	A,(SLOT3)
	EX	AF,AF'
	LD	A,SYS_PAGE
	OUT	(SLOT3),A
	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
HDD_5x_SETMED:
	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
	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)
HDD_5x_READ:
	EX	AF,AF'
	IN	A,(SLOT3)
	EX	AF,AF'
;[]================================================================[#52]
;Function: Long	Read 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)
;LONG READ SECTOR(S)
HDD_5x_LONG_READ:
	PUSH	IY
	
	SAFE_PORTY_2

	PUSH	BC
	PUSH	IX
	PUSH	HL
	CALL	RDS000
	EX	DE,HL
	JR	C,HERRRD0
	LD	A,XH
	EX	AF,AF'
	POP	HL
	POP	IX
	POP	BC
	XOR	A
	CP	B
	LD	C,B
	LD	B,A
	JR	NZ,RNOT256
	INC	B
	ADD	IX,BC
	LD	B,C
	ADC	HL,BC
	;EX	AF,AF'	;!TEST 21/11/23
	JR	RST8RDR

RNOT256	ADD	IX,BC
	LD	C,B
	ADC	HL,BC
	;EX	AF,AF'	;!TEST 21/11/23
	JR	RST8RDR

HERRRD0	LD	B,A
	LD	C,XL
	LD	A,XH
	EX	AF,AF'
	POP	HL
	POP	IX
	PUSH	BC
	LD	B,0
	ADD	IX,BC
	LD	C,B
	ADC	HL,BC
	POP	BC
	POP	AF
	SUB	C
	LD	C,A
	LD	A,B
	LD	B,C
	;R03
	 SCF
	 ;EX	AF,AF'	;!TEST 21/11/23
	;
RST8RDR: RESTORE_PORTY
	POP	IY
	;EX	AF,AF'	;!TEST 21/11/23
	RET 

	;READ SECTOR(S)
RDS000:	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.ATA.ReadSectorsWithRetry
	OUT	(C),A
;?????
;SAVE HL!
RDS002:	EXX 
	 LD	DE,#8908   ;WAIT BUSY=0 & DRQ=1 & ERR=0
	 CALL	WAITPRT
	EXX 
	RET	C
	;NOP		    ;R01 REMOVED "DI"
	IN	A,(SLOT3)
	EX	AF,AF'
	LD	A,XH
	OUT	(SLOT3),A
	LD	BC,IDE.Read.Data

RDS003:	DUP 16
	 INI 
	EDUP
	JP	NZ,RDS003
RDS004:	DUP 16
	 INI 
	EDUP
	JP	NZ,RDS004

	EX	AF,AF'
	OUT	(SLOT3),A
;
	LD	A,H
	OR	L
	JR	NZ,.W44
	LD	HL,#C000
	IN	A,(SLOT3)
	EX	AF,AF'
	LD	A,SYS_PAGE
	OUT	(SLOT3),A
	LD	D,#C2
	LD	E,XH
	LD	A,(DE)
	LD	XH,A
	EX	AF,AF'
	OUT	(SLOT3),A
	;
.W44:	INC	XL	    ;INC LOADED	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.ControlBit.DataRequest,A
	JP	NZ,RDS002
	XOR	A
	RET 
;[]===========================================================[#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)
HDD_5x_WRITE:
	EX	AF,AF'
	IN	A,(SLOT3)
	EX	AF,AF'
;[]================================================================[#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)
HDD_5x_LONG_WRITE:
	PUSH	IY

	SAFE_PORTY_2

	PUSH	IX
	PUSH	HL
	PUSH	BC
	CALL	WRS000
	EX	DE,HL
	JP	C,HERRWR0
	LD	A,XH
	EX	AF,AF'
	POP	BC
	POP	HL
	POP	IX
	XOR	A
	CP	B
	LD	C,B
	LD	B,A
	JR	NZ,WNOT256
	INC	B
	ADD	IX,BC
	LD	B,C
	ADC	HL,BC
	;EX	AF,AF'
	JR	RST8WRR

WNOT256	ADD	IX,BC
	LD	C,B
	ADC	HL,BC
	;EX	AF,AF'
	JR	RST8WRR

HERRWR0	LD	B,A
	LD	C,XL
	LD	A,XH
	EX	AF,AF'
	POP	HL
	POP	IX
	PUSH	BC
	LD	B,0
	ADD	IX,BC
	LD	C,B
	ADC	HL,BC
	POP	BC
	POP	AF
	SUB	C
	LD	C,A
	LD	A,B
	LD	B,C
	;R03
	 SCF		;R03
	 ;EX	AF,AF'	;R03	;!FIXIT намудрил он чёт в этом R03
	;
RST8WRR: RESTORE_PORTY
	POP	IY
	;EX	AF,AF'
	RET 

;WRITE SECTOR(S)
WRS000:
	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

	;[x] CMOS Write Protect Disabled
        IF	HDDwriteProtect
	 PUSH	BC
	 LD	D,CMOS_CELL.Options
         CALL    CMOS_RD
	 POP	BC
	 AND	1
	 JR	Z,NO_WriteProtect
	 POP	HL
	 POP	AF
	 EX	AF,AF'
	 LD	XL,0
	 LD	A,BIOS.Error.WriteProtect
	 SCF 
	 RET 
        ENDIF
NO_WriteProtect:
	CALL	PRESET
	POP	HL
	POP	AF
	LD	XL,0
	LD	XH,A
	LD	BC,IDE.Write.Command
	LD	A,IDE.ATA.WriteSectorsWithRetry
	OUT	(C),A
;SAVE HL!
WRS002:	EXX 
	 LD	DE,#8908   ;WAIT BUSY=0 & DRQ=1 & ERR=0
	 CALL	WAITPRT
	EXX 
	RET	C

	;DI 
	IN	A,(SLOT3)
	EX	AF,AF'
	LD	A,XH
	OUT	(SLOT3),A
	LD	BC,IDE.Write.Data
	;LD	D,#20
	LD	D,512/WRITE_OUTI_DUPs
WRS003:
 DUP WRITE_OUTI_DUPs
	OUTI 
 EDUP
	DEC	D
	JR	NZ,WRS003

	EX	AF,AF'
	OUT	(SLOT3),A
	//EI 
;
	LD	A,H
	OR	L
	JR	NZ,.W33
	LD	HL,#C000
	IN	A,(SLOT3)
	EX	AF,AF'
	LD	A,SYS_PAGE
	OUT	(SLOT3),A
	LD	D,#C2
	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.ControlBit.DataRequest,A
	JP	NZ,WRS002
	XOR	A
	RET 
;[]===========================================================[#53, #56]


;[]================================================================[#54]
;Function: Verify Sectors
;	A - Disk
;   HL:IX - Sector
;	B - Sector counter
;Return: None
;VERIFY	SECTOR(S)
HDD_5x_VERIFY:
	PUSH	IY
	 SAFE_PORTY_2
	PUSH	IX
	PUSH	HL
	CALL	VRS000
	POP	HL
	POP	IX
	 RESTORE_PORTY
	POP	IY
	RET 
;[]================================================================[#54]
;VERIFY	SECTOR(S)
VRS000:		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
		PUSH	DE
		CALL	PRESET
		POP	HL
		LD	BC,IDE.Write.Command
		LD	A,IDE.ATA.ReadVerifySectorsWithRetry
		OUT	(C),A
VRS002:		LD	BC,IDE.Read.Status
		IN	A,(C)
		BIT	IDE.ControlBit.Error,A
		JR	Z,VRS003
		SCF 
		RET 
VRS003:		LD	DE,#C140   ;WAIT BUSY=0 & ERR=0 & READY=1
		CALL	WAITPRT
		RET	C
		XOR	A
		RET 

; HL:IX	- LBA SECTOR
;     B	- SECTOR COUNTER
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
	;бит CHS/LBA ;!FIXIT сделать метками номера бит
	AND	%0100'0000
	LD	E,XL
	LD	D,XH
	CALL	Z,LBA_CHS
	LD	BC,IDE.Write.Sector
	OUT	(C),E		;LBA 0..7
 IF IDE_Optimization
	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
 ELSE
 	LD	BC,IDE.Write.CylinderLow
	OUT	(C),D		;LBA 8..15
	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
	LD	BC,IDE.Write.DeviceHead
 ENDIF
	OUT	(C),A
	EX	AF,AF'
	OUT	(SLOT3),A
	AND	A
	RET 

; HL:DE	- SECTOR OFFSET
LBA_CHS:
	LD	C,(IY+IDE.HDD_INIT_TABLE.SectorsPerCylinderLow)
	LD	B,(IY+IDE.HDD_INIT_TABLE.SectorsPerCylinderHigh)
;	HL:DE /	BC => DE:IX HL-OSTATOK
DIV32X:	LD	XH,D
	LD	XL,E
	EX	DE,HL
	LD	HL,0
	LD	A,#20
DIV011:	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,DIV011
	JR	DIV014
DIV012:	INC	IX
	DEC	A
	JR	NZ,DIV011
DIV014:	LD	E,(IY+IDE.HDD_INIT_TABLE.SectorsPerTrack)
	LD	D,0
	XOR	A
CHS005:	INC	A
	SBC	HL,DE
	JR	NC,CHS005
	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
WAITPRT:
	LD	BC,IDE.Read.Status
	LD	HL,#0000		; задержка ;!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. добавление/допиливание API CD-ROM (ATAPI)
;Function: Detect Disk
;	   A - Disk
;Return:   CF=0 - A=Drive type 
;	   CF=1 - drive not present, A=#02
HDD_5x_DETECT:
	LD	C,IDE.Device.HDD
	JP	DRV_DETECT
;[]================================================================[#57]