;======================================================== ;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' 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 зачем? LD C,0 ; признак 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 зачем? LD C,1 ; признак 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. если 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 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 зачем? LD C,0 ; признак 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 зачем? LD C,1 ; признак 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 ;███████████████████████████████████████████████████████████████████████████████████████████████████████; ; !TODO поддержка 8-bit data transfer mode для древних винтов ; 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 ; признак short/long в C LD C,IDE.Device.HDD CALL SELECT_DRIVE POP BC ; признак short/long в 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 ; признак short/long в C PUSH DE ; Address CALL PRESET ; IY из SELECT_DRIVE больше не нужен ; POP HL ; Address POP IY ; признак short/long в 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 ; счётчик для READ_ZEROS, данные для .WrZeros EX AF,AF' LD BC,IDE.Read.Data JR C,.WrZeros ; READ > /dev/null EX AF,AF' .RdLoop: IN F,(C) ; читаем по 1 разу с чётного адреса, читается 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 доделать эту же хурму для других устройств ;███████████████████████████████████████████████████████████████████████████████████████████████████████; /* 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 зачем? 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 ; выход: 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 ;бит 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 ;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 ; !!! некоторые функции надеются, что на выходе всегда 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 ; задержка ;!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]