Subversion Repositories Kolibri OS

Rev

Rev 4287 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4287 Rev 5201
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
7
 
8
$Revision: 4287 $
8
$Revision: 5201 $
9
 
9
 
10
 
10
 
11
;**********************************************************
11
;**********************************************************
12
;  Непосредственная работа с контроллером гибкого диска
12
;  Непосредственная работа с контроллером гибкого диска
13
;**********************************************************
13
;**********************************************************
14
; Автор исходного текста  Кулаков Владимир Геннадьевич.
14
; Автор исходного текста  Кулаков Владимир Геннадьевич.
15
; Адаптация и доработка Mario79
15
; Адаптация и доработка Mario79
16
 
16
 
17
;give_back_application_data:  ; переслать приложению
17
;give_back_application_data:  ; переслать приложению
18
;     mov edi,[TASK_BASE]
18
;     mov edi,[TASK_BASE]
19
;     mov edi,[edi+TASKDATA.mem_start]
19
;     mov edi,[edi+TASKDATA.mem_start]
20
;     add edi,ecx
20
;     add edi,ecx
21
give_back_application_data_1:
21
give_back_application_data_1:
22
        mov     esi, FDD_BUFF;FDD_DataBuffer  ;0x40000
22
        mov     esi, FDD_BUFF;FDD_DataBuffer  ;0x40000
23
        mov     ecx, 128
23
        mov     ecx, 128
24
        cld
24
        cld
25
        rep movsd
25
        rep movsd
26
        ret
26
        ret
27
 
27
 
28
;take_data_from_application:   ; взять из приложени
28
;take_data_from_application:   ; взять из приложени
29
;     mov esi,[TASK_BASE]
29
;     mov esi,[TASK_BASE]
30
;     mov esi,[esi+TASKDATA.mem_start]
30
;     mov esi,[esi+TASKDATA.mem_start]
31
;     add esi,ecx
31
;     add esi,ecx
32
take_data_from_application_1:
32
take_data_from_application_1:
33
        mov     edi, FDD_BUFF;FDD_DataBuffer  ;0x40000
33
        mov     edi, FDD_BUFF;FDD_DataBuffer  ;0x40000
34
        mov     ecx, 128
34
        mov     ecx, 128
35
        cld
35
        cld
36
        rep movsd
36
        rep movsd
37
        ret
37
        ret
38
 
38
 
39
; Коды завершения операции с контроллером (FDC_Status)
39
; Коды завершения операции с контроллером (FDC_Status)
40
FDC_Normal         equ 0 ;нормальное завершение
40
FDC_Normal         equ 0 ;нормальное завершение
41
FDC_TimeOut        equ 1 ;ошибка тайм-аута
41
FDC_TimeOut        equ 1 ;ошибка тайм-аута
42
FDC_DiskNotFound   equ 2 ;в дисководе нет диска
42
FDC_DiskNotFound   equ 2 ;в дисководе нет диска
43
FDC_TrackNotFound  equ 3 ;дорожка не найдена
43
FDC_TrackNotFound  equ 3 ;дорожка не найдена
44
FDC_SectorNotFound equ 4 ;сектор не найден
44
FDC_SectorNotFound equ 4 ;сектор не найден
45
 
45
 
46
; Максимальные значения координат сектора (заданные
46
; Максимальные значения координат сектора (заданные
47
; значения соответствуют параметрам стандартного
47
; значения соответствуют параметрам стандартного
48
; трехдюймового гибкого диска объемом 1,44 Мб)
48
; трехдюймового гибкого диска объемом 1,44 Мб)
49
MAX_Track   equ 79
49
MAX_Track   equ 79
50
MAX_Head    equ  1
50
MAX_Head    equ  1
51
MAX_Sector  equ 18
51
MAX_Sector  equ 18
52
 
52
 
53
uglobal
53
uglobal
54
; Счетчик тиков таймера
54
; Счетчик тиков таймера
55
TickCounter dd ?
55
TickCounter dd ?
56
; Код завершения операции с контроллером НГМД
56
; Код завершения операции с контроллером НГМД
57
FDC_Status  DB ?
57
FDC_Status  DB ?
58
; Флаг прерывания от НГМД
58
; Флаг прерывания от НГМД
59
FDD_IntFlag DB ?
59
FDD_IntFlag DB ?
60
; Момент начала последней операции с НГМД
60
; Момент начала последней операции с НГМД
61
FDD_Time    DD ?
61
FDD_Time    DD ?
62
; Номер дисковода
62
; Номер дисковода
63
FDD_Type    db 0
63
FDD_Type    db 0
64
; Координаты сектора
64
; Координаты сектора
65
FDD_Track   DB ?
65
FDD_Track   DB ?
66
FDD_Head    DB ?
66
FDD_Head    DB ?
67
FDD_Sector  DB ?
67
FDD_Sector  DB ?
68
 
68
 
69
; Блок результата операции
69
; Блок результата операции
70
FDC_ST0 DB ?
70
FDC_ST0 DB ?
71
FDC_ST1 DB ?
71
FDC_ST1 DB ?
72
FDC_ST2 DB ?
72
FDC_ST2 DB ?
73
FDC_C   DB ?
73
FDC_C   DB ?
74
FDC_H   DB ?
74
FDC_H   DB ?
75
FDC_R   DB ?
75
FDC_R   DB ?
76
FDC_N   DB ?
76
FDC_N   DB ?
77
; Счетчик повторения операции чтени
77
; Счетчик повторения операции чтени
78
ReadRepCounter  DB ?
78
ReadRepCounter  DB ?
79
; Счетчик повторения операции рекалибровки
79
; Счетчик повторения операции рекалибровки
80
RecalRepCounter DB ?
80
RecalRepCounter DB ?
81
endg
81
endg
82
; Область памяти для хранения прочитанного сектора
82
; Область памяти для хранения прочитанного сектора
83
;FDD_DataBuffer:  times 512 db 0   ;DB 512 DUP (?)
83
;FDD_DataBuffer:  times 512 db 0   ;DB 512 DUP (?)
84
fdd_motor_status db 0
84
fdd_motor_status db 0
85
timer_fdd_motor  dd 0
85
timer_fdd_motor  dd 0
86
 
86
 
87
;*************************************
87
;*************************************
88
;* ИНИЦИАЛИЗАЦИЯ РЕЖИМА ПДП ДЛЯ НГМД *
88
;* ИНИЦИАЛИЗАЦИЯ РЕЖИМА ПДП ДЛЯ НГМД *
89
;*************************************
89
;*************************************
90
Init_FDC_DMA:
90
Init_FDC_DMA:
91
        pushad
91
        pushad
92
        mov     al, 0
92
        mov     al, 0
93
        out     0x0c, al; reset the flip-flop to a known state.
93
        out     0x0c, al; reset the flip-flop to a known state.
94
        mov     al, 6           ; mask channel 2 so we can reprogram it.
94
        mov     al, 6           ; mask channel 2 so we can reprogram it.
95
        out     0x0a, al
95
        out     0x0a, al
96
        mov     al, [dmamode]; 0x46 -> Read from floppy - 0x4A Write to floppy
96
        mov     al, [dmamode]; 0x46 -> Read from floppy - 0x4A Write to floppy
97
        out     0x0b, al
97
        out     0x0b, al
98
        mov     al, 0
98
        mov     al, 0
99
        out     0x0c, al; reset the flip-flop to a known state.
99
        out     0x0c, al; reset the flip-flop to a known state.
100
        mov     eax, 0xD000
100
        mov     eax, 0xD000
101
        out     0x04, al; set the channel 2 starting address to 0
101
        out     0x04, al; set the channel 2 starting address to 0
102
        shr     eax, 8
102
        shr     eax, 8
103
        out     0x04, al
103
        out     0x04, al
104
        shr     eax, 8
104
        shr     eax, 8
105
        out     0x81, al
105
        out     0x81, al
106
        mov     al, 0
106
        mov     al, 0
107
        out     0x0c, al; reset flip-flop
107
        out     0x0c, al; reset flip-flop
108
        mov     al, 0xff;set count (actual size -1)
108
        mov     al, 0xff;set count (actual size -1)
109
        out     0x5, al
109
        out     0x5, al
110
        mov     al, 0x1;[dmasize]       ;(0x1ff = 511 / 0x23ff =9215)
110
        mov     al, 0x1;[dmasize]       ;(0x1ff = 511 / 0x23ff =9215)
111
        out     0x5, al
111
        out     0x5, al
112
        mov     al, 2
112
        mov     al, 2
113
        out     0xa, al
113
        out     0xa, al
114
        popad
114
        popad
115
        ret
115
        ret
116
 
116
 
117
;***********************************
117
;***********************************
118
;* ЗАПИСАТЬ БАЙТ В ПОРТ ДАННЫХ FDC *
118
;* ЗАПИСАТЬ БАЙТ В ПОРТ ДАННЫХ FDC *
119
;* Параметры:                      *
119
;* Параметры:                      *
120
;* AL - выводимый байт.            *
120
;* AL - выводимый байт.            *
121
;***********************************
121
;***********************************
122
FDCDataOutput:
122
FDCDataOutput:
123
;       DEBUGF 1,'K : FDCDataOutput(%x)',al
123
;       DEBUGF 1,'K : FDCDataOutput(%x)',al
124
;        pusha
124
;        pusha
125
        push    eax ecx edx
125
        push    eax ecx edx
126
        mov     AH, AL    ;запомнить байт в AH
126
        mov     AH, AL    ;запомнить байт в AH
