
;========================================================
;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 ­Ѕ рЅсЅтЈтся?
;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'
	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:
	EX	AF,AF'
	 IN	A,(SLOT3)
	EX	AF,AF'
;[]================================================================[#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
		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. ЅсЋЈ B=0, тЎ 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 - ­ЎЌЅр ЎшЈЁЊЈ
		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
		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:
	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)
ATA_5x_LONG_WRITE:
		PUSH	IY
		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
/*
		EX	DE,HL
		JP	C,.error
		LD	A,XH
		EX	AF,AF'
		;
		POP	HL
		POP	IX
		POP	BC
		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
	JR	RST8WRR

.error:	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 
*/


;ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл;
;	A - Disk
;   HL:IX - Sector
;      DE - Address
;	B - Sector counter
;	A'- Memory Page Number
;	CF'=1 - write, CF'=0 - read
RW_ATA_SECTORs:	LD	C,IDE.Device.HDD
		CALL	SELECT_DRIVE
		RET	C
		;
		EXX 
		 CALL	WAITPRT
		EXX 
		RET	C
		;
		EX	AF,AF'
		PUSH	AF		; memory page number
		PUSH	DE		; Address
		CALL	PRESET
		POP	HL		; Address
		POP	AF		; memory page number
		LD	XL,0
		LD	XH,A
		LD	BC,IDE.Write.Command
		LD	A,IDE.ATA.WriteSectorsWithRetry
		JR	C,.set_command			; CF = r/w
		;
		LD	A,IDE.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'		;<-----------< /
		OUT	(SLOT3),A
		;
		LD	A,H
		OR	L
		JR	NZ,.W44
		; next page in mem block
		; сЄЅЋ ть ЅсЋЈ ­Ѕ RW_LONG, тЎ хЎЋЎстыЅ чтЅ­ЈЅ/Ї ЏЈсь Ј ЂыхЎЄ с ЎшЈЁЊЎЉ
		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
		;
.W44:		INC	XL		;INC LOADED SECTORS
		EXX 
		 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 
		;
	;
.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
	; ; ; ; ;

	;ENDIF
;ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл;
/*
	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.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: None
;VERIFY	SECTOR(S)
ATA_5x_VERIFY:	PUSH	IY
		 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 
		 CALL	WAITPRT
		EXX 
		RET	C
		PUSH	DE
		CALL	PRESET
		POP	HL
		LD	BC,IDE.Write.Command
		LD	A,IDE.ATA.ReadVerifySectorsWithRetry
		OUT	(C),A
		LD	BC,IDE.Read.Status
		IN	A,(C)
		;BIT	IDE.CtrlBit.Error,A
		RRA				;BIT IDE.CtrlBit.Error,A : SCF : RET NZ
		RET	C
		;
		CALL	WAITPRT
		RET	C
		XOR	A
		RET
;[]================================================================[#54]


; 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
	 ;
	 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 

; 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	DE,256*(IDE.CtrlByte.Busy+IDE.CtrlByte.Ready+IDE.CtrlByte.Error)+IDE.CtrlByte.Ready
.custom:	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)
; [ ] 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 ЏЅрЅЄЅЋ ть ЋЎЃЈЊу тут Ј Ђ ? ; !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 - ­Ѕ сЄЅЋ ­Ў ; [ ] 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]