;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                                                              ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License    ;;
;;                                                              ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

$Revision$


;**********************************************************
;  Íåïîñðåäñòâåííàÿ ðàáîòà ñ êîíòðîëëåðîì ãèáêîãî äèñêà
;**********************************************************
; Àâòîð èñõîäíîãî òåêñòà  Êóëàêîâ Âëàäèìèð Ãåííàäüåâè÷.
; Àäàïòàöèÿ è äîðàáîòêà Mario79

;give_back_application_data:  ; ïåðåñëàòü ïðèëîæåíèþ
;     mov edi,[TASK_BASE]
;     mov edi,[edi+TASKDATA.mem_start]
;     add edi,ecx
give_back_application_data_1:
     mov esi,FDD_BUFF   ;FDD_DataBuffer  ;0x40000
     xor ecx,ecx
     mov cx,128
     cld
     rep movsd
     ret

;take_data_from_application:   ; âçÿòü èç ïðèëîæåíè
;     mov esi,[TASK_BASE]
;     mov esi,[esi+TASKDATA.mem_start]
;     add esi,ecx
take_data_from_application_1:
     mov edi,FDD_BUFF   ;FDD_DataBuffer  ;0x40000
     xor ecx,ecx
     mov cx,128
     cld
     rep movsd
     ret

; Êîäû çàâåðøåíèÿ îïåðàöèè ñ êîíòðîëëåðîì (FDC_Status)
FDC_Normal         equ 0 ;íîðìàëüíîå çàâåðøåíèå
FDC_TimeOut        equ 1 ;îøèáêà òàéì-àóòà
FDC_DiskNotFound   equ 2 ;â äèñêîâîäå íåò äèñêà
FDC_TrackNotFound  equ 3 ;äîðîæêà íå íàéäåíà
FDC_SectorNotFound equ 4 ;ñåêòîð íå íàéäåí

; Ìàêñèìàëüíûå çíà÷åíèÿ êîîðäèíàò ñåêòîðà (çàäàííûå
; çíà÷åíèÿ ñîîòâåòñòâóþò ïàðàìåòðàì ñòàíäàðòíîãî
; òðåõäþéìîâîãî ãèáêîãî äèñêà îáúåìîì 1,44 Ìá)
MAX_Track   equ 79
MAX_Head    equ  1
MAX_Sector  equ 18

uglobal
; Ñ÷åò÷èê òèêîâ òàéìåðà
TickCounter dd ?
; Êîä çàâåðøåíèÿ îïåðàöèè ñ êîíòðîëëåðîì ÍÃÌÄ
FDC_Status  DB ?
; Ôëàã ïðåðûâàíèÿ îò ÍÃÌÄ
FDD_IntFlag DB ?
; Ìîìåíò íà÷àëà ïîñëåäíåé îïåðàöèè ñ ÍÃÌÄ
FDD_Time    DD ?
; Íîìåð äèñêîâîäà
FDD_Type    db 0
; Êîîðäèíàòû ñåêòîðà
FDD_Track   DB ?
FDD_Head    DB ?
FDD_Sector  DB ?

; Áëîê ðåçóëüòàòà îïåðàöèè
FDC_ST0 DB ?
FDC_ST1 DB ?
FDC_ST2 DB ?
FDC_C   DB ?
FDC_H   DB ?
FDC_R   DB ?
FDC_N   DB ?
; Ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ÷òåíè
ReadRepCounter  DB ?
; Ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ðåêàëèáðîâêè
RecalRepCounter DB ?
endg
; Îáëàñòü ïàìÿòè äëÿ õðàíåíèÿ ïðî÷èòàííîãî ñåêòîðà
;FDD_DataBuffer:  times 512 db 0   ;DB 512 DUP (?)
fdd_motor_status db 0
timer_fdd_motor  dd 0