127
; Сбросить переменную состояния контроллера
127
; Сбросить переменную состояния контроллера
128
        mov     [FDC_Status], FDC_Normal
128
        mov     [FDC_Status], FDC_Normal
129
; Проверить готовность контроллера к приему данных
129
; Проверить готовность контроллера к приему данных
130
        mov     DX, 3F4h  ;(порт состояния FDC)
130
        mov     DX, 3F4h  ;(порт состояния FDC)
131
        mov     ecx, 0x10000 ;установить счетчик тайм-аута
131
        mov     ecx, 0x10000 ;установить счетчик тайм-аута
132
@@TestRS:
132
@@TestRS:
133
        in      AL, DX    ;прочитать регистр RS
133
        in      AL, DX    ;прочитать регистр RS
134
        and     AL, 0C0h  ;выделить разряды 6 и 7
134
        and     AL, 0C0h  ;выделить разряды 6 и 7
135
        cmp     AL, 80h   ;проверить разряды 6 и 7
135
        cmp     AL, 80h   ;проверить разряды 6 и 7
136
        je      @@OutByteToFDC
136
        je      @@OutByteToFDC
137
        loop    @@TestRS
137
        loop    @@TestRS
138
; Ошибка тайм-аута
138
; Ошибка тайм-аута
139
;       DEBUGF 1,' timeout\n'
139
;       DEBUGF 1,' timeout\n'
140
        mov     [FDC_Status], FDC_TimeOut
140
        mov     [FDC_Status], FDC_TimeOut
141
        jmp     @@End_5
141
        jmp     @@End_5
142
; Вывести байт в порт данных
142
; Вывести байт в порт данных
143
@@OutByteToFDC:
143
@@OutByteToFDC:
144
        inc     DX
144
        inc     DX
145
        mov     AL, AH
145
        mov     AL, AH
146
        out     DX, AL
146
        out     DX, AL
147
;        DEBUGF 1,' ok\n'
147
;        DEBUGF 1,' ok\n'
148
@@End_5:
148
@@End_5:
149
;        popa
149
;        popa
150
        pop     edx ecx eax
150
        pop     edx ecx eax
151
        ret
151
        ret
152
 
152
 
153
;******************************************
153
;******************************************
154
;*   ПРОЧИТАТЬ БАЙТ ИЗ ПОРТА ДАННЫХ FDC   *
154
;*   ПРОЧИТАТЬ БАЙТ ИЗ ПОРТА ДАННЫХ FDC   *
155
;* Процедура не имеет входных параметров. *
155
;* Процедура не имеет входных параметров. *
156
;* Выходные данные:                       *
156
;* Выходные данные:                       *
157
;* AL - считанный байт.                   *
157
;* AL - считанный байт.                   *
158
;******************************************
158
;******************************************
159
FDCDataInput:
159
FDCDataInput:
160
        push    ECX
160
        push    ECX
161
        push    DX
161
        push    DX
162
; Сбросить переменную состояния контроллера
162
; Сбросить переменную состояния контроллера
163
        mov     [FDC_Status], FDC_Normal
163
        mov     [FDC_Status], FDC_Normal
164
; Проверить готовность контроллера к передаче данных
164
; Проверить готовность контроллера к передаче данных
165
        mov     DX, 3F4h  ;(порт состояния FDC)
165
        mov     DX, 3F4h  ;(порт состояния FDC)
166
        mov     ecx, 0x10000 ;установить счетчик тайм-аута
166
        mov     ecx, 0x10000 ;установить счетчик тайм-аута
167
@@TestRS_1:
167
@@TestRS_1:
168
        in      AL, DX    ;прочитать регистр RS
168
        in      AL, DX    ;прочитать регистр RS
169
        and     AL, 0C0h  ;выдлить разряды 6 и 7
169
        and     AL, 0C0h  ;выдлить разряды 6 и 7
170
        cmp     AL, 0C0h  ;проверить разряды 6 и 7
170
        cmp     AL, 0C0h  ;проверить разряды 6 и 7
171
        je      @@GetByteFromFDC
171
        je      @@GetByteFromFDC
172
        loop    @@TestRS_1
172
        loop    @@TestRS_1
173
; Ошибка тайм-аута
173
; Ошибка тайм-аута
174
;       DEBUGF 1,'K : FDCDataInput: timeout\n'
174
;       DEBUGF 1,'K : FDCDataInput: timeout\n'
175
        mov     [FDC_Status], FDC_TimeOut
175
        mov     [FDC_Status], FDC_TimeOut
176
        jmp     @@End_6
176
        jmp     @@End_6
177
; Ввести байт из порта данных
177
; Ввести байт из порта данных
178
@@GetByteFromFDC:
178
@@GetByteFromFDC:
179
        inc     DX
179
        inc     DX
180
        in      AL, DX
180
        in      AL, DX
181
;       DEBUGF 1,'K : FDCDataInput: %x\n',al
181
;       DEBUGF 1,'K : FDCDataInput: %x\n',al
182
@@End_6:
182
@@End_6:
183
        pop     DX
183
        pop     DX
184
        pop     ECX
184
        pop     ECX
185
        ret
185
        ret
186
 
186
 
187
;*********************************************
187
;*********************************************
188
;* ОБРАБОТЧИК ПРЕРЫВАНИЯ ОТ КОНТРОЛЛЕРА НГМД *
188
;* ОБРАБОТЧИК ПРЕРЫВАНИЯ ОТ КОНТРОЛЛЕРА НГМД *
189
;*********************************************
189
;*********************************************
190
FDCInterrupt:
190
FDCInterrupt:
191
;       dbgstr 'FDCInterrupt'
191
;       dbgstr 'FDCInterrupt'
192
; Установить флаг прерывания
192
; Установить флаг прерывания
193
        mov     [FDD_IntFlag], 1
193
        mov     [FDD_IntFlag], 1
194
        mov     al, 1
194
        mov     al, 1
195
        ret
195
        ret
196
 
196
 
197
;*******************************************
197
;*******************************************
198
;* ОЖИДАНИЕ ПРЕРЫВАНИЯ ОТ КОНТРОЛЛЕРА НГМД *
198
;* ОЖИДАНИЕ ПРЕРЫВАНИЯ ОТ КОНТРОЛЛЕРА НГМД *
199
;*******************************************
199
;*******************************************
200
WaitFDCInterrupt:
200
WaitFDCInterrupt:
201
        pusha
201
        pusha
202
; Сбросить байт состояния операции
202
; Сбросить байт состояния операции
203
        mov     [FDC_Status], FDC_Normal
203
        mov     [FDC_Status], FDC_Normal
204
; Обнулить счетчик тиков
204
; Обнулить счетчик тиков
205
        mov     eax, [timer_ticks]
205
        mov     eax, [timer_ticks]
206
        mov     [TickCounter], eax
206
        mov     [TickCounter], eax
207
; Ожидать установки флага прерывания НГМД
207
; Ожидать установки флага прерывания НГМД
208
@@TestRS_2:
208
@@TestRS_2:
209
        call    change_task
209
        call    change_task
210
        cmp     [FDD_IntFlag], 0
210
        cmp     [FDD_IntFlag], 0
211
        jnz     @@End_7           ;прерывание произошло
211
        jnz     @@End_7           ;прерывание произошло
212
        mov     eax, [timer_ticks]
212
        mov     eax, [timer_ticks]
213
        sub     eax, [TickCounter]
213
        sub     eax, [TickCounter]
214
        cmp     eax, 200;50 ;25   ;5 ;ожидать 5 тиков
214
        cmp     eax, 200;50 ;25   ;5 ;ожидать 5 тиков
215
        jb      @@TestRS_2
215
        jb      @@TestRS_2
216
;        jl      @@TestRS_2
216
;        jl      @@TestRS_2
217
; Ошибка тайм-аута
217
; Ошибка тайм-аута
218
;       dbgstr 'WaitFDCInterrupt: timeout'
218
;       dbgstr 'WaitFDCInterrupt: timeout'
219
        mov     [FDC_Status], FDC_TimeOut
219
        mov     [FDC_Status], FDC_TimeOut
220
@@End_7:
220
@@End_7:
221
        popa
221
        popa
222
        ret
222
        ret
223
 
223
 
224
;*********************************
224
;*********************************
225
;* ВКЛЮЧИТЬ МОТОР ДИСКОВОДА "A:" *
225
;* ВКЛЮЧИТЬ МОТОР ДИСКОВОДА "A:" *
226
;*********************************
226
;*********************************
227
FDDMotorON:
227
FDDMotorON:
228
;       dbgstr 'FDDMotorON'
228
;       dbgstr 'FDDMotorON'
229
        pusha
229
        pusha
230
;        cmp     [fdd_motor_status],1
230
;        cmp     [fdd_motor_status],1
231
;        je      fdd_motor_on
231
;        je      fdd_motor_on
232
        mov     al, [flp_number]
232
        mov     al, [flp_number]
233
        cmp     [fdd_motor_status], al
233
        cmp     [fdd_motor_status], al
234
        je      fdd_motor_on
234
        je      fdd_motor_on
235
; Произвести сброс контроллера НГМД
235
; Произвести сброс контроллера НГМД
236
        mov     DX, 3F2h;порт управления двигателями
236
        mov     DX, 3F2h;порт управления двигателями
237
        mov     AL, 0
237
        mov     AL, 0
238
        out     DX, AL
238
        out     DX, AL
239
; Выбрать и включить мотор дисковода
239
; Выбрать и включить мотор дисковода
240
        cmp     [flp_number], 1
240
        cmp     [flp_number], 1
241
        jne     FDDMotorON_B
241
        jne     FDDMotorON_B
