;;.PRINTX "HDD utility" DEFINE HDD_TYPE 1 MACRO WAIT_HDD .LL1: LD BC,IDE.Read.Status IN A,(C) BIT 7,A JR NZ,.LL1 ENDM ;************************************** HD_EXP_EXE: POP AF CALL HD_CMD_X JP HD_EXP_RET HD_CMD: POP AF CALL HD_CMD_X JP HD_DOS_RET HD_CMD_X: ; C - COMAND ( 5 - RD, 6 - WR ) PUSH AF LD A,C AND A JP Z,HD_CMD_0 ; 0 - инициализация DEC A JP Z,HD_CMD_1 ; 1 - DIAG DEC A JP Z,HD_CMD_2 ; 2 - тест DEC A JP Z,HD_CMD_3 ; 3 - preread DEC A JP Z,HD_CMD_4 ; 4 - read bpb DEC A JP Z,HD_CMD_5 ; 5 - read DEC A JP Z,HD_CMD_6 ; 6 - write DEC A JP Z,FN_HDD_PART POP AF SCF RET HD_BPB_PREP: LD D,A IN A,(SLOT3) EX AF,AF' LD A,SYS_PAGE OUT (SLOT3),A LD A,(SYS_PAGE.HD_IDF_ADR.sectors) LD E,A EX AF,AF' OUT (SLOT3),A LD A,D LD D,0 LD IX,0 LD B,1 HD_PREPARE: PUSH AF PUSH HL CALL HD_CALC_SECS JR NC,HD_PREP_L1 POP HL POP AF SCF RET HD_PREP_L1: LD A,B LD BC,IDE.Write.Counter ; Установить число секторов для чтения OUT (C),A LD BC,IDE.Write.Sector OUT (C),L ; СЕКТОР LD BC,IDE.Write.CylinderLow OUT (C),E ; дорожка low LD BC,IDE.Write.CylinderHigh OUT (C),D ; дорожка high LD BC,IDE.Write.DeviceHead DEC B IN A,(C) AND 0F0H OR H INC B OUT (C),A POP HL ; BUFER & PAGE POP AF AND A RET HD_CMD_3: ; ПОДГОТОВКА К ВНЕШНИМ ОПЕРАЦИЯМ R/W POP AF AND A INC B DEC B RET Z CALL HD_WAIT RET C CALL HD_PREPARE RET C EXX LD C,SLOT3 IN B,(C) EXX OUT (SLOT3),A EX AF,AF' LD A,0C0H OUT (RGADR),A LD BC,IDE.Write.Command LD A,#20 ; OUT (C),A AND A RET ; SCF ; RET HD_CMD_4: POP AF CALL HD_WAIT RET C CALL HD_BPB_PREP RET C JR HD_RD_L1 ;******************* HD_CMD_5: POP AF ; HL - BUFER, A - PAGE !!! HD_RD_CMD: AND A INC B DEC B RET Z CALL HD_WAIT RET C CALL HD_PREPARE RET C HD_RD_L1: EXX LD C,SLOT3 IN B,(C) EXX OUT (SLOT3),A EX AF,AF' LD A,0C0H OUT (RGADR),A LD BC,IDE.Write.Command LD A,20H OUT (C),A HD_RD_L2: WAIT_HDD BIT 3,A JR NZ,HD_READ_CONT LD A,0 OUT (RGADR),A HD_RET: EXX OUT (C),B EXX LD BC,IDE.Read.Error IN A,(C) AND A SCF RET NZ EX AF,AF' AND A RET HD_READ_CONT: LD BC,IDE.Read.Data HD_RD_CONT1: DUP 16 INI ; всего 16 раз INI - оптимально. EDUP JP NZ,HD_RD_CONT1 HD_RD_CONT2: DUP 16 INI ; всего 16 раз INI - оптимально. EDUP JP NZ,HD_RD_CONT2 ; INIR ; INIR LD A,H OR L JR NZ,HD_RD_L2 LD A,SYS_PAGE OUT (SLOT3),A EX AF,AF' LD HL,SYS_PAGE.RAMD_FAT LD L,A LD A,(HL) OUT (SLOT3),A EX AF,AF' LD HL,#C000 JR HD_RD_L2 ;*********************************************** HD_CMD_6: POP AF ; HL - BUFER, A - PAGE !!! HD_WR_CMD: AND A INC B DEC B RET Z CALL HD_WAIT RET C CALL HD_PREPARE RET C EXX LD C,SLOT3 IN B,(C) EXX OUT (SLOT3),A EX AF,AF' LD BC,IDE.Write.Command LD A,30H OUT (C),A HD_WR_L2: WAIT_HDD BIT 3,A JP Z,HD_RET ;####################################### IF HDD_TYPE LD BC,IDE.Read.Data+100H LD D,32 HD_WR_CONT1: DUP 16 OUTI ; всего 16 раз OUTI - оптимально. EDUP DEC D JP NZ,HD_WR_CONT1 ;####################################### ELSE LD D,64 LD BC,IDE.Read.Data+100H HD_WR_LOOP: INC HL OUTI DEC HL DEC HL OUTI INC HL INC HL OUTI DEC HL DEC HL OUTI INC HL INC HL OUTI DEC HL DEC HL OUTI INC HL INC HL OUTI DEC HL DEC HL OUTI INC HL DEC D JR NZ,HD_WR_LOOP ENDIF ;####################################### LD A,H OR L JR NZ,HD_WR_L2 LD A,SYS_PAGE OUT (SLOT3),A EX AF,AF' LD HL,SYS_PAGE.RAMD_FAT LD L,A LD A,(HL) OUT (SLOT3),A EX AF,AF' LD HL,#C000 JR HD_WR_L2 ;******************************************************** HD_CMD_1: POP AF HD_CMD1_EX: ld a,0A0h LD BC,IDE.Write.DeviceHead OUT (C),A LD A,90h ; DIAGNOSTICS CALL HD_CMD_EXE AND A BIT 0,A RET Z LD BC,IDE.Read.Error IN A,(C) CP 1 RET Z SCF RET ;********************************************** HD_CMD_2: POP AF LD E,0 LD BC,IDE.Write.DeviceHead LD A,0A0H OUT (C),A CALL TEST_HDD_DRV JR NZ,NO_HDD1 SET 0,E NO_HDD1: LD BC,IDE.Write.DeviceHead LD A,0B0H OUT (C),A CALL TEST_HDD_DRV JR NZ,NO_HDD2 SET 1,E NO_HDD2: LD A,E AND A SCF RET Z ; HDD absent ! AND A RET TEST_HDD_DRV: LD HL,01FEH LD BC,IDE.Write.Counter OUT (C),L LD BC,IDE.Write.Sector OUT (C),H LD BC,IDE.Write.Counter+256 IN A,(C) CP L RET NZ LD BC,IDE.Write.Sector+256 IN A,(C) CP H RET HD_CMD_0: POP AF LD BC,IDE.Write.DeviceHead LD A,0A0H OUT (C),A CALL TEST_HDD_DRV JR NZ,HD_ABSENT HD_C0_L3: WAIT_HDD LD BC,IDE.Write.Command LD A,0ECH OUT (C),A WAIT_HDD ;HD_C0_L1: ; ; LD BC,IDE.Read.Status ; IN A,(C) ; BIT 7,A ; JR NZ,HD_C0_L1 BIT 3,A JR NZ,HD_C0_L2 SCF RET HD_ABSENT: LD BC,IDE.Write.DeviceHead LD A,0B0H OUT (C),A CALL TEST_HDD_DRV JR Z,HD_C0_L3 SCF RET HD_C0_L2: LD BC,IDE.Read.Data LD HL,SYS_PAGE.HD_IDF_ADR IN A,(SLOT3) LD D,A LD A,SYS_PAGE OUT (SLOT3),A INIR INIR ;HD_C0_L4: ; LD BC,IDE.Read.Status ; IN A,(C) ; BIT 7,A ; JR NZ,HD_C0_L4 LD A,(SYS_PAGE.HD_IDF_ADR.sectors) ; число секторов LD C,A LD B,0 LD HL,0 LD A,(SYS_PAGE.HD_IDF_ADR.heads) ; число головок LOOP_XX: ADD HL,BC DEC A JR NZ,LOOP_XX LD (SYS_PAGE.HD_IDF_ADR.sec_cyl),HL WAIT_HDD LD BC,IDE.Write.DeviceHead DEC B IN A,(C) AND 010H LD B,A LD A,(SYS_PAGE.HD_IDF_ADR.heads) ; число головок DEC A AND 0FH OR 0A0H OR B LD H,A LD A,(SYS_PAGE.HD_IDF_ADR+99) ;!HARDCODE BIT 1,A JR Z,HD_C0_NO_LBA SET 6,H HD_C0_NO_LBA: LD BC,IDE.Write.DeviceHead OUT (C),H LD A,(SYS_PAGE.HD_IDF_ADR.sectors) ; число секторов LD BC,IDE.Write.Counter OUT (C),A LD A,D OUT (SLOT3),A LD A,91H ; SET HDD PARAMETERS CALL HD_CMD_EXE RET ; RET C ; LD A,1FH ; RECALIBRATE ; CALL HD_CMD_EXE ; RET HD_CMD_EXE: CALL HD_WAIT RET C LD BC,IDE.Write.Command OUT (C),A HD_WAIT: PUSH DE PUSH BC PUSH AF LD DE,0 HD_WAIT1: LD BC,IDE.Read.Status IN A,(C) BIT 7,A JR Z,HD_W_EXIT DEC DE LD A,D OR E JR NZ,HD_WAIT1 POP AF POP BC POP DE SCF RET HD_W_EXIT: POP AF POP BC POP DE AND A RET ;**************************** HDD_LBA: POP BC LD L,E LD E,D DB 0DDH LD D,L XOR A LD H,A RET HD_CALC_SECS: DB 0DDH LD A,H AND A SCF RET NZ ; ошибка, слишком большой HDD.. PUSH BC LD BC,IDE.Write.DeviceHead DEC B IN A,(C) BIT 6,A JR NZ,HDD_LBA ;******************************* ; IX,DE - абсолютный номер сектора PUSH IX POP HL IN A,(SLOT3) LD C,A LD A,SYS_PAGE OUT (SLOT3),A LD A,C LD (SYS_PAGE.COPY_SLOT3),A LD BC,(SYS_PAGE.HD_IDF_ADR.sec_cyl) ; число секторов на цилиндре ; HL,DE - номер сектора ; BC - число секторов на цилиндре ; HL,DE разделить на BC LD A,16 SCF DIV_LOOP: EX DE,HL ADD HL,HL EX DE,HL ADC HL,HL SBC HL,BC ; сравнить HL и BC JR NC,NO_ADD ; переноса не было - +1! ADD HL,BC DEC A JR NZ,DIV_LOOP JR DIV_END NO_ADD: INC DE DEC A JR NZ,DIV_LOOP DIV_END: ; DE - результат, HL - остаток ; DE - цилиндр LD A,(SYS_PAGE.HD_IDF_ADR.sectors) ; A - число секторов на дорожке ; HL - номер сектора в цилиндре LD B,0 LD C,A ; LD BC,(MS_BPB+S_P_T) ; ЧИСЛО СЕКТОРОВ НА ДОРОЖКЕ XOR A HD_CALC_LOOP2: SBC HL,BC INC A JR NC,HD_CALC_LOOP2 DEC A ; A - головка ADD HL,BC ; L - сектор INC L LD H,A ; HL - HEAD,SEC LD A,(SYS_PAGE.COPY_SLOT3) OUT (SLOT3),A POP BC AND A RET FN_HDD_PART: POP AF BIT 0,A LD A,IDE.Chanel.Primary JR Z,.SET_CH LD A,IDE.Chanel.Secondary .SET_CH: OUT (IDE.Chanel.Set),A RET ; DB 'HDD_DRV_END' ; Вход: ; C - команда ; 0 - INIT - входных пар нет => A - число поддерживаемых дисков. ; 1 - RESET - выбор диска A - номер диска от 0 => ; 2 - (STATUS) ; 3 - MEDIA CHECK - A - номер диска => A = 0 - old. #FF - new (всегда #FF) ; 4 - READ BPB - A - диск HL - адрес в текущей странице. ; 5 - READ - A - диск, IX:DE сектор, HL - адрес, B - число секторов ; 6 - WRITE - '' - ; ; ошибки - CF - A - ошибка ; ; 0 - нет ошибки ; 1 - неверная команда ; 2 - неверный номер диска ; 3 - неверный формат (не MS-DOS) ; 4 - нет готовности ; 5 - ошибка позиционирования ; 6 - сектор не найден ; 7 - ошибка CRC ; 8 - защита записи ; 9 - ошибка чтения ; 10 - ошибка записи ; 11 - ГЛЮК ;