;*************************************
;* ÈÍÈÖÈÀËÈÇÀÖÈß ÐÅÆÈÌÀ ÏÄÏ ÄËß ÍÃÌÄ *
;*************************************
Init_FDC_DMA:
        pushad
        mov al,0
        out 0x0c,al     ; reset the flip-flop to a known state.
        mov al,6                ; mask channel 2 so we can reprogram it.
        out 0x0a,al
        mov al,[dmamode] ; 0x46 -> Read from floppy - 0x4A Write to floppy
        out 0x0b,al
        mov al,0
        out 0x0c,al     ; reset the flip-flop to a known state.
        mov eax,0xD000
        out 0x04,al     ; set the channel 2 starting address to 0
        shr eax,8
        out 0x04,al
        shr eax,8
        out 0x81,al
        mov al,0
        out 0x0c, al    ; reset flip-flop
        mov al, 0xff    ;set count (actual size -1)
        out 0x5, al
        mov al,0x1  ;[dmasize]       ;(0x1ff = 511 / 0x23ff =9215)
        out 0x5,al
        mov al,2
        out 0xa,al
        popad
        ret

;***********************************
;* ÇÀÏÈÑÀÒÜ ÁÀÉÒ Â ÏÎÐÒ ÄÀÍÍÛÕ FDC *
;* Ïàðàìåòðû:                      *
;* AL - âûâîäèìûé áàéò.            *
;***********************************
FDCDataOutput:
;        pusha
        push eax ecx edx
        mov     AH,AL     ;çàïîìíèòü áàéò â AH
; Ñáðîñèòü ïåðåìåííóþ ñîñòîÿíèÿ êîíòðîëëåðà
        mov     [FDC_Status],FDC_Normal
; Ïðîâåðèòü ãîòîâíîñòü êîíòðîëëåðà ê ïðèåìó äàííûõ
        mov     DX,3F4h   ;(ïîðò ñîñòîÿíèÿ FDC)
        mov     ecx, 0x10000 ;óñòàíîâèòü ñ÷åò÷èê òàéì-àóòà
@@TestRS:
        in      AL,DX     ;ïðî÷èòàòü ðåãèñòð RS
        and     AL,0C0h   ;âûäåëèòü ðàçðÿäû 6 è 7
        cmp     AL,80h    ;ïðîâåðèòü ðàçðÿäû 6 è 7
        je      @@OutByteToFDC
        loop    @@TestRS
; Îøèáêà òàéì-àóòà
        mov     [FDC_Status],FDC_TimeOut
        jmp @@End_5
; Âûâåñòè áàéò â ïîðò äàííûõ
@@OutByteToFDC:
        inc     DX
        mov     AL,AH
        out     DX,AL
@@End_5:
;        popa
        pop edx ecx eax
        ret

;******************************************
;*   ÏÐÎ×ÈÒÀÒÜ ÁÀÉÒ ÈÇ ÏÎÐÒÀ ÄÀÍÍÛÕ FDC   *
;* Ïðîöåäóðà íå èìååò âõîäíûõ ïàðàìåòðîâ. *
;* Âûõîäíûå äàííûå:                       *
;* AL - ñ÷èòàííûé áàéò.                   *
;******************************************
FDCDataInput:
        push    ECX
        push    DX
; Ñáðîñèòü ïåðåìåííóþ ñîñòîÿíèÿ êîíòðîëëåðà
        mov     [FDC_Status],FDC_Normal
; Ïðîâåðèòü ãîòîâíîñòü êîíòðîëëåðà ê ïåðåäà÷å äàííûõ
        mov     DX,3F4h   ;(ïîðò ñîñòîÿíèÿ FDC)
        xor     CX,CX     ;óñòàíîâèòü ñ÷åò÷èê òàéì-àóòà
@@TestRS_1:
        in      AL,DX     ;ïðî÷èòàòü ðåãèñòð RS
        and     AL,0C0h   ;âûäëèòü ðàçðÿäû 6 è 7
        cmp     AL,0C0h   ;ïðîâåðèòü ðàçðÿäû 6 è 7
        je      @@GetByteFromFDC
        loop    @@TestRS_1
; Îøèáêà òàéì-àóòà
        mov     [FDC_Status],FDC_TimeOut
        jmp @@End_6