242
;        call    FDDMotorOFF_B
242
;        call    FDDMotorOFF_B
243
        mov     AL, 1Ch   ; Floppy A
243
        mov     AL, 1Ch   ; Floppy A
244
        jmp     FDDMotorON_1
244
        jmp     FDDMotorON_1
245
FDDMotorON_B:
245
FDDMotorON_B:
246
;        call    FDDMotorOFF_A
246
;        call    FDDMotorOFF_A
247
        mov     AL, 2Dh   ; Floppy B
247
        mov     AL, 2Dh   ; Floppy B
248
FDDMotorON_1:
248
FDDMotorON_1:
249
        out     DX, AL
249
        out     DX, AL
250
; Обнулить счетчик тиков
250
; Обнулить счетчик тиков
251
        mov     eax, [timer_ticks]
251
        mov     eax, [timer_ticks]
252
        mov     [TickCounter], eax
252
        mov     [TickCounter], eax
253
; Ожидать 0,5 с
253
; Ожидать 0,5 с
254
@@dT:
254
@@dT:
255
        call    change_task
255
        call    change_task
256
        mov     eax, [timer_ticks]
256
        mov     eax, [timer_ticks]
257
        sub     eax, [TickCounter]
257
        sub     eax, [TickCounter]
258
        cmp     eax, 50 ;10
258
        cmp     eax, 50 ;10
259
        jb      @@dT
259
        jb      @@dT
260
; Read results of RESET command
260
; Read results of RESET command
261
        push    4
261
        push    4
262
;       DEBUGF 1,'K : floppy reset results:'
262
;       DEBUGF 1,'K : floppy reset results:'
263
@@:
263
@@:
264
        mov     al, 8
264
        mov     al, 8
265
        call    FDCDataOutput
265
        call    FDCDataOutput
266
        call    FDCDataInput
266
        call    FDCDataInput
267
;       DEBUGF 1,' %x',al
267
;       DEBUGF 1,' %x',al
268
        call    FDCDataInput
268
        call    FDCDataInput
269
;       DEBUGF 1,' %x',al
269
;       DEBUGF 1,' %x',al
270
        dec     dword [esp]
270
        dec     dword [esp]
271
        jnz     @b
271
        jnz     @b
272
;       DEBUGF 1,'\n'
272
;       DEBUGF 1,'\n'
273
        pop     eax
273
        pop     eax
274
        cmp     [flp_number], 1
274
        cmp     [flp_number], 1
275
        jne     fdd_motor_on_B
275
        jne     fdd_motor_on_B
276
        mov     [fdd_motor_status], 1
276
        mov     [fdd_motor_status], 1
277
        jmp     fdd_motor_on
277
        jmp     fdd_motor_on
278
fdd_motor_on_B:
278
fdd_motor_on_B:
279
        mov     [fdd_motor_status], 2
279
        mov     [fdd_motor_status], 2
280
fdd_motor_on:
280
fdd_motor_on:
281
        call    save_timer_fdd_motor
281
        call    save_timer_fdd_motor
282
        popa
282
        popa
283
        ret
283
        ret
284
 
284
 
285
;*****************************************
285
;*****************************************
286
;*  СОХРАНЕНИЕ УКАЗАТЕЛЯ ВРЕМЕНИ         *
286
;*  СОХРАНЕНИЕ УКАЗАТЕЛЯ ВРЕМЕНИ         *
287
;*****************************************
287
;*****************************************
288
save_timer_fdd_motor:
288
save_timer_fdd_motor:
289
        mov     eax, [timer_ticks]
289
        mov     eax, [timer_ticks]
290
        mov     [timer_fdd_motor], eax
290
        mov     [timer_fdd_motor], eax
291
        ret
291
        ret
292
 
292
 
293
;*****************************************
293
;*****************************************
294
;*  ПРОВЕРКА ЗАДЕРЖКИ ВЫКЛЮЧЕНИЯ МОТОРА  *
294
;*  ПРОВЕРКА ЗАДЕРЖКИ ВЫКЛЮЧЕНИЯ МОТОРА  *
295
;*****************************************
295
;*****************************************
296
proc check_fdd_motor_status_has_work?
296
proc check_fdd_motor_status_has_work?
297
        cmp     [fdd_motor_status], 0
297
        cmp     [fdd_motor_status], 0
298
        jz      .no
298
        jz      .no
299
        mov     eax, [timer_ticks]
299
        mov     eax, [timer_ticks]
300
        sub     eax, [timer_fdd_motor]
300
        sub     eax, [timer_fdd_motor]
301
        cmp     eax, 500
301
        cmp     eax, 500
302
        jb      .no
302
        jb      .no
303
.yes:
303
.yes:
304
        xor     eax, eax
304
        xor     eax, eax
305
        inc     eax
305
        inc     eax
306
        ret
306
        ret
307
.no:
307
.no:
308
        xor     eax, eax
308
        xor     eax, eax
309
        ret
309
        ret
310
endp
310
endp
311
 
311
 
312
align 4
312
align 4
313
check_fdd_motor_status:
313
check_fdd_motor_status:
314
        cmp     [fdd_motor_status], 0
314
        cmp     [fdd_motor_status], 0
315
        je      end_check_fdd_motor_status_1
315
        je      end_check_fdd_motor_status_1
316
        mov     eax, [timer_ticks]
316
        mov     eax, [timer_ticks]
317
        sub     eax, [timer_fdd_motor]
317
        sub     eax, [timer_fdd_motor]
318
        cmp     eax, 500
318
        cmp     eax, 500
319
        jb      end_check_fdd_motor_status
319
        jb      end_check_fdd_motor_status
320
        call    FDDMotorOFF
320
        call    FDDMotorOFF
321
        mov     [fdd_motor_status], 0
321
        mov     [fdd_motor_status], 0
322
end_check_fdd_motor_status_1:
322
end_check_fdd_motor_status_1:
323
end_check_fdd_motor_status:
323
end_check_fdd_motor_status:
324
        ret
324
        ret
325
 
325
 
326
;**********************************
326
;**********************************
327
;* ВЫКЛЮЧИТЬ МОТОР ДИСКОВОДА      *
327
;* ВЫКЛЮЧИТЬ МОТОР ДИСКОВОДА      *
328
;**********************************
328
;**********************************
329
FDDMotorOFF:
329
FDDMotorOFF:
330
;       dbgstr 'FDDMotorOFF'
330
;       dbgstr 'FDDMotorOFF'
331
        push    AX
331
        push    AX
332
        push    DX
332
        push    DX
333
        cmp     [flp_number], 1
333
        cmp     [flp_number], 1
334
        jne     FDDMotorOFF_1
334
        jne     FDDMotorOFF_1
335
        call    FDDMotorOFF_A
335
        call    FDDMotorOFF_A
336
        jmp     FDDMotorOFF_2
336
        jmp     FDDMotorOFF_2
337
FDDMotorOFF_1:
337
FDDMotorOFF_1:
338
        call    FDDMotorOFF_B
338
        call    FDDMotorOFF_B
339
FDDMotorOFF_2:
339
FDDMotorOFF_2:
340
        pop     DX
340
        pop     DX
341
        pop     AX
341
        pop     AX
342
        ; сброс флагов кеширования в связи с устареванием информации
342
        ; сброс флагов кеширования в связи с устареванием информации
343
        or      [floppy_media_flags+0], FLOPPY_MEDIA_NEED_RESCAN
343
        or      [floppy_media_flags+0], FLOPPY_MEDIA_NEED_RESCAN
344
        or      [floppy_media_flags+1], FLOPPY_MEDIA_NEED_RESCAN
344
        or      [floppy_media_flags+1], FLOPPY_MEDIA_NEED_RESCAN
345
        ret
345
        ret
346
 
346
 
347
FDDMotorOFF_A:
347
FDDMotorOFF_A:
348
        mov     DX, 3F2h;порт управления двигателями
348
        mov     DX, 3F2h;порт управления двигателями
349
        mov     AL, 0Ch ; Floppy A
349
        mov     AL, 0Ch ; Floppy A
350
        out     DX, AL
350
        out     DX, AL
351
        ret
351
        ret
352
 
352
 
353
FDDMotorOFF_B:
353
FDDMotorOFF_B:
354
        mov     DX, 3F2h;порт управления двигателями
354
        mov     DX, 3F2h;порт управления двигателями
355
        mov     AL, 5h ; Floppy B
355
        mov     AL, 5h ; Floppy B
356
        out     DX, AL
356
        out     DX, AL
357
        ret
357
        ret
358
 
358
 
359
;*******************************
359
;*******************************
360
;* РЕКАЛИБРОВКА ДИСКОВОДА "A:" *
360
;* РЕКАЛИБРОВКА ДИСКОВОДА "A:" *
361
;*******************************
361
;*******************************
362
RecalibrateFDD:
362
RecalibrateFDD:
363
;       dbgstr 'RecalibrateFDD'
363
;       dbgstr 'RecalibrateFDD'
364
        pusha
364
        pusha
365
        call    save_timer_fdd_motor
365
        call    save_timer_fdd_motor
366
; Сбросить флаг прерывания
366
; Сбросить флаг прерывания
367
        mov     [FDD_IntFlag], 0
367
        mov     [FDD_IntFlag], 0
368
; Подать команду "Рекалибровка"
368
; Подать команду "Рекалибровка"
369
        mov     AL, 07h
369
        mov     AL, 07h
370
        call    FDCDataOutput
370
        call    FDCDataOutput
371
        mov     AL, 00h
371
        mov     AL, 00h
372
        call    FDCDataOutput
