;[]===========================================================[] ; FDD.CHANGE: ; LD A,#01 ; AND A ; RET FDD_COUNTERS: .RW_Retries EQU 5 .INTRQorDRQ EQU 4 ;[]===========================================================[] ;Function: Get Current Media Parameters ; A - Disk ;Return: ; H - Heads ; L - Sectors ; DE - Cylinders ; IX - Capacity sector in bytes ; B - Flags ; D7 - "1": High Density, "0": Double Density ; D1-2 - FDD type %01 - 3.5"; %10 - 5.25"; ; D0 - FDD drv number ; A - D0 - "1" - Removable media ;[]===========================================================[] ;[x] всегда шла работа с данными для диска А ;[x] читать данные с нулевой дорожки? Придумать что делать с геометрией флопарей FDD_5x_GET_PAR: CALL SELECT_FDD RET C ; IN A,(SLOT3) EX AF,AF' LD A,SYS_PAGE OUT (SLOT3),A LD L,(IY + FDD_TABLE_s.SECTORS) LD H,(IY + FDD_TABLE_s.HEADS) LD E,(IY + FDD_TABLE_s.BytesPerSector) LD D,(IY + FDD_TABLE_s.BytesPerSector + 1) PUSH DE POP IX LD E,(IY + FDD_TABLE_s.CYLINDL) LD D,(IY + FDD_TABLE_s.CYLINDH) LD B,(IY + FDD_TABLE_s.DISK) LD A,(IY + FDD_TABLE_s.ID) SLA A OR B LD B,A EX AF,AF' OUT (SLOT3),A XOR A INC A ; removable media. CF=0, LD A,1 RET ;[]===========================================================[] ;Function: Set Current Media Parameters ; A - Disk ; H - Heads ; L - Sectors ; DE - Cylinders ; IX - Capacity sector in bytes ; B - Flags ; D7 - "1" - High Density, "0" - Double Density ;Return: None ;[]===========================================================[] FDD_5x_SET_PAR: CALL SELECT_FDD RET C ; IN A,(SLOT3) EX AF,AF' LD A,SYS_PAGE OUT (SLOT3),A LD (IY + FDD_TABLE_s.SECTORS),L LD (IY + FDD_TABLE_s.HEADS),H LD (IY + FDD_TABLE_s.CYLINDL),E LD (IY + FDD_TABLE_s.CYLINDH),D PUSH IX POP DE LD (IY + FDD_TABLE_s.BytesPerSector),E LD (IY + FDD_TABLE_s.BytesPerSector + 1),D LD A,B AND %1000'0000 RES 7,(IY + FDD_TABLE_s.DISK) OR (IY + FDD_TABLE_s.DISK) LD (IY + FDD_TABLE_s.DISK),A EX AF,AF' OUT (SLOT3),A AND A RET ;[]===========================================================[] ;Function: Detect Disk Density ; A - Disk ;Return: ; A - Flag D7 - "1" - High Density, "0" - Double Density ; B - bit0=1 removable ;[]===========================================================[] FDD_5x_DETECT: CALL SAVE_INTERRUPTS.switch_off CALL SET_DOS_ON CALL SELECT_FDD CALL NC,DISK_ID PUSH AF CALL SET_DOS_OFF POP AF LD B,%0000'0001 ;bit0=1 removable, bit1=1 drive changed, bit7..2 reserved ; [ ] JP SAVE_INTERRUPTS.restore ;RET ;[]===========================================================[] ;Function: Reset Disk ; A - Disk ;Return: None ;[]===========================================================[] FDD_5x_RESET: CALL SAVE_INTERRUPTS.switch_off CALL SET_DOS_ON CALL SELECT_FDD CALL NC,DISK_ID JR C,.int ; [ ] размера сектора IN A,(SLOT3) EX AF,AF' LD A,SYS_PAGE OUT (SLOT3),A XOR A CP B JR NZ,.SetSectorSize ; LD A,#80 .SetSectorSize: LD (IY + FDD_TABLE_s.BytesPerSector),A LD (IY + FDD_TABLE_s.BytesPerSector + 1),B EX AF,AF' OUT (SLOT3),A ; .int: CALL SAVE_INTERRUPTS.restore JR C,.MOTOR_OFF ; CALL RESWG XOR A ;!HARDCODE CMD КР1818ВГ93 OUT (FDC_93.Track),A IN A,(FDC_93.Command) ;LD C,A CALL SET_DOS_OFF ;LD A,C AND A JP SAVE_INTERRUPTS.restore ;RET .MOTOR_OFF: ;PUSH AF LD A,#D0 ;!HARDCODE CMD КР1818ВГ93 OUT (FDC_93.Command),A ;STOP OPERATION LD A,#00 OUT (FDC_93.DrvCTRL),A LD A,#3C OUT (FDC_93.DrvCTRL),A JP SET_DOS_OFF ; CF=1 ;LD A,BIOS.Error.NotReady ;POP AF ;JP SAVE_INTERRUPTS.restore ;RET ;[]===========================================================[] ;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) ;[]===========================================================[] FDD_5x_READ: EX AF,AF' IN A,(SLOT3) EX AF,AF' ;[]===========================================================[] ;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) ;[]===========================================================[] FDD_5x_LONG_READ: EXX LD B,#80 ; COMMAND READ ;!HARDCODE CMD КР1818ВГ93 EXX ; .RW_Shared: CALL SAVE_INTERRUPTS.switch_off CALL .Start JP SAVE_INTERRUPTS.restore ; .Start: ;PUSH IY EX AF,AF' LD C,A ; Memory Page Number EX AF,AF' CALL SET_DOS_ON CALL SELECT_FDD CALL C,SET_DOS_OFF RET C ; PUSH BC PUSH HL PUSH IX CALL SET_SPEED PUSH BC CALL NTRACK POP BC EX DE,HL IN A,(SLOT3) EX AF,AF' LD A,SYS_PAGE OUT (SLOT3),A LD XH,C ; Memory Page Number LD C,(IY + FDD_TABLE_s.SECTORS) EX AF,AF' OUT (SLOT3),A ; .DSK_LP: LD A,D EXX PUSH BC CALL SEEK ;!FIXIT контроль ошибки POP BC EXX PUSH DE PUSH BC PUSH HL CALL FDD_RW_SECTOR JR C,.ERRDOS ; размер сектора IN A,(SLOT3) EX AF,AF' LD A,SYS_PAGE OUT (SLOT3),A LD E,(IY + FDD_TABLE_s.BytesPerSector) LD D,(IY + FDD_TABLE_s.BytesPerSector + 1) EX AF,AF' OUT (SLOT3),A POP HL POP BC ADD HL,DE CALL C,CHANGE_MEM_BLK ;.THISRD POP DE LD A,C INC E CP E JR NZ,.NINC_T ; LD E,0 INC D .NINC_T: DJNZ .DSK_LP ; ;.RETDOS: CALL SET_DOS_OFF LD A,XH ; Memory Page Number EX AF,AF' EX DE,HL POP IX POP HL POP BC ;POP IY LD A,B LD C,B INC B DEC B LD B,0 JR NZ,.ADD8BIT ; INC B .ADD8BIT: ADD IX,BC ;!TEST ;LD BC,0 ;ADC HL,BC ;LD B,A ;XOR A ;RET ; LD B,A RET NC INC HL XOR A RET ; .ERRDOS: POP HL POP BC POP DE CALL SET_DOS_OFF EX DE,HL EX AF,AF' EXX LD C,XH ; Memory Page Number EXX LD A,B POP IX POP HL POP BC ;POP IY PUSH AF LD C,A LD A,B SUB C LD C,A LD B,0 ADD IX,BC LD C,B ADC HL,BC POP BC EXX LD A,C EXX EX AF,AF' SCF RET ;[]===========================================================[] ;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) ;[]===========================================================[] FDD_5x_WRITE: EX AF,AF' IN A,(SLOT3) EX AF,AF' ;[]===========================================================[] ;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) ;?? B - Sector counter ;[]===========================================================[] FDD_5x_LONG_WRITE: EXX LD B,#A0 ;COMMAND WRITE ;!HARDCODE CMD КР1818ВГ93 EXX JP FDD_5x_LONG_READ.RW_Shared ; ;------------------------------- ;WRITE SECTOR ;------------------------------- FDD_RW_SECTOR: LD D,FDD_COUNTERS.RW_Retries .RETRY: PUSH HL PUSH DE IN A,(SLOT3) PUSH AF ; сохраняем текущую страницу LD A,E INC A OUT (FDC_93.Sector),A LD A,SYS_PAGE OUT (SLOT3),A EXX ; [ ] 15/04/25 размер сектора больше, чем установлено в SYS_PAGE.FDD_TABLE.BytesPerSector вызовет ошибку LD E,(IY + FDD_TABLE_s.BytesPerSector) LD D,(IY + FDD_TABLE_s.BytesPerSector + 1) INC DE ; BIT 5,B ; Set Z flag for read or NZ for write EX AF,AF LD A,B ; COMMAND read or write EXX LD C,A LD A,XH OUT (SLOT3),A LD A,C ; COMMAND read or write ;██████████ КРИТИЧНЫЙ К СКОРОСТИ КУСОК ПОСЛЕ УСТАНОВКИ КОМАНДЫ ДО СНЯТИЯ РЕЗУЛЬТАТА ██████████ OUT (FDC_93.Command),A LD BC,FDD_COUNTERS.INTRQorDRQ*256 + FDC_93.Data ; именно тут для задержки между предыдущей и следующей команды .wait_loop: IN A,(FDC_93.DrvCTRL) ; 11 ; 11 ;WAIT INTRQ or DRQ AND %0100'0000 ; 7 ; 7 ;b7: INTRQ (выполняется команда = 0), b6: DRQ (запрос данных = 1). JR Z,.wait_loop_next ; 7 ; 12 + 34 (.wait_loop_next) ; тут максимум 64 такта EX AF,AF' JR NZ,.write_loop ; 11 ; результат BIT 5,B' ; ;EX AF,AF' ;READ BYTE. между .wait_loop и .read_loop (INI) 64+11=75 тактов .read_loop: EXX DEC DE LD A,D OR E EXX JR Z,.SectorSizeError ; от .wait_loop досюда минимум 26+11+7+7+11+29=91, было 75+29=104 тактов ; примерно 9,1 мкс при условных средних 10 Мгц ; примерно 26 мкс при 3,5 Мгц ; Должно быть не больше 16 мкс для 1.44 или 32 мкс для 720 INI ;█████████████████████████████████████████████████████████████████████████████████████████████ .wait_data_r: IN A,(FDC_93.DrvCTRL) AND %1100'0000 ;b7: INTRQ (выполняется команда = 0). b6: DRQ (запрос данных = 1). JR Z,.wait_data_r JP P,.read_loop ; JUMP if "выполняется команда = 0" ; ; .after_rw: EX AF,AF' POP AF ; возвращаем текущую страницу OUT (SLOT3),A EX AF,AF' ; POP DE POP HL LD A,BIOS.Error.NotReady JR C,.CMD_ERROR ; IN A,(FDC_93.Command) LD C,A AND #7F RET Z ; NORMAL EXIT ; BIT 6,C LD A,BIOS.Error.WriteProtect JR NZ,.error_exit ; BIT 2,C JR NZ,.data_lost ; Error Read ; LD A,BIOS.Error.Seek .CMD_ERROR: DEC D ; FDD_COUNTERS.RW_Retries JR Z,.error_exit ; PUSH DE PUSH HL CALL RESWG ; RESET_WG ;!FIXIT контроль ошибки LD A,XL CALL SEEK ; !!!!! посмотреть ;!FIXIT контроль ошибки POP HL POP DE JR .RETRY ; .wait_loop_next: INC DE LD A,E OR D JR NZ,.wait_loop ; 26 ; DJNZ .wait_loop SCF JR .after_rw ; error ; ; .data_lost: DEC D ; потеря данных JR NZ,.RETRY ; EXX BIT 5,B EXX LD A,BIOS.Error.Read ; Error Read JR Z,.error_exit ; LD A,BIOS.Error.Write ; Error Write .error_exit: EX AF,AF' LD A,#D0 ;!HARDCODE CMD КР1818ВГ93 OUT (FDC_93.Command),A ;STOP OPERATION EX AF,AF' BIT 0,C SCF RET Z LD A,BIOS.Error.SectorNotFound RET ; ;██████████ КРИТИЧНЫЙ К СКОРОСТИ КУСОК ПОСЛЕ УСТАНОВКИ КОМАНДЫ ДО СНЯТИЯ РЕЗУЛЬТАТА ██████████ ;WRITE BYTE ;.go_write: EX AF,AF' .write_loop: EXX DEC DE LD A,D OR E EXX JR Z,.SectorSizeError ; OUTI ;█████████████████████████████████████████████████████████████████████████████████████████████ .wait_data_w: IN A,(FDC_93.DrvCTRL) AND %1100'0000 ;b6: DRQ (запрос данных = 1). b7: INTRQ (выполняется команда = 0). JR Z,.wait_data_w JP P,.write_loop JP .after_rw ; .SectorSizeError: ; A = 0 LD C,A POP AF ; возвращаем текущую страницу OUT (SLOT3),A POP DE POP HL LD A,BIOS.Error.UnknownDevice JR .error_exit ; ; Врубает третью карту портов SET_DOS_ON: EX AF,AF' LD A,CNF_PORT.CNF_3 + ROM.BIOS OUT (SYS_PORT.ROM),A ; - OPEN EX AF,AF' RET ; Врубает нулевую карту портов SET_DOS_OFF: EX AF,AF' LD A,CNF_PORT.CNF_0 + ROM.BIOS OUT (SYS_PORT.ROM),A ; - CLOSE EX AF,AF' RET //////////////////////////////////////////////////////////////////////// ; НЕ ГРОХАТЬ. Версия для FDD AUTO одним буфером FDD_TABLE ; SET_FDD: PUSH BC ; AND 1 ; LD B,A ; OR #3C ; OUT (FDC_93.DrvCTRL),A ; IN A,(SLOT3) ; EX AF,AF' ; LD A,SYS_PAGE ; OUT (SLOT3),A ; LD A,(SYS_PAGE.FDD_TABLE.DISK) ; AND #FE ; OR B ; LD (SYS_PAGE.FDD_TABLE.DISK),A ; EX AF,AF' ; OUT (SLOT3),A ; POP BC ; RET //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// SELECT_FDD: PUSH BC OR A LD IY,SYS_PAGE.FDD_TABLE.A JR Z,.IY_Selected ; LD IY,SYS_PAGE.FDD_TABLE.B .IY_Selected: ;LD B,A OR #3C OUT (FDC_93.DrvCTRL),A IN A,(SLOT3) EX AF,AF' LD A,SYS_PAGE OUT (SLOT3),A LD B,(IY + FDD_TABLE_s.ID) EX AF,AF' OUT (SLOT3),A INC B POP BC RET NZ ; no drive LD A,BIOS.Error.BadNumber SCF RET //////////////////////////////////////////////////////////////////////// ;----------------------------------------------------------------------; ; CHANGE_SPEED: IN A,(SLOT3) ; EX AF,AF' ; LD A,SYS_PAGE ; OUT (SLOT3),A ; LD A,(SYS_PAGE.FDD_TABLE.DISK) ; XOR #80 ; LD (SYS_PAGE.FDD_TABLE.DISK),A ; RLA ; EX AF,AF' ; OUT (SLOT3),A ; EX AF,AF' ; JR NC,FDD.SET720 ; FDD.SET1440: LD A,FDD_Density.SET_1440 ; OUT (FDD_Density),A ; RET ; ; ; ; ; SET_SPEED: IN A,(SLOT3) ; EX AF,AF' ; LD A,SYS_PAGE ; OUT (SLOT3),A ; LD A,(SYS_PAGE.FDD_TABLE.DISK) ; ;AND #80 ; RLA ; EX AF,AF' ; OUT (SLOT3),A ; EX AF,AF' ; JR C,FDD.SET1440 ; FDD.SET720: LD A,FDD_Density.SET_720 ; OUT (FDD_Density),A ; RET ; ; Вход: IY - Указатель на таблицу выбранного FDD CHANGE_SPEED: IN A,(SLOT3) EX AF,AF' LD A,SYS_PAGE OUT (SLOT3),A LD A,(IY + FDD_TABLE_s.DISK) XOR #80 LD (IY + FDD_TABLE_s.DISK),A JR SET_SPEED.set ; SET_SPEED: IN A,(SLOT3) EX AF,AF' LD A,SYS_PAGE OUT (SLOT3),A LD A,(IY + FDD_TABLE_s.DISK) .set: AND #80 RRA RRA OR 1 OUT (FDD_Density),A EX AF,AF' OUT (SLOT3),A RET ;----------------------------------------------------------------------; //////////////////////////////////////////////////////////////////////// ; Вход: BC - внутренний и внешний счётчики ; IY - Указатель на таблицу выбранного FDD WAIT_FDD_FOR_SEARCH_TRACK: LD A,#C0 ;!HARDCODE CMD КР1818ВГ93 OUT (FDC_93.Command),A PUSH BC CALL .LOOP POP BC RET NC ; CALL CHANGE_SPEED DEC C JR NZ,WAIT_FDD_FOR_SEARCH_TRACK ; SCF RET ; .LOOP: LD HL,#F000 .loop_reg_HL: IN A,(FDC_93.DrvCTRL) AND #C0 RET NZ ; .ID_LP4: DEC HL LD A,H OR L JR NZ,.loop_reg_HL ; DJNZ .LOOP SCF RET //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// ; прерывания должны быть отключены ; Вход: IY - Указатель на таблицу выбранного FDD ; Выход: A - bit7 - 720/1440, B - sector size high byte DISK_ID: EXX CALL SET_SPEED IN A,(FDC_93.Track) OUT (FDC_93.Data),A LD A,#18 ;!TODO выписать комманды ВГ ;SEARCH ;!HARDCODE CMD КР1818ВГ93 CALL EXECOM ; кусок для быстрых флоппарей LD BC,#0104 ; счётчики CALL WAIT_FDD_FOR_SEARCH_TRACK JR NC,.Read_Index ; кусок для тормозных флоппарей LD BC,#0804 ; счётчики CALL WAIT_FDD_FOR_SEARCH_TRACK JR NC,.Read_Index EXX ;SCF LD A,BIOS.Error.NotReady RET ; .Read_Index: ; ; Данные FDC_93.Data: ; номер цилиндра BYTE ; номер головки BYTE ; номер сектора BYTE ; длина сектора BYTE ; контрольная сумма WORD LD H,4 ; !HARDCODE счётчик до байта размера сектора .ID_LP2: IN A,(FDC_93.Data) DEC H JR NZ,.ID_LP3 LD L,A ; [ ] размера сектора (старший байт) .ID_LP3: IN A,(FDC_93.DrvCTRL) AND %1100'0000 JR Z,.ID_LP3 JP P,.ID_LP2 LD A,L EXX LD B,A ; [ ] размера сектора (старший байт) IN A,(SLOT3) EX AF,AF' LD A,SYS_PAGE OUT (SLOT3),A LD A,(IY + FDD_TABLE_s.DISK) EX AF,AF' OUT (SLOT3),A EX AF,AF' AND #80 RET //////////////////////////////////////////////////////////////////////// ; in: A - track SEEK: LD XL,A LD C,A IN A,(SLOT3) EX AF,AF' LD A,SYS_PAGE OUT (SLOT3),A LD A,(IY + FDD_TABLE_s.DISK) AND 1 EX AF,AF' OUT (SLOT3),A EX AF,AF' SRL C JR C,.GT001 ; OR #3C .GT001: OR #2C OUT (FDC_93.DrvCTRL),A IN A,(FDC_93.Track) CP C CALL NZ,P50ms LD A,C OUT (FDC_93.Data),A IN A,(FDC_93.Track) CP C EX AF,AF' ;R.TRACK==PHISICAL TRACK LD A,#18 ;!HARDCODE CMD КР1818ВГ93 CALL EXECOM RET C EX AF,AF' LD A,C OUT (FDC_93.Track),A RET Z .STOL: CALL P50ms RET ; P50ms: PUSH BC LD B,12 .P1ms: LD C,255 .PMS: DEC C JR NZ,.PMS DJNZ .P1ms POP BC RET ; ; ;P750ms LD B,3 ;PMS2 LD A,255 ; CALL P1ms ; DJNZ PMS2 ; RET //////////////////////////////////////////////////////////////////////// ;RESWG: LD A,8 ; ; ;EXECOM: OUT (FDC_93.Command),A ; LD HL,#0000 ; счётчик ;.WREST: DEC HL ; LD A,H ; OR L ; SCF ; RET Z ; ; ; IN A,(FDC_93.DrvCTRL) ; AND #80 ; JR Z,.WREST ; RET ; RESWG: LD A,8 ;!HARDCODE CMD КР1818ВГ93 EXECOM: OUT (FDC_93.Command),A LD HL,#0000 ; счётчик PUSH BC LD BC,#0380 ; счётчик и маска .WREST: DEC HL LD A,H OR L JR NZ,.get_state DJNZ .WREST POP BC SCF RET ; .get_state: IN A,(FDC_93.DrvCTRL) AND C JR Z,.WREST POP BC RET //////////////////////////////////////////////////////////////////////// ; ;------------------------------- ; HL:IX - SECTOR ; H - TRACK, L - SECTOR ;HL:IX/SECTOR_PER_TRACK NTRACK: PUSH HL EX (SP),IX POP HL IN A,(SLOT3) EX AF,AF' LD A,SYS_PAGE OUT (SLOT3),A LD C,(IY + FDD_TABLE_s.SECTORS) LD B,0 EX AF,AF' OUT (SLOT3),A XOR A .NTRK: INC A SBC HL,BC JR NC,.NTRK ; EX AF,AF' LD A,XL OR XH JR Z,.NTRK3 ; EX AF,AF' DEC IX JR .NTRK ; .NTRK3: EX AF,AF' ADD HL,BC DEC A LD H,A RET ; SAVE_INTERRUPTS: .switch_off: PUSH AF LD A,R DI LD A,#80 JP PE,.set_R XOR A .set_R: LD R,A POP AF RET ; ; .restore: PUSH AF LD A,R DI RLA JR NC,.set_di EI .set_di: POP AF ; PE RET ;[]===========================================================[]