; Ââåñòè áàéò èç ïîðòà äàííûõ
@@GetByteFromFDC:
        inc     DX
        in      AL,DX
@@End_6:  pop     DX
        pop     ECX
        ret

;*********************************************
;* ÎÁÐÀÁÎÒ×ÈÊ ÏÐÅÐÛÂÀÍÈß ÎÒ ÊÎÍÒÐÎËËÅÐÀ ÍÃÌÄ *
;*********************************************
FDCInterrupt:
; Óñòàíîâèòü ôëàã ïðåðûâàíè
        mov     [FDD_IntFlag],1
        ret


;******************************************
;* ÓÑÒÀÍÎÂÈÒÜ ÍÎÂÛÉ ÎÁÐÀÁÎÒ×ÈÊ ÏÐÅÐÛÂÀÍÈÉ *
;*             ÍÃÌÄ                       *
;******************************************
SetUserInterrupts:
         mov     [fdc_irq_func],FDCInterrupt
         ret

;*******************************************
;* ÎÆÈÄÀÍÈÅ ÏÐÅÐÛÂÀÍÈß ÎÒ ÊÎÍÒÐÎËËÅÐÀ ÍÃÌÄ *
;*******************************************
WaitFDCInterrupt:
        pusha
; Ñáðîñèòü áàéò ñîñòîÿíèÿ îïåðàöèè
        mov     [FDC_Status],FDC_Normal
; Ñáðîñèòü ôëàã ïðåðûâàíè
        mov     [FDD_IntFlag],0
; Îáíóëèòü ñ÷åò÷èê òèêîâ
        mov     eax,[timer_ticks]
        mov     [TickCounter],eax
; Îæèäàòü óñòàíîâêè ôëàãà ïðåðûâàíèÿ ÍÃÌÄ
@@TestRS_2:
        cmp     [FDD_IntFlag],0
        jnz     @@End_7           ;ïðåðûâàíèå ïðîèçîøëî
        call    change_task
        mov     eax,[timer_ticks]
        sub     eax,[TickCounter]
        cmp     eax,50  ;25   ;5 ;îæèäàòü 5 òèêîâ
        jb      @@TestRS_2
;        jl      @@TestRS_2
; Îøèáêà òàéì-àóòà
        mov     [FDC_Status],FDC_TimeOut
;        mov   [flp_status],0
@@End_7:  popa
        ret

;*********************************
;* ÂÊËÞ×ÈÒÜ ÌÎÒÎÐ ÄÈÑÊÎÂÎÄÀ "A:" *
;*********************************
FDDMotorON:
        pusha
;        cmp     [fdd_motor_status],1
;        je      fdd_motor_on
        mov     al,[flp_number]
        cmp     [fdd_motor_status],al
        je      fdd_motor_on
; Ïðîèçâåñòè ñáðîñ êîíòðîëëåðà ÍÃÌÄ
        mov     DX,3F2h ;ïîðò óïðàâëåíèÿ äâèãàòåëÿìè
        mov     AL,0
        out     DX,AL
; Âûáðàòü è âêëþ÷èòü ìîòîð äèñêîâîäà
        cmp     [flp_number],1
        jne     FDDMotorON_B
;        call    FDDMotorOFF_B
        mov     AL,1Ch    ; Floppy A
        jmp     FDDMotorON_1
FDDMotorON_B:
;        call    FDDMotorOFF_A
        mov     AL,2Dh    ; Floppy B
FDDMotorON_1:
        out     DX,AL
; Îáíóëèòü ñ÷åò÷èê òèêîâ
        mov     eax,[timer_ticks]
        mov     [TickCounter],eax
; Îæèäàòü 0,5 ñ
@@dT:
        call    change_task
        mov     eax,[timer_ticks]
        sub     eax,[TickCounter]
        cmp     eax,50  ;10
        jb      @@dT
        cmp     [flp_number],1
        jne     fdd_motor_on_B
        mov     [fdd_motor_status],1
        jmp     fdd_motor_on
fdd_motor_on_B:
        mov     [fdd_motor_status],2
fdd_motor_on:
        call    save_timer_fdd_motor
        popa
        ret