372
        call    FDCDataOutput
373
; Ожидать завершения операции
373
; Ожидать завершения операции
374
        call    WaitFDCInterrupt
374
        call    WaitFDCInterrupt
375
        cmp     [FDC_Status], 0
375
        cmp     [FDC_Status], 0
376
        jne     .fail
376
        jne     .fail
377
; Read results of RECALIBRATE command
377
; Read results of RECALIBRATE command
378
;       DEBUGF 1,'K : floppy recalibrate results:'
378
;       DEBUGF 1,'K : floppy recalibrate results:'
379
        mov     al, 8
379
        mov     al, 8
380
        call    FDCDataOutput
380
        call    FDCDataOutput
381
        call    FDCDataInput
381
        call    FDCDataInput
-
 
382
        push    eax
382
;       DEBUGF 1,' %x',al
383
;       DEBUGF 1,' %x',al
383
        call    FDCDataInput
384
        call    FDCDataInput
384
;       DEBUGF 1,' %x',al
385
;       DEBUGF 1,' %x',al
385
;       DEBUGF 1,'\n'
386
;       DEBUGF 1,'\n'
-
 
387
        pop     eax
-
 
388
        test    al, 0xC0
-
 
389
        jz      @f
-
 
390
        mov     [FDC_Status], FDC_DiskNotFound
-
 
391
@@:
386
.fail:
392
.fail:
387
        call    save_timer_fdd_motor
393
        call    save_timer_fdd_motor
388
        popa
394
        popa
389
        ret
395
        ret
390
 
396
 
391
;*****************************************************
397
;*****************************************************
392
;*                    ПОИСК ДОРОЖКИ                  *
398
;*                    ПОИСК ДОРОЖКИ                  *
393
;* Параметры передаются через глобальные переменные: *
399
;* Параметры передаются через глобальные переменные: *
394
;* FDD_Track - номер дорожки (0-79);                 *
400
;* FDD_Track - номер дорожки (0-79);                 *
395
;* FDD_Head - номер головки (0-1).                   *
401
;* FDD_Head - номер головки (0-1).                   *
396
;* Результат операции заносится в FDC_Status.        *
402
;* Результат операции заносится в FDC_Status.        *
397
;*****************************************************
403
;*****************************************************
398
SeekTrack:
404
SeekTrack:
399
;       dbgstr 'SeekTrack'
405
;       dbgstr 'SeekTrack'
400
        pusha
406
        pusha
401
        call    save_timer_fdd_motor
407
        call    save_timer_fdd_motor
402
; Сбросить флаг прерывания
408
; Сбросить флаг прерывания
403
        mov     [FDD_IntFlag], 0
409
        mov     [FDD_IntFlag], 0
404
; Подать команду "Поиск"
410
; Подать команду "Поиск"
405
        mov     AL, 0Fh
411
        mov     AL, 0Fh
406
        call    FDCDataOutput
412
        call    FDCDataOutput
407
        ; Передать байт номера головки/накопител
413
        ; Передать байт номера головки/накопител
408
        mov     AL, [FDD_Head]
414
        mov     AL, [FDD_Head]
409
        shl     AL, 2
415
        shl     AL, 2
410
        call    FDCDataOutput
416
        call    FDCDataOutput
411
        ; Передать байт номера дорожки
417
        ; Передать байт номера дорожки
412
        mov     AL, [FDD_Track]
418
        mov     AL, [FDD_Track]
413
        call    FDCDataOutput
419
        call    FDCDataOutput
414
; Ожидать завершения операции
420
; Ожидать завершения операции
415
        call    WaitFDCInterrupt
421
        call    WaitFDCInterrupt
416
        cmp     [FDC_Status], FDC_Normal
422
        cmp     [FDC_Status], FDC_Normal
417
        jne     @@Exit
423
        jne     @@Exit
418
; Сохранить результат поиска
424
; Сохранить результат поиска
419
        mov     AL, 08h
425
        mov     AL, 08h
420
        call    FDCDataOutput
426
        call    FDCDataOutput
421
        call    FDCDataInput
427
        call    FDCDataInput
422
        mov     [FDC_ST0], AL
428
        mov     [FDC_ST0], AL
423
        call    FDCDataInput
429
        call    FDCDataInput
424
        mov     [FDC_C], AL
430
        mov     [FDC_C], AL
425
; Проверить результат поиска
431
; Проверить результат поиска
426
        ; Поиск завершен?
432
        ; Поиск завершен?
427
        test    [FDC_ST0], 100000b
433
        test    [FDC_ST0], 100000b
428
        je      @@Err
434
        je      @@Err
429
        ; Заданный трек найден?
435
        ; Заданный трек найден?
430
        mov     AL, [FDC_C]
436
        mov     AL, [FDC_C]
431
        cmp     AL, [FDD_Track]
437
        cmp     AL, [FDD_Track]
432
        jne     @@Err
438
        jne     @@Err
433
        ; Номер головки совпадает с заданным?
439
        ; Номер головки совпадает с заданным?
434
; The H bit (Head Address) in ST0 will always return a "0" (c) 82077AA datasheet,
440
; The H bit (Head Address) in ST0 will always return a "0" (c) 82077AA datasheet,
435
; description of SEEK command. So we can not verify the proper head.
441
; description of SEEK command. So we can not verify the proper head.
436
;        mov     AL, [FDC_ST0]
442
;        mov     AL, [FDC_ST0]
437
;        and     AL, 100b
443
;        and     AL, 100b
438
;        shr     AL, 2
444
;        shr     AL, 2
439
;        cmp     AL, [FDD_Head]
445
;        cmp     AL, [FDD_Head]
440
;        jne     @@Err
446
;        jne     @@Err
441
        ; Операция завершена успешно
447
        ; Операция завершена успешно
442
;        dbgstr 'SeekTrack: FDC_Normal'
448
;        dbgstr 'SeekTrack: FDC_Normal'
443
        mov     [FDC_Status], FDC_Normal
449
        mov     [FDC_Status], FDC_Normal
444
        jmp     @@Exit
450
        jmp     @@Exit
445
@@Err:  ; Трек не найден
451
@@Err:  ; Трек не найден
446
;       dbgstr 'SeekTrack: FDC_TrackNotFound'
452
;       dbgstr 'SeekTrack: FDC_TrackNotFound'
447
        mov     [FDC_Status], FDC_TrackNotFound
453
        mov     [FDC_Status], FDC_TrackNotFound
448
@@Exit:
454
@@Exit:
449
        call    save_timer_fdd_motor
455
        call    save_timer_fdd_motor
450
        popa
456
        popa
451
        ret
457
        ret
452
 
458
 
453
;*******************************************************
459
;*******************************************************
454
;*               ЧТЕНИЕ СЕКТОРА ДАННЫХ                 *
460
;*               ЧТЕНИЕ СЕКТОРА ДАННЫХ                 *
455
;* Параметры передаются через глобальные переменные:   *
461
;* Параметры передаются через глобальные переменные:   *
456
;* FDD_Track - номер дорожки (0-79);                   *
462
;* FDD_Track - номер дорожки (0-79);                   *
457
;* FDD_Head - номер головки (0-1);                     *
463
;* FDD_Head - номер головки (0-1);                     *
458
;* FDD_Sector - номер сектора (1-18).                  *
464
;* FDD_Sector - номер сектора (1-18).                  *
459
;* Результат операции заносится в FDC_Status.          *
465
;* Результат операции заносится в FDC_Status.          *
460
;* В случае успешного выполнения операции чтения       *
466
;* В случае успешного выполнения операции чтения       *
461
;* содержимое сектора будет занесено в FDD_DataBuffer. *
467
;* содержимое сектора будет занесено в FDD_DataBuffer. *
462
;*******************************************************
468
;*******************************************************
463
ReadSector:
469
ReadSector:
464
;       dbgstr 'ReadSector'
470
;       dbgstr 'ReadSector'
465
        pushad
471
        pushad
466
        call    save_timer_fdd_motor
472
        call    save_timer_fdd_motor
467
; Сбросить флаг прерывания
473
; Сбросить флаг прерывания
468
        mov     [FDD_IntFlag], 0
474
        mov     [FDD_IntFlag], 0
469
; Установить скорость передачи 500 Кбайт/с
475
; Установить скорость передачи 500 Кбайт/с
470
        mov     AX, 0
476
        mov     AX, 0
471
        mov     DX, 03F7h
477
        mov     DX, 03F7h
472
        out     DX, AL
478
        out     DX, AL
473
; Инициализировать канал прямого доступа к памяти
479
; Инициализировать канал прямого доступа к памяти
474
        mov     [dmamode], 0x46
480
        mov     [dmamode], 0x46
475
        call    Init_FDC_DMA
481
        call    Init_FDC_DMA
476
; Подать команду "Чтение данных"
482
; Подать команду "Чтение данных"
477
        mov     AL, 0E6h ;чтение в мультитрековом режиме
483
        mov     AL, 0E6h ;чтение в мультитрековом режиме
478
        call    FDCDataOutput
484
        call    FDCDataOutput
479
        mov     AL, [FDD_Head]
485
        mov     AL, [FDD_Head]
480
        shl     AL, 2
486
        shl     AL, 2
481
        call    FDCDataOutput
487
        call    FDCDataOutput
482
        mov     AL, [FDD_Track]
488
        mov     AL, [FDD_Track]
483
        call    FDCDataOutput
489
        call    FDCDataOutput
484
        mov     AL, [FDD_Head]
490
        mov     AL, [FDD_Head]
485
        call    FDCDataOutput
491
        call    FDCDataOutput
486
        mov     AL, [FDD_Sector]
492
        mov     AL, [FDD_Sector]
487
        call    FDCDataOutput
493
        call    FDCDataOutput
488
        mov     AL, 2   ;код размера сектора (512 байт)
494
        mov     AL, 2   ;код размера сектора (512 байт)
489
        call    FDCDataOutput
495
        call    FDCDataOutput
490
        mov     AL, 18 ;+1; 3Fh  ;число секторов на дорожке
496
        mov     AL, 18 ;+1; 3Fh  ;число секторов на дорожке
491
        call    FDCDataOutput
497
        call    FDCDataOutput
492
        mov     AL, 1Bh ;значение GPL
498
        mov     AL, 1Bh ;значение GPL
493
        call    FDCDataOutput
499
        call    FDCDataOutput
494
        mov     AL, 0FFh;значение DTL
500
        mov     AL, 0FFh;значение DTL
495
        call    FDCDataOutput
501
        call    FDCDataOutput
496
; Ожидаем прерывание по завершении операции
502
; Ожидаем прерывание по завершении операции
497
        call    WaitFDCInterrupt
503
        call    WaitFDCInterrupt
498
        cmp     [FDC_Status], FDC_Normal
504
        cmp     [FDC_Status], FDC_Normal
499
        jne     @@Exit_1
505
        jne     @@Exit_1
500
; Считываем статус завершения операции
506
; Считываем статус завершения операции
501
        call    GetStatusInfo
507
        call    GetStatusInfo
502
        test    [FDC_ST0], 11011000b
508
        test    [FDC_ST0], 11011000b
503
        jnz     @@Err_1
509
        jnz     @@Err_1
504
;        dbgstr 'ReadSector: FDC_Normal'
510
;        dbgstr 'ReadSector: FDC_Normal'
505
        mov     [FDC_Status], FDC_Normal
511
        mov     [FDC_Status], FDC_Normal
506
        jmp     @@Exit_1
512
        jmp     @@Exit_1
507
@@Err_1:
513
@@Err_1:
508
;       dbgstr 'ReadSector: FDC_SectorNotFound'
514
;       dbgstr 'ReadSector: FDC_SectorNotFound'
509
        mov     [FDC_Status], FDC_SectorNotFound
515
        mov     [FDC_Status], FDC_SectorNotFound
510
@@Exit_1:
516
@@Exit_1:
511
        call    save_timer_fdd_motor
517
        call    save_timer_fdd_motor
512
        popad
518
        popad
513
        ret
519
        ret
514
 
520
 
515
;*******************************************************
521
;*******************************************************
516
;*   ЧТЕНИЕ СЕКТОРА (С ПОВТОРЕНИЕМ ОПЕРАЦИИ ПРИ СБОЕ)  *
522
;*   ЧТЕНИЕ СЕКТОРА (С ПОВТОРЕНИЕМ ОПЕРАЦИИ ПРИ СБОЕ)  *
517
;* Параметры передаются через глобальные переменные:   *
523
;* Параметры передаются через глобальные переменные:   *
518
;* FDD_Track - номер дорожки (0-79);                   *
524
;* FDD_Track - номер дорожки (0-79);                   *
519
;* FDD_Head - номер головки (0-1);                     *
525
;* FDD_Head - номер головки (0-1);                     *
520
;* FDD_Sector - номер сектора (1-18).                  *
526
;* FDD_Sector - номер сектора (1-18).                  *
521
;* Результат операции заносится в FDC_Status.          *
527
;* Результат операции заносится в FDC_Status.          *
522
;* В случае успешного выполнения операции чтения       *
528
;* В случае успешного выполнения операции чтения       *
523
;* содержимое сектора будет занесено в FDD_DataBuffer. *
529
;* содержимое сектора будет занесено в FDD_DataBuffer. *
524
;*******************************************************
530
;*******************************************************
525
ReadSectWithRetr:
531
ReadSectWithRetr:
526
        pusha
532
        pusha
527
; Обнулить счетчик повторения операции рекалибровки
533
; Обнулить счетчик повторения операции рекалибровки
528
        mov     [RecalRepCounter], 0
534
        mov     [RecalRepCounter], 0
529
@@TryAgain:
535
@@TryAgain:
530
; Обнулить счетчик повторения операции чтени
536
; Обнулить счетчик повторения операции чтени
531
        mov     [ReadRepCounter], 0
537
        mov     [ReadRepCounter], 0
532
@@ReadSector_1:
538
@@ReadSector_1:
533
        call    ReadSector
539
        call    ReadSector
534
        cmp     [FDC_Status], 0
540
        cmp     [FDC_Status], 0
535
        je      @@Exit_2
541
        je      @@Exit_2
536
        cmp     [FDC_Status], 1
542
        cmp     [FDC_Status], 1
537
        je      @@Err_3
543
        je      @@Err_3
538
        ; Троекратное повторение чтени
544
        ; Троекратное повторение чтени
539
        inc     [ReadRepCounter]
545
        inc     [ReadRepCounter]
540
        cmp     [ReadRepCounter], 3
546
        cmp     [ReadRepCounter], 3
541
        jb      @@ReadSector_1
547
        jb      @@ReadSector_1
542
        ; Троекратное повторение рекалибровки
548
        ; Троекратное повторение рекалибровки
543
        call    RecalibrateFDD
549
        call    RecalibrateFDD
544
        call    SeekTrack
550
        call    SeekTrack
545
        inc     [RecalRepCounter]
551
        inc     [RecalRepCounter]
546
        cmp     [RecalRepCounter], 3
552
        cmp     [RecalRepCounter], 3
547
        jb      @@TryAgain
553
        jb      @@TryAgain
548
@@Exit_2:
554
@@Exit_2:
549
        popa
555
        popa
550
        ret
556
        ret
551
@@Err_3:
557
@@Err_3:
552
        popa
558
        popa
553
        ret
559
        ret
554
 
560
 
555
;*******************************************************
561
;*******************************************************
556
;*               ЗАПИСЬ СЕКТОРА ДАННЫХ                 *
562
;*               ЗАПИСЬ СЕКТОРА ДАННЫХ                 *
557
;* Параметры передаются через глобальные переменные:   *
563
;* Параметры передаются через глобальные переменные:   *
558
;* FDD_Track - номер дорожки (0-79);                   *
564
;* FDD_Track - номер дорожки (0-79);                   *
559
;* FDD_Head - номер головки (0-1);                     *
565
;* FDD_Head - номер головки (0-1);                     *
560
;* FDD_Sector - номер сектора (1-18).                  *
566
;* FDD_Sector - номер сектора (1-18).                  *
561
;* Результат операции заносится в FDC_Status.          *
567
;* Результат операции заносится в FDC_Status.          *
562
;* В случае успешного выполнения операции записи       *
568
;* В случае успешного выполнения операции записи       *
563
;* содержимое FDD_DataBuffer будет занесено в сектор.  *
569
;* содержимое FDD_DataBuffer будет занесено в сектор.  *
564
;*******************************************************
570
;*******************************************************
565
WriteSector:
571
WriteSector:
566
;       dbgstr 'WriteSector'
572
;       dbgstr 'WriteSector'
567
        pushad
573
        pushad
568
        call    save_timer_fdd_motor
574
        call    save_timer_fdd_motor
569
; Сбросить флаг прерывания
575
; Сбросить флаг прерывания
570
        mov     [FDD_IntFlag], 0
576
        mov     [FDD_IntFlag], 0
571
; Установить скорость передачи 500 Кбайт/с
577
; Установить скорость передачи 500 Кбайт/с
572
        mov     AX, 0
578
        mov     AX, 0
573
        mov     DX, 03F7h
579
        mov     DX, 03F7h
574
        out     DX, AL
580
        out     DX, AL
575
; Инициализировать канал прямого доступа к памяти
581
; Инициализировать канал прямого доступа к памяти
576
        mov     [dmamode], 0x4A
582
        mov     [dmamode], 0x4A
577
        call    Init_FDC_DMA
583
        call    Init_FDC_DMA
578
; Подать команду "Запись данных"
584
; Подать команду "Запись данных"
579
        mov     AL, 0xC5 ;0x45  ;запись в мультитрековом режиме
585
        mov     AL, 0xC5 ;0x45  ;запись в мультитрековом режиме
580
        call    FDCDataOutput
586
        call    FDCDataOutput
581
        mov     AL, [FDD_Head]
587
        mov     AL, [FDD_Head]
582
        shl     AL, 2
588
        shl     AL, 2
583
        call    FDCDataOutput
589
        call    FDCDataOutput
584
        mov     AL, [FDD_Track]
590
        mov     AL, [FDD_Track]
585
        call    FDCDataOutput
591
        call    FDCDataOutput
586
        mov     AL, [FDD_Head]
592
        mov     AL, [FDD_Head]
587
        call    FDCDataOutput
593
        call    FDCDataOutput
588
        mov     AL, [FDD_Sector]
594
        mov     AL, [FDD_Sector]
589
        call    FDCDataOutput
595
        call    FDCDataOutput
590
        mov     AL, 2   ;код размера сектора (512 байт)
596
        mov     AL, 2   ;код размера сектора (512 байт)
591
        call    FDCDataOutput
597
        call    FDCDataOutput
592
        mov     AL, 18; 3Fh  ;число секторов на дорожке
598
        mov     AL, 18; 3Fh  ;число секторов на дорожке
593
        call    FDCDataOutput
599
        call    FDCDataOutput
594
        mov     AL, 1Bh ;значение GPL
600
        mov     AL, 1Bh ;значение GPL