;*****************************************
;*  ÑÎÕÐÀÍÅÍÈÅ ÓÊÀÇÀÒÅËß ÂÐÅÌÅÍÈ         *
;*****************************************
save_timer_fdd_motor:
        mov     eax,[timer_ticks]
        mov     [timer_fdd_motor],eax
        ret

;*****************************************
;*  ÏÐÎÂÅÐÊÀ ÇÀÄÅÐÆÊÈ ÂÛÊËÞ×ÅÍÈß ÌÎÒÎÐÀ  *
;*****************************************
check_fdd_motor_status:
        cmp     [fdd_motor_status],0
        je      end_check_fdd_motor_status_1
        mov     eax,[timer_ticks]
        sub     eax,[timer_fdd_motor]
        cmp     eax,500
        jb      end_check_fdd_motor_status
        call    FDDMotorOFF
        mov     [fdd_motor_status],0
end_check_fdd_motor_status_1:
        mov     [flp_status],0
end_check_fdd_motor_status:
        ret

;**********************************
;* ÂÛÊËÞ×ÈÒÜ ÌÎÒÎÐ ÄÈÑÊÎÂÎÄÀ      *
;**********************************
FDDMotorOFF:
        push    AX
        push    DX
        cmp     [flp_number],1
        jne     FDDMotorOFF_1
        call    FDDMotorOFF_A
        jmp     FDDMotorOFF_2
FDDMotorOFF_1:
        call    FDDMotorOFF_B
FDDMotorOFF_2:
        pop     DX
        pop     AX
        ; ñáðîñ ôëàãîâ êåøèðîâàíèÿ â ñâÿçè ñ óñòàðåâàíèåì èíôîðìàöèè
        mov    [root_read],0
        mov    [flp_fat],0
        ret

FDDMotorOFF_A:
        mov     DX,3F2h ;ïîðò óïðàâëåíèÿ äâèãàòåëÿìè
        mov     AL,0Ch  ; Floppy A
        out     DX,AL
        ret

FDDMotorOFF_B:
        mov     DX,3F2h ;ïîðò óïðàâëåíèÿ äâèãàòåëÿìè
        mov     AL,5h  ; Floppy B
        out     DX,AL
        ret

;*******************************
;* ÐÅÊÀËÈÁÐÎÂÊÀ ÄÈÑÊÎÂÎÄÀ "A:" *
;*******************************
RecalibrateFDD:
        pusha
        call    save_timer_fdd_motor
; Ïîäàòü êîìàíäó "Ðåêàëèáðîâêà"
        mov     AL,07h
        call    FDCDataOutput
        mov     AL,00h
        call    FDCDataOutput
; Îæèäàòü çàâåðøåíèÿ îïåðàöèè
        call    WaitFDCInterrupt
;        cmp    [FDC_Status],0
;        je    no_fdc_status_error
;        mov   [flp_status],0
;no_fdc_status_error:
        call    save_timer_fdd_motor
        popa
        ret

;*****************************************************
;*                    ÏÎÈÑÊ ÄÎÐÎÆÊÈ                  *
;* Ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå ïåðåìåííûå: *
;* FDD_Track - íîìåð äîðîæêè (0-79);                 *
;* FDD_Head - íîìåð ãîëîâêè (0-1).                   *
;* Ðåçóëüòàò îïåðàöèè çàíîñèòñÿ â FDC_Status.        *
;*****************************************************
SeekTrack:
        pusha
        call    save_timer_fdd_motor
; Ïîäàòü êîìàíäó "Ïîèñê"
        mov     AL,0Fh
        call    FDCDataOutput
        ; Ïåðåäàòü áàéò íîìåðà ãîëîâêè/íàêîïèòåë
        mov     AL,[FDD_Head]
        shl     AL,2
        call    FDCDataOutput
        ; Ïåðåäàòü áàéò íîìåðà äîðîæêè
        mov     AL,[FDD_Track]
        call    FDCDataOutput
; Îæèäàòü çàâåðøåíèÿ îïåðàöèè
        call    WaitFDCInterrupt
        cmp     [FDC_Status],FDC_Normal
        jne     @@Exit
; Ñîõðàíèòü ðåçóëüòàò ïîèñêà
        mov     AL,08h
        call    FDCDataOutput
        call    FDCDataInput
        mov     [FDC_ST0],AL
        call    FDCDataInput
        mov     [FDC_C],AL
; Ïðîâåðèòü ðåçóëüòàò ïîèñêà
        ; Ïîèñê çàâåðøåí?
        test    [FDC_ST0],100000b
        je      @@Err
        ; Çàäàííûé òðåê íàéäåí?
        mov     AL,[FDC_C]
        cmp     AL,[FDD_Track]
        jne     @@Err
        ; Íîìåð ãîëîâêè ñîâïàäàåò ñ çàäàííûì?
        mov     AL,[FDC_ST0]
        and     AL,100b
        shr     AL,2
        cmp     AL,[FDD_Head]
        jne     @@Err
        ; Îïåðàöèÿ çàâåðøåíà óñïåøíî
        mov     [FDC_Status],FDC_Normal
        jmp @@Exit
@@Err:  ; Òðåê íå íàéäåí
        mov     [FDC_Status],FDC_TrackNotFound
;        mov   [flp_status],0
@@Exit:
        call    save_timer_fdd_motor
        popa
        ret

;*******************************************************
;*               ×ÒÅÍÈÅ ÑÅÊÒÎÐÀ ÄÀÍÍÛÕ                 *
;* Ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå ïåðåìåííûå:   *
;* FDD_Track - íîìåð äîðîæêè (0-79);                   *
;* FDD_Head - íîìåð ãîëîâêè (0-1);                     *
;* FDD_Sector - íîìåð ñåêòîðà (1-18).                  *
;* Ðåçóëüòàò îïåðàöèè çàíîñèòñÿ â FDC_Status.          *
;*  ñëó÷àå óñïåøíîãî âûïîëíåíèÿ îïåðàöèè ÷òåíèÿ       *
;* ñîäåðæèìîå ñåêòîðà áóäåò çàíåñåíî â FDD_DataBuffer. *
;*******************************************************
ReadSector:
        pushad
        call    save_timer_fdd_motor
; Óñòàíîâèòü ñêîðîñòü ïåðåäà÷è 500 Êáàéò/ñ
        mov     AX,0
        mov     DX,03F7h
        out     DX,AL
; Èíèöèàëèçèðîâàòü êàíàë ïðÿìîãî äîñòóïà ê ïàìÿòè
        mov     [dmamode],0x46
        call    Init_FDC_DMA
; Ïîäàòü êîìàíäó "×òåíèå äàííûõ"
        mov     AL,0E6h  ;÷òåíèå â ìóëüòèòðåêîâîì ðåæèìå
        call    FDCDataOutput
        mov     AL,[FDD_Head]
        shl     AL,2
        call    FDCDataOutput
        mov     AL,[FDD_Track]
        call    FDCDataOutput
        mov     AL,[FDD_Head]
        call    FDCDataOutput
        mov     AL,[FDD_Sector]
        call    FDCDataOutput
        mov     AL,2    ;êîä ðàçìåðà ñåêòîðà (512 áàéò)
        call    FDCDataOutput
        mov     AL,18  ;+1; 3Fh  ;÷èñëî ñåêòîðîâ íà äîðîæêå
        call    FDCDataOutput
        mov     AL,1Bh  ;çíà÷åíèå GPL
        call    FDCDataOutput
        mov     AL,0FFh ;çíà÷åíèå DTL
        call    FDCDataOutput
; Îæèäàåì ïðåðûâàíèå ïî çàâåðøåíèè îïåðàöèè
        call    WaitFDCInterrupt
        cmp     [FDC_Status],FDC_Normal
        jne     @@Exit_1
; Ñ÷èòûâàåì ñòàòóñ çàâåðøåíèÿ îïåðàöèè
        call    GetStatusInfo
        test    [FDC_ST0],11011000b
        jnz     @@Err_1
        mov     [FDC_Status],FDC_Normal
        jmp @@Exit_1