595
        call    FDCDataOutput
601
        call    FDCDataOutput
596
        mov     AL, 0FFh;значение DTL
602
        mov     AL, 0FFh;значение DTL
597
        call    FDCDataOutput
603
        call    FDCDataOutput
598
; Ожидаем прерывание по завершении операции
604
; Ожидаем прерывание по завершении операции
599
        call    WaitFDCInterrupt
605
        call    WaitFDCInterrupt
600
        cmp     [FDC_Status], FDC_Normal
606
        cmp     [FDC_Status], FDC_Normal
601
        jne     @@Exit_3
607
        jne     @@Exit_3
602
; Считываем статус завершения операции
608
; Считываем статус завершения операции
603
        call    GetStatusInfo
609
        call    GetStatusInfo
604
        test    [FDC_ST0], 11000000b ;11011000b
610
        test    [FDC_ST0], 11000000b ;11011000b
605
        jnz     @@Err_2
611
        jnz     @@Err_2
606
        mov     [FDC_Status], FDC_Normal
612
        mov     [FDC_Status], FDC_Normal
607
        jmp     @@Exit_3
613
        jmp     @@Exit_3
608
@@Err_2:
614
@@Err_2:
609
        mov     [FDC_Status], FDC_SectorNotFound
615
        mov     [FDC_Status], FDC_SectorNotFound
610
@@Exit_3:
616
@@Exit_3:
611
        call    save_timer_fdd_motor
617
        call    save_timer_fdd_motor
612
        popad
618
        popad
613
        ret
619
        ret
614
 
620
 
615
;*******************************************************
621
;*******************************************************
616
;*   ЗАПИСЬ СЕКТОРА (С ПОВТОРЕНИЕМ ОПЕРАЦИИ ПРИ СБОЕ)  *
622
;*   ЗАПИСЬ СЕКТОРА (С ПОВТОРЕНИЕМ ОПЕРАЦИИ ПРИ СБОЕ)  *
617
;* Параметры передаются через глобальные переменные:   *
623
;* Параметры передаются через глобальные переменные:   *
618
;* FDD_Track - номер дорожки (0-79);                   *
624
;* FDD_Track - номер дорожки (0-79);                   *
619
;* FDD_Head - номер головки (0-1);                     *
625
;* FDD_Head - номер головки (0-1);                     *
620
;* FDD_Sector - номер сектора (1-18).                  *
626
;* FDD_Sector - номер сектора (1-18).                  *
621
;* Результат операции заносится в FDC_Status.          *
627
;* Результат операции заносится в FDC_Status.          *
622
;* В случае успешного выполнения операции записи       *
628
;* В случае успешного выполнения операции записи       *
623
;* содержимое FDD_DataBuffer будет занесено в сектор.  *
629
;* содержимое FDD_DataBuffer будет занесено в сектор.  *
624
;*******************************************************
630
;*******************************************************
625
WriteSectWithRetr:
631
WriteSectWithRetr:
626
        pusha
632
        pusha
627
; Обнулить счетчик повторения операции рекалибровки
633
; Обнулить счетчик повторения операции рекалибровки
628
        mov     [RecalRepCounter], 0
634
        mov     [RecalRepCounter], 0
629
@@TryAgain_1:
635
@@TryAgain_1:
630
; Обнулить счетчик повторения операции чтени
636
; Обнулить счетчик повторения операции чтени
631
        mov     [ReadRepCounter], 0
637
        mov     [ReadRepCounter], 0
632
@@WriteSector_1:
638
@@WriteSector_1:
633
        call    WriteSector
639
        call    WriteSector
634
        cmp     [FDC_Status], 0
640
        cmp     [FDC_Status], 0
635
        je      @@Exit_4
641
        je      @@Exit_4
636
        cmp     [FDC_Status], 1
642
        cmp     [FDC_Status], 1
637
        je      @@Err_4
643
        je      @@Err_4
638
        ; Троекратное повторение чтени
644
        ; Троекратное повторение чтени
639
        inc     [ReadRepCounter]
645
        inc     [ReadRepCounter]
640
        cmp     [ReadRepCounter], 3
646
        cmp     [ReadRepCounter], 3
641
        jb      @@WriteSector_1
647
        jb      @@WriteSector_1
642
        ; Троекратное повторение рекалибровки
648
        ; Троекратное повторение рекалибровки
643
        call    RecalibrateFDD
649
        call    RecalibrateFDD
644
        call    SeekTrack
650
        call    SeekTrack
645
        inc     [RecalRepCounter]
651
        inc     [RecalRepCounter]
646
        cmp     [RecalRepCounter], 3
652
        cmp     [RecalRepCounter], 3
647
        jb      @@TryAgain_1
653
        jb      @@TryAgain_1
648
@@Exit_4:
654
@@Exit_4:
649
        popa
655
        popa
650
        ret
656
        ret
651
@@Err_4:
657
@@Err_4:
652
        popa
658
        popa
653
        ret
659
        ret
654
 
660
 
655
;*********************************************
661
;*********************************************
656
;* ПОЛУЧИТЬ ИНФОРМАЦИЮ О РЕЗУЛЬТАТЕ ОПЕРАЦИИ *
662
;* ПОЛУЧИТЬ ИНФОРМАЦИЮ О РЕЗУЛЬТАТЕ ОПЕРАЦИИ *
657
;*********************************************
663
;*********************************************
658
GetStatusInfo:
664
GetStatusInfo:
659
        push    AX
665
        push    AX
660
        call    FDCDataInput
666
        call    FDCDataInput
661
        mov     [FDC_ST0], AL
667
        mov     [FDC_ST0], AL
662
        call    FDCDataInput
668
        call    FDCDataInput
663
        mov     [FDC_ST1], AL
669
        mov     [FDC_ST1], AL
664
        call    FDCDataInput
670
        call    FDCDataInput
665
        mov     [FDC_ST2], AL
671
        mov     [FDC_ST2], AL
666
        call    FDCDataInput
672
        call    FDCDataInput
667
        mov     [FDC_C], AL
673
        mov     [FDC_C], AL
668
        call    FDCDataInput
674
        call    FDCDataInput
669
        mov     [FDC_H], AL
675
        mov     [FDC_H], AL
670
        call    FDCDataInput
676
        call    FDCDataInput
671
        mov     [FDC_R], AL
677
        mov     [FDC_R], AL
672
        call    FDCDataInput
678
        call    FDCDataInput
673
        mov     [FDC_N], AL
679
        mov     [FDC_N], AL
674
        pop     AX
680
        pop     AX
675
        ret
681
        ret
676
 
682
 
677
; Interface for disk subsystem.
683
; Interface for disk subsystem.
678
; Assume fixed capacity for 1.44M.
684
; Assume fixed capacity for 1.44M.
679
FLOPPY_CAPACITY = 2880  ; in sectors
685
FLOPPY_CAPACITY = 2880  ; in sectors
680
 
686
 
681
iglobal
687
iglobal
682
align 4
688
align 4
683
floppy_functions:
689
floppy_functions:
684
        dd      .size
690
        dd      .size
685
        dd      0       ; no close() function
691
        dd      0       ; no close() function
686
        dd      0       ; no closemedia() function
692
        dd      0       ; no closemedia() function
687
        dd      floppy_querymedia
693
        dd      floppy_querymedia
688
        dd      floppy_read
694
        dd      floppy_read
689
        dd      floppy_write
695
        dd      floppy_write
690
        dd      0       ; no flush() function
696
        dd      0       ; no flush() function
691
        dd      0       ; no adjust_cache_size() function
697
        dd      0       ; no adjust_cache_size() function
692
.size = $ - floppy_functions
698
.size = $ - floppy_functions
693
endg
699
endg
694
 
700
 
695
uglobal
701
uglobal
696
floppy_media_flags      rb      2
702
floppy_media_flags      rb      2
697
n_sector    dd 0  ; temporary save for sector value
703
n_sector    dd 0  ; temporary save for sector value
698
flp_number  db 0  ; 1- Floppy A, 2-Floppy B
704
flp_number  db 0  ; 1- Floppy A, 2-Floppy B
699
old_track   db 0  ; old value track
705
old_track   db 0  ; old value track
700
flp_label   rb 15*2 ; Label and ID of inserted floppy disk
706
flp_label   rb 15*2 ; Label and ID of inserted floppy disk
701
align 4
707
align 4
702
; Hardware does not allow to work with two floppies in parallel,
708
; Hardware does not allow to work with two floppies in parallel,
703
; so there is one mutex guarding access to any floppy.
709
; so there is one mutex guarding access to any floppy.
704
floppy_mutex    MUTEX
710
floppy_mutex    MUTEX
705
endg
711
endg
706
; Meaning of bits in floppy_media_flags
712
; Meaning of bits in floppy_media_flags
707
FLOPPY_MEDIA_PRESENT = 1        ; media was present when last asked
713
FLOPPY_MEDIA_PRESENT = 1        ; media was present when last asked
708
FLOPPY_MEDIA_NEED_RESCAN = 2    ; media was possibly changed, need to rescan
714
FLOPPY_MEDIA_NEED_RESCAN = 2    ; media was possibly changed, need to rescan
709
FLOPPY_MEDIA_LABEL_CHANGED = 4  ; temporary state
715
FLOPPY_MEDIA_LABEL_CHANGED = 4  ; temporary state
710
 
716
 
711
iglobal
717
iglobal
712
floppy1_name    db      'fd',0
718
floppy1_name    db      'fd',0
713
floppy2_name    db      'fd2',0
719
floppy2_name    db      'fd2',0
714
endg
720
endg
715
 