@@Err_1:  mov     [FDC_Status],FDC_SectorNotFound
;        mov   [flp_status],0
@@Exit_1:
        call    save_timer_fdd_motor
        popad
        ret

;*******************************************************
;*   ×ÒÅÍÈÅ ÑÅÊÒÎÐÀ (Ñ ÏÎÂÒÎÐÅÍÈÅÌ ÎÏÅÐÀÖÈÈ ÏÐÈ ÑÁÎÅ)  *
;* Ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå ïåðåìåííûå:   *
;* FDD_Track - íîìåð äîðîæêè (0-79);                   *
;* FDD_Head - íîìåð ãîëîâêè (0-1);                     *
;* FDD_Sector - íîìåð ñåêòîðà (1-18).                  *
;* Ðåçóëüòàò îïåðàöèè çàíîñèòñÿ â FDC_Status.          *
;*  ñëó÷àå óñïåøíîãî âûïîëíåíèÿ îïåðàöèè ÷òåíèÿ       *
;* ñîäåðæèìîå ñåêòîðà áóäåò çàíåñåíî â FDD_DataBuffer. *
;*******************************************************
ReadSectWithRetr:
        pusha
; Îáíóëèòü ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ðåêàëèáðîâêè
        mov     [RecalRepCounter],0
@@TryAgain:
; Îáíóëèòü ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ÷òåíè
        mov     [ReadRepCounter],0
@@ReadSector_1:
        call    ReadSector
        cmp     [FDC_Status],0
        je      @@Exit_2
        cmp     [FDC_Status],1
        je      @@Err_3
        ; Òðîåêðàòíîå ïîâòîðåíèå ÷òåíè
        inc     [ReadRepCounter]
        cmp     [ReadRepCounter],3
        jb      @@ReadSector_1
        ; Òðîåêðàòíîå ïîâòîðåíèå ðåêàëèáðîâêè
        call    RecalibrateFDD
        call    SeekTrack
        inc     [RecalRepCounter]
        cmp     [RecalRepCounter],3
        jb      @@TryAgain
;        mov   [flp_status],0
@@Exit_2:
        popa
        ret
@@Err_3:
        mov   [flp_status],0
        popa
        ret

;*******************************************************
;*               ÇÀÏÈÑÜ ÑÅÊÒÎÐÀ ÄÀÍÍÛÕ                 *
;* Ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå ïåðåìåííûå:   *
;* FDD_Track - íîìåð äîðîæêè (0-79);                   *
;* FDD_Head - íîìåð ãîëîâêè (0-1);                     *
;* FDD_Sector - íîìåð ñåêòîðà (1-18).                  *
;* Ðåçóëüòàò îïåðàöèè çàíîñèòñÿ â FDC_Status.          *
;*  ñëó÷àå óñïåøíîãî âûïîëíåíèÿ îïåðàöèè çàïèñè       *
;* ñîäåðæèìîå FDD_DataBuffer áóäåò çàíåñåíî â ñåêòîð.  *
;*******************************************************
WriteSector:
        pushad
        call    save_timer_fdd_motor
; Óñòàíîâèòü ñêîðîñòü ïåðåäà÷è 500 Êáàéò/ñ
        mov     AX,0
        mov     DX,03F7h
        out     DX,AL
; Èíèöèàëèçèðîâàòü êàíàë ïðÿìîãî äîñòóïà ê ïàìÿòè
        mov     [dmamode],0x4A
        call    Init_FDC_DMA
; Ïîäàòü êîìàíäó "Çàïèñü äàííûõ"
        mov     AL,0xC5  ;0x45  ;çàïèñü â ìóëüòèòðåêîâîì ðåæèìå
        call    FDCDataOutput
        mov     AL,[FDD_Head]
        shl     AL,2
        call    FDCDataOutput
        mov     AL,[FDD_Track]
        call    FDCDataOutput
        mov     AL,[FDD_Head]
        call    FDCDataOutput
        mov     AL,[FDD_Sector]
        call    FDCDataOutput
        mov     AL,2    ;êîä ðàçìåðà ñåêòîðà (512 áàéò)
        call    FDCDataOutput
        mov     AL,18; 3Fh  ;÷èñëî ñåêòîðîâ íà äîðîæêå
        call    FDCDataOutput
        mov     AL,1Bh  ;çíà÷åíèå GPL
        call    FDCDataOutput
        mov     AL,0FFh ;çíà÷åíèå DTL
        call    FDCDataOutput