721
 
716
; This function is called in boot process.
722
; This function is called in boot process.
717
; It creates filesystems /fd and/or /fd2, if the system has one/two floppy drives.
723
; It creates filesystems /fd and/or /fd2, if the system has one/two floppy drives.
718
proc floppy_init
724
proc floppy_init
719
        mov     ecx, floppy_mutex
725
        mov     ecx, floppy_mutex
720
        call    mutex_init
726
        call    mutex_init
721
; First floppy is present if [DRIVE_DATA] and 0xF0 is nonzero.
727
; First floppy is present if [DRIVE_DATA] and 0xF0 is nonzero.
722
        test    byte [DRIVE_DATA], 0xF0
728
        test    byte [DRIVE_DATA], 0xF0
723
        jz      .no1
729
        jz      .no1
724
        stdcall disk_add, floppy_functions, floppy1_name, 1, DISK_NO_INSERT_NOTIFICATION
730
        stdcall disk_add, floppy_functions, floppy1_name, 1, DISK_NO_INSERT_NOTIFICATION
725
.no1:
731
.no1:
726
; Second floppy is present if [DRIVE_DATA] and 0x0F is nonzero.
732
; Second floppy is present if [DRIVE_DATA] and 0x0F is nonzero.
727
        test    byte [DRIVE_DATA], 0x0F
733
        test    byte [DRIVE_DATA], 0x0F
728
        jz      .no2
734
        jz      .no2
729
        stdcall disk_add, floppy_functions, floppy2_name, 2, DISK_NO_INSERT_NOTIFICATION
735
        stdcall disk_add, floppy_functions, floppy2_name, 2, DISK_NO_INSERT_NOTIFICATION
730
.no2:
736
.no2:
731
        ret
737
        ret
732
endp
738
endp
733
 
739
 
734
; Returns information about disk media.
740
; Returns information about disk media.
735
; Floppy drives do not support insert notifications,
741
; Floppy drives do not support insert notifications,
736
; DISK_NO_INSERT_NOTIFICATION is set,
742
; DISK_NO_INSERT_NOTIFICATION is set,
737
; the disk subsystem calls this function before each filesystem operation.
743
; the disk subsystem calls this function before each filesystem operation.
738
; If the media has changed, return error for the first call as signal
744
; If the media has changed, return error for the first call as signal
739
; to finalize work with old media and the true geometry for the second call.
745
; to finalize work with old media and the true geometry for the second call.
740
; Assume that media is (possibly) changed anytime when motor is off.
746
; Assume that media is (possibly) changed anytime when motor is off.
741
proc floppy_querymedia
747
proc floppy_querymedia
742
  virtual at esp+4
748
  virtual at esp+4
743
    .userdata dd ?
749
    .userdata dd ?
744
    .info dd ?
750
    .info dd ?
745
  end virtual
751
  end virtual
746
; 1. Acquire the global lock.
752
; 1. Acquire the global lock.
747
        mov     ecx, floppy_mutex
753
        mov     ecx, floppy_mutex
748
        call    mutex_lock
754
        call    mutex_lock
749
        mov     edx, [.userdata]        ; 1 for /fd, 2 for /fd2
755
        mov     edx, [.userdata]        ; 1 for /fd, 2 for /fd2
750
; 2. If the media was reported and has been changed, forget it and report an error.
756
; 2. If the media was reported and has been changed, forget it and report an error.
751
        mov     al, [floppy_media_flags+edx-1]
757
        mov     al, [floppy_media_flags+edx-1]
752
        and     al, FLOPPY_MEDIA_PRESENT + FLOPPY_MEDIA_NEED_RESCAN
758
        and     al, FLOPPY_MEDIA_PRESENT + FLOPPY_MEDIA_NEED_RESCAN
753
        cmp     al, FLOPPY_MEDIA_PRESENT + FLOPPY_MEDIA_NEED_RESCAN
759
        cmp     al, FLOPPY_MEDIA_PRESENT + FLOPPY_MEDIA_NEED_RESCAN
754
        jnz     .not_reported
760
        jnz     .not_reported
755
.no_media:
761
.no_media:
756
        mov     [floppy_media_flags+edx-1], 0
762
        mov     [floppy_media_flags+edx-1], 0
757
.return_no_media:
763
.return_no_media:
758
        mov     ecx, floppy_mutex
764
        mov     ecx, floppy_mutex
759
        call    mutex_unlock
765
        call    mutex_unlock
760
        mov     eax, DISK_STATUS_NO_MEDIA
766
        mov     eax, DISK_STATUS_NO_MEDIA
761
        retn    8
767
        retn    8
762
.not_reported:
768
.not_reported:
763
; 3. If we are in the temporary state LABEL_CHANGED, this is the second call
769
; 3. If we are in the temporary state LABEL_CHANGED, this is the second call
764
; after intermediate DISK_STATUS_NO_MEDIA due to media change;
770
; after intermediate DISK_STATUS_NO_MEDIA due to media change;
765
; clear the flag and return the current geometry without rereading the bootsector.
771
; clear the flag and return the current geometry without rereading the bootsector.
766
        cmp     [floppy_media_flags+edx-1], FLOPPY_MEDIA_LABEL_CHANGED
772
        cmp     [floppy_media_flags+edx-1], FLOPPY_MEDIA_LABEL_CHANGED
767
        jz      .report_geometry
773
        jz      .report_geometry
768
; 4. Try to read the bootsector.
774
; 4. Try to read the bootsector.
769
        mov     [flp_number], dl
775
        mov     [flp_number], dl
770
        mov     [FDC_Status], 0
776
        mov     [FDC_Status], 0
771
        call    floppy_read_bootsector
777
        call    floppy_read_bootsector
772
; 5. If reading bootsector failed, assume that media is not present.
778
; 5. If reading bootsector failed, assume that media is not present.
773
        mov     edx, [.userdata]
779
        mov     edx, [.userdata]
774
        cmp     [FDC_Status], 0
780
        cmp     [FDC_Status], 0
775
        jnz     .no_media
781
        jnz     .no_media
776
; 6. Check whether the previous status is "present". If not, go to 10.
782
; 6. Check whether the previous status is "present". If not, go to 10.
777
        push    esi edi
783
        push    esi edi
778
        imul    edi, edx, 15
784
        imul    edi, edx, 15
779
        add     edi, flp_label-15
785
        add     edi, flp_label-15
780
        mov     esi, FDD_BUFF+39
786
        mov     esi, FDD_BUFF+39
781
        mov     ecx, 15
787
        mov     ecx, 15
782
        test    [floppy_media_flags+edx-1], FLOPPY_MEDIA_PRESENT
788
        test    [floppy_media_flags+edx-1], FLOPPY_MEDIA_PRESENT
783
        jz      .set_label
789
        jz      .set_label
784
; 7. Compare the old label with the current one.
790
; 7. Compare the old label with the current one.
785
        rep cmpsb
791
        rep cmpsb
786
; 8. If the label has not changed, go to 11.
792
; 8. If the label has not changed, go to 11.
787
        jz      .ok
793
        jz      .ok
788
; 9. If the label has changed, store it, enter temporary state LABEL_CHANGED
794
; 9. If the label has changed, store it, enter temporary state LABEL_CHANGED
789
; and report DISK_STATUS_NO_MEDIA.
795
; and report DISK_STATUS_NO_MEDIA.
790
;       dbgstr 'floppy label changed'
796
;       dbgstr 'floppy label changed'
791
        add     esi, ecx
797
        add     esi, ecx
792
        add     edi, ecx
798
        add     edi, ecx
793
        mov     ecx, 15
799
        mov     ecx, 15
794
        sub     esi, ecx
800
        sub     esi, ecx
795
        sub     edi, ecx
801
        sub     edi, ecx
796
        rep movsb
802
        rep movsb
797
        mov     [floppy_media_flags+edx-1], FLOPPY_MEDIA_LABEL_CHANGED
803
        mov     [floppy_media_flags+edx-1], FLOPPY_MEDIA_LABEL_CHANGED
798
        pop     edi esi
804
        pop     edi esi
799
        jmp     .return_no_media
805
        jmp     .return_no_media
800
.set_label:
806
.set_label:
801
; 10. The previous state was "not present". Copy the label.
807
; 10. The previous state was "not present". Copy the label.
802
        rep movsb
808
        rep movsb
803
.ok:
809
.ok:
804
        pop     edi esi
810
        pop     edi esi
805
.report_geometry:
811
.report_geometry:
806
; 11. Fill DISKMEDIAINFO structure.
812
; 11. Fill DISKMEDIAINFO structure.
807
        mov     ecx, [.info]
813
        mov     ecx, [.info]
808
        and     [ecx+DISKMEDIAINFO.Flags], 0
814
        and     [ecx+DISKMEDIAINFO.Flags], 0
809
        mov     [ecx+DISKMEDIAINFO.SectorSize], 512
815
        mov     [ecx+DISKMEDIAINFO.SectorSize], 512
810
        mov     dword [ecx+DISKMEDIAINFO.Capacity], FLOPPY_CAPACITY
816
        mov     dword [ecx+DISKMEDIAINFO.Capacity], FLOPPY_CAPACITY
811
        and     dword [ecx+DISKMEDIAINFO.Capacity+4], 0
817
        and     dword [ecx+DISKMEDIAINFO.Capacity+4], 0
812
; 12. Update state: media is present, data are actual.
818
; 12. Update state: media is present, data are actual.
813
        mov     [floppy_media_flags+edx-1], FLOPPY_MEDIA_PRESENT