; Îæèäàåì ïðåðûâàíèå ïî çàâåðøåíèè îïåðàöèè
        call    WaitFDCInterrupt
        cmp     [FDC_Status],FDC_Normal
        jne     @@Exit_3
; Ñ÷èòûâàåì ñòàòóñ çàâåðøåíèÿ îïåðàöèè
        call    GetStatusInfo
        test    [FDC_ST0],11000000b  ;11011000b
        jnz     @@Err_2
        mov     [FDC_Status],FDC_Normal
        jmp @@Exit_3
@@Err_2:  mov     [FDC_Status],FDC_SectorNotFound
@@Exit_3:
        call    save_timer_fdd_motor
        popad
        ret

;*******************************************************
;*   ÇÀÏÈÑÜ ÑÅÊÒÎÐÀ (Ñ ÏÎÂÒÎÐÅÍÈÅÌ ÎÏÅÐÀÖÈÈ ÏÐÈ ÑÁÎÅ)  *
;* Ïàðàìåòðû ïåðåäàþòñÿ ÷åðåç ãëîáàëüíûå ïåðåìåííûå:   *
;* FDD_Track - íîìåð äîðîæêè (0-79);                   *
;* FDD_Head - íîìåð ãîëîâêè (0-1);                     *
;* FDD_Sector - íîìåð ñåêòîðà (1-18).                  *
;* Ðåçóëüòàò îïåðàöèè çàíîñèòñÿ â FDC_Status.          *
;*  ñëó÷àå óñïåøíîãî âûïîëíåíèÿ îïåðàöèè çàïèñè       *
;* ñîäåðæèìîå FDD_DataBuffer áóäåò çàíåñåíî â ñåêòîð.  *
;*******************************************************
WriteSectWithRetr:
        pusha
; Îáíóëèòü ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ðåêàëèáðîâêè
        mov     [RecalRepCounter],0
@@TryAgain_1:
; Îáíóëèòü ñ÷åò÷èê ïîâòîðåíèÿ îïåðàöèè ÷òåíè
        mov     [ReadRepCounter],0
@@WriteSector_1:
        call    WriteSector
        cmp     [FDC_Status],0
        je      @@Exit_4
        cmp     [FDC_Status],1
        je      @@Err_4
        ; Òðîåêðàòíîå ïîâòîðåíèå ÷òåíè
        inc     [ReadRepCounter]
        cmp     [ReadRepCounter],3
        jb      @@WriteSector_1
        ; Òðîåêðàòíîå ïîâòîðåíèå ðåêàëèáðîâêè
        call    RecalibrateFDD
        call    SeekTrack
        inc     [RecalRepCounter]
        cmp     [RecalRepCounter],3
        jb      @@TryAgain_1
@@Exit_4:
        popa
        ret
@@Err_4:
        mov   [flp_status],0
        popa
        ret

;*********************************************
;* ÏÎËÓ×ÈÒÜ ÈÍÔÎÐÌÀÖÈÞ Î ÐÅÇÓËÜÒÀÒÅ ÎÏÅÐÀÖÈÈ *
;*********************************************
GetStatusInfo:
        push    AX
        call    FDCDataInput
        mov     [FDC_ST0],AL
        call    FDCDataInput
        mov     [FDC_ST1],AL
        call    FDCDataInput
        mov     [FDC_ST2],AL
        call    FDCDataInput
        mov     [FDC_C],AL
        call    FDCDataInput
        mov     [FDC_H],AL
        call    FDCDataInput
        mov     [FDC_R],AL
        call    FDCDataInput
        mov     [FDC_N],AL
        pop     AX
        ret