819
        mov     [floppy_media_flags+edx-1], FLOPPY_MEDIA_PRESENT
814
; 13. Release the global lock and return successful status.
820
; 13. Release the global lock and return successful status.
815
        mov     ecx, floppy_mutex
821
        mov     ecx, floppy_mutex
816
        call    mutex_unlock
822
        call    mutex_unlock
817
        xor     eax, eax
823
        xor     eax, eax
818
        retn    8
824
        retn    8
819
endp
825
endp
820
 
826
 
821
proc floppy_read_bootsector
827
proc floppy_read_bootsector
822
        pushad
828
        pushad
823
        mov     [FDD_Track], 0; Цилиндр
829
        mov     [FDD_Track], 0; Цилиндр
824
        mov     [FDD_Head], 0; Сторона
830
        mov     [FDD_Head], 0; Сторона
825
        mov     [FDD_Sector], 1; Сектор
831
        mov     [FDD_Sector], 1; Сектор
826
        call    FDDMotorON
832
        call    FDDMotorON
827
        call    RecalibrateFDD
833
        call    RecalibrateFDD
828
        cmp     [FDC_Status], 0
834
        cmp     [FDC_Status], 0
829
        jne     .nothing
835
        jne     .nothing
830
        call    SeekTrack
836
        call    SeekTrack
831
        cmp     [FDC_Status], 0
837
        cmp     [FDC_Status], 0
832
        jne     .nothing
838
        jne     .nothing
833
        call    ReadSectWithRetr
839
        call    ReadSectWithRetr
834
.nothing:
840
.nothing:
835
        popad
841
        popad
836
        ret
842
        ret
837
endp
843
endp
838
 
844
 
839
read_chs_sector:
845
read_chs_sector:
840
        call    calculate_chs
846
        call    calculate_chs
841
        call    ReadSectWithRetr
847
        call    ReadSectWithRetr
842
        ret
848
        ret
843
 
849
 
844
save_chs_sector:
850
save_chs_sector:
845
        call    calculate_chs
851
        call    calculate_chs
846
        call    WriteSectWithRetr
852
        call    WriteSectWithRetr
847
        ret
853
        ret
848
 
854
 
849
calculate_chs:
855
calculate_chs:
850
        mov     bl, [FDD_Track]
856
        mov     bl, [FDD_Track]
851
        mov     [old_track], bl
857
        mov     [old_track], bl
852
        mov     ebx, 18
858
        mov     ebx, 18
853
        xor     edx, edx
859
        xor     edx, edx
854
        div     ebx
860
        div     ebx
855
        inc     edx
861
        inc     edx
856
        mov     [FDD_Sector], dl
862
        mov     [FDD_Sector], dl
857
        mov     edx, eax
863
        mov     edx, eax
858
        shr     eax, 1
864
        shr     eax, 1
859
        and     edx, 1
865
        and     edx, 1
860
        mov     [FDD_Track], al
866
        mov     [FDD_Track], al
861
        mov     [FDD_Head], dl
867
        mov     [FDD_Head], dl
862
        mov     dl, [old_track]
868
        mov     dl, [old_track]
863
        cmp     dl, [FDD_Track]
869
        cmp     dl, [FDD_Track]
864
        je      no_seek_track_1
870
        je      no_seek_track_1
865
        call    SeekTrack
871
        call    SeekTrack
866
no_seek_track_1:
872
no_seek_track_1:
867
        ret
873
        ret
868
 
874
 
869
; Writes one or more sectors to the device.
875
; Writes one or more sectors to the device.
870
proc floppy_write
876
proc floppy_write
871
        mov     dl, 1
877
        mov     dl, 1
872
        jmp     floppy_read_write
878
        jmp     floppy_read_write
873
endp
879
endp
874
 
880
 
875
; Reads one or more sectors from the device.
881
; Reads one or more sectors from the device.
876
proc floppy_read
882
proc floppy_read
877
        mov     dl, 0
883
        mov     dl, 0
878
endp
884
endp
879
 
885
 
880
; Common part of floppy_read and floppy_write.
886
; Common part of floppy_read and floppy_write.
881
proc floppy_read_write userdata:dword, buffer:dword, start_sector:qword, numsectors_ptr:dword
887
proc floppy_read_write userdata:dword, buffer:dword, start_sector:qword, numsectors_ptr:dword
882
virtual at ebp-8
888
virtual at ebp-8
883
.sectors_todo   dd      ?
889
.sectors_todo   dd      ?
884
.operation      db      ?
890
.operation      db      ?
885
end virtual
891
end virtual
886
        push    edx             ; save operation code to [.operation]
892
        push    edx             ; save operation code to [.operation]
887
; 1. Get number of sectors to read/write
893
; 1. Get number of sectors to read/write
888
; and zero number of sectors that were actually read/written.
894
; and zero number of sectors that were actually read/written.
889
        mov     eax, [numsectors_ptr]
895
        mov     eax, [numsectors_ptr]
890
        push    dword [eax]     ; initialize [.sectors_todo]
896
        push    dword [eax]     ; initialize [.sectors_todo]
891
        and     dword [eax], 0
897
        and     dword [eax], 0
892
        push    ebx esi edi     ; save used registers to be stdcall
898
        push    ebx esi edi     ; save used registers to be stdcall
893
; 2. Acquire the global lock.
899
; 2. Acquire the global lock.
894
        mov     ecx, floppy_mutex
900
        mov     ecx, floppy_mutex
895
        call    mutex_lock
901
        call    mutex_lock
896
; 3. Set floppy number for this operation.
902
; 3. Set floppy number for this operation.
897
        mov     edx, [userdata]
903
        mov     edx, [userdata]
898
        mov     [flp_number], dl
904
        mov     [flp_number], dl
899
; 4. Read/write sector-by-sector.
905
; 4. Read/write sector-by-sector.
900
.operation_loop:
906
.operation_loop:
901
; 4a. Check that the sector is inside the media.
907
; 4a. Check that the sector is inside the media.
902
        cmp     dword [start_sector+4], 0
908
        cmp     dword [start_sector+4], 0
903
        jnz     .end_of_media
909
        jnz     .end_of_media
904
        mov     eax, dword [start_sector]
910
        mov     eax, dword [start_sector]
905
        cmp     eax, FLOPPY_CAPACITY
911
        cmp     eax, FLOPPY_CAPACITY
906
        jae     .end_of_media
912
        jae     .end_of_media
907
; 4b. For read operation, call read_chs_sector and then move data from FDD_BUFF to [buffer].
913
; 4b. For read operation, call read_chs_sector and then move data from FDD_BUFF to [buffer].
908
; For write operation, move data from [buffer] to FDD_BUFF and then call save_chs_sector.
914
; For write operation, move data from [buffer] to FDD_BUFF and then call save_chs_sector.
909
        cmp     [.operation], 0
915
        cmp     [.operation], 0
910
        jz      .read
916
        jz      .read
911
        mov     esi, [buffer]
917
        mov     esi, [buffer]
912
        mov     edi, FDD_BUFF
918
        mov     edi, FDD_BUFF
913
        mov     ecx, 512/4
919
        mov     ecx, 512/4
914
        rep movsd
920
        rep movsd
915
        mov     [buffer], esi
921
        mov     [buffer], esi
916
        call    save_chs_sector
922
        call    save_chs_sector
917
        jmp     @f
923
        jmp     @f
918
.read:
924
.read:
919
        call    read_chs_sector
925
        call    read_chs_sector
920
        mov     esi, FDD_BUFF
926
        mov     esi, FDD_BUFF
921
        mov     edi, [buffer]
927
        mov     edi, [buffer]
922
        mov     ecx, 512/4
928
        mov     ecx, 512/4
923
        rep movsd
929
        rep movsd
924
        mov     [buffer], edi
930
        mov     [buffer], edi
925
@@:
931
@@:
926
; 4c. If there was an error, propagate it to the caller.
932
; 4c. If there was an error, propagate it to the caller.
927
        cmp     [FDC_Status], 0
933
        cmp     [FDC_Status], 0
928
        jnz     .fail
934
        jnz     .fail
929
; 4d. Otherwise, increment number of sectors processed and continue the loop.
935
; 4d. Otherwise, increment number of sectors processed and continue the loop.
930
        mov     eax, [numsectors_ptr]
936
        mov     eax, [numsectors_ptr]
931
        inc     dword [eax]
937
        inc     dword [eax]
932
        inc     dword [start_sector]
938
        inc     dword [start_sector]
933
        dec     [.sectors_todo]
939
        dec     [.sectors_todo]
934
        jnz     .operation_loop
940
        jnz     .operation_loop
935
; 5. Release the global lock and return with the correct status.
941
; 5. Release the global lock and return with the correct status.
936
        push    0
942
        push    0
937
.return:
943
.return:
938
        mov     ecx, floppy_mutex
944
        mov     ecx, floppy_mutex
939
        call    mutex_unlock
945
        call    mutex_unlock
940
        pop     eax
946
        pop     eax
941
        pop     edi esi ebx     ; restore used registers to be stdcall
947
        pop     edi esi ebx     ; restore used registers to be stdcall
942
        ret     ; this translates to leave/retn N and purges local variables
948
        ret     ; this translates to leave/retn N and purges local variables
943
.fail:
949
.fail:
944
        push    -1
950
        push    -1
945
        jmp     .return
951
        jmp     .return
946
.end_of_media:
952
.end_of_media:
947
        push    DISK_STATUS_END_OF_MEDIA
953
        push    DISK_STATUS_END_OF_MEDIA
948
        jmp     .return
954
        jmp     .return
949
endp
955
endp