Subversion Repositories Kolibri OS

Rev

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

Rev 5363 Rev 6814
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
3
;; Copyright (C) KolibriOS team 2004-2015. 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: 5363 $
8
$Revision: 6814 $
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, [flp_number]
371
        mov     AL, 00h
372
        dec     AL
372
        call    FDCDataOutput
373
        call    FDCDataOutput
373
; Ожидать завершения операции
374
; Ожидать завершения операции
374
        call    WaitFDCInterrupt
375
        call    WaitFDCInterrupt
375
        cmp     [FDC_Status], 0
376
        cmp     [FDC_Status], 0
376
        jne     .fail
377
        jne     .fail
377
; Read results of RECALIBRATE command
378
; Read results of RECALIBRATE command
378
;       DEBUGF 1,'K : floppy recalibrate results:'
379
;       DEBUGF 1,'K : floppy recalibrate results:'
379
        mov     al, 8
380
        mov     al, 8
380
        call    FDCDataOutput
381
        call    FDCDataOutput
381
        call    FDCDataInput
382
        call    FDCDataInput
382
        push    eax
383
        push    eax
383
;       DEBUGF 1,' %x',al
384
;       DEBUGF 1,' %x',al
384
        call    FDCDataInput
385
        call    FDCDataInput
385
;       DEBUGF 1,' %x',al
386
;       DEBUGF 1,' %x',al
386
;       DEBUGF 1,'\n'
387
;       DEBUGF 1,'\n'
387
        pop     eax
388
        pop     eax
388
        test    al, 0xC0
389
        test    al, 0xC0
389
        jz      @f
390
        jz      @f
390
        mov     [FDC_Status], FDC_DiskNotFound
391
        mov     [FDC_Status], FDC_DiskNotFound
391
@@:
392
@@:
392
.fail:
393
.fail:
393
        call    save_timer_fdd_motor
394
        call    save_timer_fdd_motor
394
        popa
395
        popa
395
        ret
396
        ret
396
 
397
 
397
;*****************************************************
398
;*****************************************************
398
;*                    ПОИСК ДОРОЖКИ                  *
399
;*                    ПОИСК ДОРОЖКИ                  *
399
;* Параметры передаются через глобальные переменные: *
400
;* Параметры передаются через глобальные переменные: *
400
;* FDD_Track - номер дорожки (0-79);                 *
401
;* FDD_Track - номер дорожки (0-79);                 *
401
;* FDD_Head - номер головки (0-1).                   *
402
;* FDD_Head - номер головки (0-1).                   *
402
;* Результат операции заносится в FDC_Status.        *
403
;* Результат операции заносится в FDC_Status.        *
403
;*****************************************************
404
;*****************************************************
404
SeekTrack:
405
SeekTrack:
405
;       dbgstr 'SeekTrack'
406
;       dbgstr 'SeekTrack'
406
        pusha
407
        pusha
407
        call    save_timer_fdd_motor
408
        call    save_timer_fdd_motor
408
; Сбросить флаг прерывания
409
; Сбросить флаг прерывания
409
        mov     [FDD_IntFlag], 0
410
        mov     [FDD_IntFlag], 0
410
; Подать команду "Поиск"
411
; Подать команду "Поиск"
411
        mov     AL, 0Fh
412
        mov     AL, 0Fh
412
        call    FDCDataOutput
413
        call    FDCDataOutput
413
        ; Передать байт номера головки/накопител
414
        ; Передать байт номера головки/накопител
414
        mov     AL, [FDD_Head]
415
        mov     AL, [FDD_Head]
415
        shl     AL, 2
416
        shl     AL, 2
416
        call    FDCDataOutput
417
        call    FDCDataOutput
417
        ; Передать байт номера дорожки
418
        ; Передать байт номера дорожки
418
        mov     AL, [FDD_Track]
419
        mov     AL, [FDD_Track]
419
        call    FDCDataOutput
420
        call    FDCDataOutput
420
; Ожидать завершения операции
421
; Ожидать завершения операции
421
        call    WaitFDCInterrupt
422
        call    WaitFDCInterrupt
422
        cmp     [FDC_Status], FDC_Normal
423
        cmp     [FDC_Status], FDC_Normal
423
        jne     @@Exit
424
        jne     @@Exit
424
; Сохранить результат поиска
425
; Сохранить результат поиска
425
        mov     AL, 08h
426
        mov     AL, 08h
426
        call    FDCDataOutput
427
        call    FDCDataOutput
427
        call    FDCDataInput
428
        call    FDCDataInput
428
        mov     [FDC_ST0], AL
429
        mov     [FDC_ST0], AL
429
        call    FDCDataInput
430
        call    FDCDataInput
430
        mov     [FDC_C], AL
431
        mov     [FDC_C], AL
431
; Проверить результат поиска
432
; Проверить результат поиска
432
        ; Поиск завершен?
433
        ; Поиск завершен?
433
        test    [FDC_ST0], 100000b
434
        test    [FDC_ST0], 100000b
434
        je      @@Err
435
        je      @@Err
435
        ; Заданный трек найден?
436
        ; Заданный трек найден?
436
        mov     AL, [FDC_C]
437
        mov     AL, [FDC_C]
437
        cmp     AL, [FDD_Track]
438
        cmp     AL, [FDD_Track]
438
        jne     @@Err
439
        jne     @@Err
439
        ; Номер головки совпадает с заданным?
440
        ; Номер головки совпадает с заданным?
440
; The H bit (Head Address) in ST0 will always return a "0" (c) 82077AA datasheet,
441
; The H bit (Head Address) in ST0 will always return a "0" (c) 82077AA datasheet,
441
; description of SEEK command. So we can not verify the proper head.
442
; description of SEEK command. So we can not verify the proper head.
442
;        mov     AL, [FDC_ST0]
443
;        mov     AL, [FDC_ST0]
443
;        and     AL, 100b
444
;        and     AL, 100b
444
;        shr     AL, 2
445
;        shr     AL, 2
445
;        cmp     AL, [FDD_Head]
446
;        cmp     AL, [FDD_Head]
446
;        jne     @@Err
447
;        jne     @@Err
447
        ; Операция завершена успешно
448
        ; Операция завершена успешно
448
;        dbgstr 'SeekTrack: FDC_Normal'
449
;        dbgstr 'SeekTrack: FDC_Normal'
449
        mov     [FDC_Status], FDC_Normal
450
        mov     [FDC_Status], FDC_Normal
450
        jmp     @@Exit
451
        jmp     @@Exit
451
@@Err:  ; Трек не найден
452
@@Err:  ; Трек не найден
452
;       dbgstr 'SeekTrack: FDC_TrackNotFound'
453
;       dbgstr 'SeekTrack: FDC_TrackNotFound'
453
        mov     [FDC_Status], FDC_TrackNotFound
454
        mov     [FDC_Status], FDC_TrackNotFound
454
@@Exit:
455
@@Exit:
455
        call    save_timer_fdd_motor
456
        call    save_timer_fdd_motor
456
        popa
457
        popa
457
        ret
458
        ret
458
 
459
 
459
;*******************************************************
460
;*******************************************************
460
;*               ЧТЕНИЕ СЕКТОРА ДАННЫХ                 *
461
;*               ЧТЕНИЕ СЕКТОРА ДАННЫХ                 *
461
;* Параметры передаются через глобальные переменные:   *
462
;* Параметры передаются через глобальные переменные:   *
462
;* FDD_Track - номер дорожки (0-79);                   *
463
;* FDD_Track - номер дорожки (0-79);                   *
463
;* FDD_Head - номер головки (0-1);                     *
464
;* FDD_Head - номер головки (0-1);                     *
464
;* FDD_Sector - номер сектора (1-18).                  *
465
;* FDD_Sector - номер сектора (1-18).                  *
465
;* Результат операции заносится в FDC_Status.          *
466
;* Результат операции заносится в FDC_Status.          *
466
;* В случае успешного выполнения операции чтения       *
467
;* В случае успешного выполнения операции чтения       *
467
;* содержимое сектора будет занесено в FDD_DataBuffer. *
468
;* содержимое сектора будет занесено в FDD_DataBuffer. *
468
;*******************************************************
469
;*******************************************************
469
ReadSector:
470
ReadSector:
470
;       dbgstr 'ReadSector'
471
;       dbgstr 'ReadSector'
471
        pushad
472
        pushad
472
        call    save_timer_fdd_motor
473
        call    save_timer_fdd_motor
473
; Сбросить флаг прерывания
474
; Сбросить флаг прерывания
474
        mov     [FDD_IntFlag], 0
475
        mov     [FDD_IntFlag], 0
475
; Установить скорость передачи 500 Кбайт/с
476
; Установить скорость передачи 500 Кбайт/с
476
        mov     AX, 0
477
        mov     AX, 0
477
        mov     DX, 03F7h
478
        mov     DX, 03F7h
478
        out     DX, AL
479
        out     DX, AL
479
; Инициализировать канал прямого доступа к памяти
480
; Инициализировать канал прямого доступа к памяти
480
        mov     [dmamode], 0x46
481
        mov     [dmamode], 0x46
481
        call    Init_FDC_DMA
482
        call    Init_FDC_DMA
482
; Подать команду "Чтение данных"
483
; Подать команду "Чтение данных"
483
        mov     AL, 0E6h ;чтение в мультитрековом режиме
484
        mov     AL, 0E6h ;чтение в мультитрековом режиме
484
        call    FDCDataOutput
485
        call    FDCDataOutput
485
        mov     AL, [FDD_Head]
486
        mov     AL, [FDD_Head]
486
        shl     AL, 2
487
        shl     AL, 2
-
 
488
        or      AL, [flp_number]
-
 
489
        dec     AL
487
        call    FDCDataOutput
490
        call    FDCDataOutput
488
        mov     AL, [FDD_Track]
491
        mov     AL, [FDD_Track]
489
        call    FDCDataOutput
492
        call    FDCDataOutput
490
        mov     AL, [FDD_Head]
493
        mov     AL, [FDD_Head]
491
        call    FDCDataOutput
494
        call    FDCDataOutput
492
        mov     AL, [FDD_Sector]
495
        mov     AL, [FDD_Sector]
493
        call    FDCDataOutput
496
        call    FDCDataOutput
494
        mov     AL, 2   ;код размера сектора (512 байт)
497
        mov     AL, 2   ;код размера сектора (512 байт)
495
        call    FDCDataOutput
498
        call    FDCDataOutput
496
        mov     AL, 18 ;+1; 3Fh  ;число секторов на дорожке
499
        mov     AL, 18 ;+1; 3Fh  ;число секторов на дорожке
497
        call    FDCDataOutput
500
        call    FDCDataOutput
498
        mov     AL, 1Bh ;значение GPL
501
        mov     AL, 1Bh ;значение GPL
499
        call    FDCDataOutput
502
        call    FDCDataOutput
500
        mov     AL, 0FFh;значение DTL
503
        mov     AL, 0FFh;значение DTL
501
        call    FDCDataOutput
504
        call    FDCDataOutput
502
; Ожидаем прерывание по завершении операции
505
; Ожидаем прерывание по завершении операции
503
        call    WaitFDCInterrupt
506
        call    WaitFDCInterrupt
504
        cmp     [FDC_Status], FDC_Normal
507
        cmp     [FDC_Status], FDC_Normal
505
        jne     @@Exit_1
508
        jne     @@Exit_1
506
; Считываем статус завершения операции
509
; Считываем статус завершения операции
507
        call    GetStatusInfo
510
        call    GetStatusInfo
508
        test    [FDC_ST0], 11011000b
511
        test    [FDC_ST0], 11011000b
509
        jnz     @@Err_1
512
        jnz     @@Err_1
510
;        dbgstr 'ReadSector: FDC_Normal'
513
;        dbgstr 'ReadSector: FDC_Normal'
511
        mov     [FDC_Status], FDC_Normal
514
        mov     [FDC_Status], FDC_Normal
512
        jmp     @@Exit_1
515
        jmp     @@Exit_1
513
@@Err_1:
516
@@Err_1:
514
;       dbgstr 'ReadSector: FDC_SectorNotFound'
517
;       dbgstr 'ReadSector: FDC_SectorNotFound'
515
        mov     [FDC_Status], FDC_SectorNotFound
518
        mov     [FDC_Status], FDC_SectorNotFound
516
@@Exit_1:
519
@@Exit_1:
517
        call    save_timer_fdd_motor
520
        call    save_timer_fdd_motor
518
        popad
521
        popad
519
        ret
522
        ret
520
 
523
 
521
;*******************************************************
524
;*******************************************************
522
;*   ЧТЕНИЕ СЕКТОРА (С ПОВТОРЕНИЕМ ОПЕРАЦИИ ПРИ СБОЕ)  *
525
;*   ЧТЕНИЕ СЕКТОРА (С ПОВТОРЕНИЕМ ОПЕРАЦИИ ПРИ СБОЕ)  *
523
;* Параметры передаются через глобальные переменные:   *
526
;* Параметры передаются через глобальные переменные:   *
524
;* FDD_Track - номер дорожки (0-79);                   *
527
;* FDD_Track - номер дорожки (0-79);                   *
525
;* FDD_Head - номер головки (0-1);                     *
528
;* FDD_Head - номер головки (0-1);                     *
526
;* FDD_Sector - номер сектора (1-18).                  *
529
;* FDD_Sector - номер сектора (1-18).                  *
527
;* Результат операции заносится в FDC_Status.          *
530
;* Результат операции заносится в FDC_Status.          *
528
;* В случае успешного выполнения операции чтения       *
531
;* В случае успешного выполнения операции чтения       *
529
;* содержимое сектора будет занесено в FDD_DataBuffer. *
532
;* содержимое сектора будет занесено в FDD_DataBuffer. *
530
;*******************************************************
533
;*******************************************************
531
ReadSectWithRetr:
534
ReadSectWithRetr:
532
        pusha
535
        pusha
533
; Обнулить счетчик повторения операции рекалибровки
536
; Обнулить счетчик повторения операции рекалибровки
534
        mov     [RecalRepCounter], 0
537
        mov     [RecalRepCounter], 0
535
@@TryAgain:
538
@@TryAgain:
536
; Обнулить счетчик повторения операции чтени
539
; Обнулить счетчик повторения операции чтени
537
        mov     [ReadRepCounter], 0
540
        mov     [ReadRepCounter], 0
538
@@ReadSector_1:
541
@@ReadSector_1:
539
        call    ReadSector
542
        call    ReadSector
540
        cmp     [FDC_Status], 0
543
        cmp     [FDC_Status], 0
541
        je      @@Exit_2
544
        je      @@Exit_2
542
        cmp     [FDC_Status], 1
545
        cmp     [FDC_Status], 1
543
        je      @@Err_3
546
        je      @@Err_3
544
        ; Троекратное повторение чтени
547
        ; Троекратное повторение чтени
545
        inc     [ReadRepCounter]
548
        inc     [ReadRepCounter]
546
        cmp     [ReadRepCounter], 3
549
        cmp     [ReadRepCounter], 3
547
        jb      @@ReadSector_1
550
        jb      @@ReadSector_1
548
        ; Троекратное повторение рекалибровки
551
        ; Троекратное повторение рекалибровки
549
        call    RecalibrateFDD
552
        call    RecalibrateFDD
550
        call    SeekTrack
553
        call    SeekTrack
551
        inc     [RecalRepCounter]
554
        inc     [RecalRepCounter]
552
        cmp     [RecalRepCounter], 3
555
        cmp     [RecalRepCounter], 3
553
        jb      @@TryAgain
556
        jb      @@TryAgain
554
@@Exit_2:
557
@@Exit_2:
555
        popa
558
        popa
556
        ret
559
        ret
557
@@Err_3:
560
@@Err_3:
558
        popa
561
        popa
559
        ret
562
        ret
560
 
563
 
561
;*******************************************************
564
;*******************************************************
562
;*               ЗАПИСЬ СЕКТОРА ДАННЫХ                 *
565
;*               ЗАПИСЬ СЕКТОРА ДАННЫХ                 *
563
;* Параметры передаются через глобальные переменные:   *
566
;* Параметры передаются через глобальные переменные:   *
564
;* FDD_Track - номер дорожки (0-79);                   *
567
;* FDD_Track - номер дорожки (0-79);                   *
565
;* FDD_Head - номер головки (0-1);                     *
568
;* FDD_Head - номер головки (0-1);                     *
566
;* FDD_Sector - номер сектора (1-18).                  *
569
;* FDD_Sector - номер сектора (1-18).                  *
567
;* Результат операции заносится в FDC_Status.          *
570
;* Результат операции заносится в FDC_Status.          *
568
;* В случае успешного выполнения операции записи       *
571
;* В случае успешного выполнения операции записи       *
569
;* содержимое FDD_DataBuffer будет занесено в сектор.  *
572
;* содержимое FDD_DataBuffer будет занесено в сектор.  *
570
;*******************************************************
573
;*******************************************************
571
WriteSector:
574
WriteSector:
572
;       dbgstr 'WriteSector'
575
;       dbgstr 'WriteSector'
573
        pushad
576
        pushad
574
        call    save_timer_fdd_motor
577
        call    save_timer_fdd_motor
575
; Сбросить флаг прерывания
578
; Сбросить флаг прерывания
576
        mov     [FDD_IntFlag], 0
579
        mov     [FDD_IntFlag], 0
577
; Установить скорость передачи 500 Кбайт/с
580
; Установить скорость передачи 500 Кбайт/с
578
        mov     AX, 0
581
        mov     AX, 0
579
        mov     DX, 03F7h
582
        mov     DX, 03F7h
580
        out     DX, AL
583
        out     DX, AL
581
; Инициализировать канал прямого доступа к памяти
584
; Инициализировать канал прямого доступа к памяти
582
        mov     [dmamode], 0x4A
585
        mov     [dmamode], 0x4A
583
        call    Init_FDC_DMA
586
        call    Init_FDC_DMA
584
; Подать команду "Запись данных"
587
; Подать команду "Запись данных"
585
        mov     AL, 0xC5 ;0x45  ;запись в мультитрековом режиме
588
        mov     AL, 0xC5 ;0x45  ;запись в мультитрековом режиме
586
        call    FDCDataOutput
589
        call    FDCDataOutput
587
        mov     AL, [FDD_Head]
590
        mov     AL, [FDD_Head]
588
        shl     AL, 2
591
        shl     AL, 2
-
 
592
        or      AL, [flp_number]
-
 
593
        dec     AL
589
        call    FDCDataOutput
594
        call    FDCDataOutput
590
        mov     AL, [FDD_Track]
595
        mov     AL, [FDD_Track]
591
        call    FDCDataOutput
596
        call    FDCDataOutput
592
        mov     AL, [FDD_Head]
597
        mov     AL, [FDD_Head]
593
        call    FDCDataOutput
598
        call    FDCDataOutput
594
        mov     AL, [FDD_Sector]
599
        mov     AL, [FDD_Sector]
595
        call    FDCDataOutput
600
        call    FDCDataOutput
596
        mov     AL, 2   ;код размера сектора (512 байт)
601
        mov     AL, 2   ;код размера сектора (512 байт)
597
        call    FDCDataOutput
602
        call    FDCDataOutput
598
        mov     AL, 18; 3Fh  ;число секторов на дорожке
603
        mov     AL, 18; 3Fh  ;число секторов на дорожке
599
        call    FDCDataOutput
604
        call    FDCDataOutput
600
        mov     AL, 1Bh ;значение GPL
605
        mov     AL, 1Bh ;значение GPL
601
        call    FDCDataOutput
606
        call    FDCDataOutput
602
        mov     AL, 0FFh;значение DTL
607
        mov     AL, 0FFh;значение DTL
603
        call    FDCDataOutput
608
        call    FDCDataOutput
604
; Ожидаем прерывание по завершении операции
609
; Ожидаем прерывание по завершении операции
605
        call    WaitFDCInterrupt
610
        call    WaitFDCInterrupt
606
        cmp     [FDC_Status], FDC_Normal
611
        cmp     [FDC_Status], FDC_Normal
607
        jne     @@Exit_3
612
        jne     @@Exit_3
608
; Считываем статус завершения операции
613
; Считываем статус завершения операции
609
        call    GetStatusInfo
614
        call    GetStatusInfo
610
        test    [FDC_ST0], 11000000b ;11011000b
615
        test    [FDC_ST0], 11000000b ;11011000b
611
        jnz     @@Err_2
616
        jnz     @@Err_2
612
        mov     [FDC_Status], FDC_Normal
617
        mov     [FDC_Status], FDC_Normal
613
        jmp     @@Exit_3
618
        jmp     @@Exit_3
614
@@Err_2:
619
@@Err_2:
615
        mov     [FDC_Status], FDC_SectorNotFound
620
        mov     [FDC_Status], FDC_SectorNotFound
616
@@Exit_3:
621
@@Exit_3:
617
        call    save_timer_fdd_motor
622
        call    save_timer_fdd_motor
618
        popad
623
        popad
619
        ret
624
        ret
620
 
625
 
621
;*******************************************************
626
;*******************************************************
622
;*   ЗАПИСЬ СЕКТОРА (С ПОВТОРЕНИЕМ ОПЕРАЦИИ ПРИ СБОЕ)  *
627
;*   ЗАПИСЬ СЕКТОРА (С ПОВТОРЕНИЕМ ОПЕРАЦИИ ПРИ СБОЕ)  *
623
;* Параметры передаются через глобальные переменные:   *
628
;* Параметры передаются через глобальные переменные:   *
624
;* FDD_Track - номер дорожки (0-79);                   *
629
;* FDD_Track - номер дорожки (0-79);                   *
625
;* FDD_Head - номер головки (0-1);                     *
630
;* FDD_Head - номер головки (0-1);                     *
626
;* FDD_Sector - номер сектора (1-18).                  *
631
;* FDD_Sector - номер сектора (1-18).                  *
627
;* Результат операции заносится в FDC_Status.          *
632
;* Результат операции заносится в FDC_Status.          *
628
;* В случае успешного выполнения операции записи       *
633
;* В случае успешного выполнения операции записи       *
629
;* содержимое FDD_DataBuffer будет занесено в сектор.  *
634
;* содержимое FDD_DataBuffer будет занесено в сектор.  *
630
;*******************************************************
635
;*******************************************************
631
WriteSectWithRetr:
636
WriteSectWithRetr:
632
        pusha
637
        pusha
633
; Обнулить счетчик повторения операции рекалибровки
638
; Обнулить счетчик повторения операции рекалибровки
634
        mov     [RecalRepCounter], 0
639
        mov     [RecalRepCounter], 0
635
@@TryAgain_1:
640
@@TryAgain_1:
636
; Обнулить счетчик повторения операции чтени
641
; Обнулить счетчик повторения операции чтени
637
        mov     [ReadRepCounter], 0
642
        mov     [ReadRepCounter], 0
638
@@WriteSector_1:
643
@@WriteSector_1:
639
        call    WriteSector
644
        call    WriteSector
640
        cmp     [FDC_Status], 0
645
        cmp     [FDC_Status], 0
641
        je      @@Exit_4
646
        je      @@Exit_4
642
        cmp     [FDC_Status], 1
647
        cmp     [FDC_Status], 1
643
        je      @@Err_4
648
        je      @@Err_4
644
        ; Троекратное повторение чтени
649
        ; Троекратное повторение чтени
645
        inc     [ReadRepCounter]
650
        inc     [ReadRepCounter]
646
        cmp     [ReadRepCounter], 3
651
        cmp     [ReadRepCounter], 3
647
        jb      @@WriteSector_1
652
        jb      @@WriteSector_1
648
        ; Троекратное повторение рекалибровки
653
        ; Троекратное повторение рекалибровки
649
        call    RecalibrateFDD
654
        call    RecalibrateFDD
650
        call    SeekTrack
655
        call    SeekTrack
651
        inc     [RecalRepCounter]
656
        inc     [RecalRepCounter]
652
        cmp     [RecalRepCounter], 3
657
        cmp     [RecalRepCounter], 3
653
        jb      @@TryAgain_1
658
        jb      @@TryAgain_1
654
@@Exit_4:
659
@@Exit_4:
655
        popa
660
        popa
656
        ret
661
        ret
657
@@Err_4:
662
@@Err_4:
658
        popa
663
        popa
659
        ret
664
        ret
660
 
665
 
661
;*********************************************
666
;*********************************************
662
;* ПОЛУЧИТЬ ИНФОРМАЦИЮ О РЕЗУЛЬТАТЕ ОПЕРАЦИИ *
667
;* ПОЛУЧИТЬ ИНФОРМАЦИЮ О РЕЗУЛЬТАТЕ ОПЕРАЦИИ *
663
;*********************************************
668
;*********************************************
664
GetStatusInfo:
669
GetStatusInfo:
665
        push    AX
670
        push    AX
666
        call    FDCDataInput
671
        call    FDCDataInput
667
        mov     [FDC_ST0], AL
672
        mov     [FDC_ST0], AL
668
        call    FDCDataInput
673
        call    FDCDataInput
669
        mov     [FDC_ST1], AL
674
        mov     [FDC_ST1], AL
670
        call    FDCDataInput
675
        call    FDCDataInput
671
        mov     [FDC_ST2], AL
676
        mov     [FDC_ST2], AL
672
        call    FDCDataInput
677
        call    FDCDataInput
673
        mov     [FDC_C], AL
678
        mov     [FDC_C], AL
674
        call    FDCDataInput
679
        call    FDCDataInput
675
        mov     [FDC_H], AL
680
        mov     [FDC_H], AL
676
        call    FDCDataInput
681
        call    FDCDataInput
677
        mov     [FDC_R], AL
682
        mov     [FDC_R], AL
678
        call    FDCDataInput
683
        call    FDCDataInput
679
        mov     [FDC_N], AL
684
        mov     [FDC_N], AL
680
        pop     AX
685
        pop     AX
681
        ret
686
        ret
682
 
687
 
683
; Interface for disk subsystem.
688
; Interface for disk subsystem.
684
; Assume fixed capacity for 1.44M.
689
; Assume fixed capacity for 1.44M.
685
FLOPPY_CAPACITY = 2880  ; in sectors
690
FLOPPY_CAPACITY = 2880  ; in sectors
686
 
691
 
687
iglobal
692
iglobal
688
align 4
693
align 4
689
floppy_functions:
694
floppy_functions:
690
        dd      .size
695
        dd      .size
691
        dd      0       ; no close() function
696
        dd      0       ; no close() function
692
        dd      0       ; no closemedia() function
697
        dd      0       ; no closemedia() function
693
        dd      floppy_querymedia
698
        dd      floppy_querymedia
694
        dd      floppy_read
699
        dd      floppy_read
695
        dd      floppy_write
700
        dd      floppy_write
696
        dd      0       ; no flush() function
701
        dd      0       ; no flush() function
697
        dd      0       ; no adjust_cache_size() function
702
        dd      0       ; no adjust_cache_size() function
698
.size = $ - floppy_functions
703
.size = $ - floppy_functions
699
endg
704
endg
700
 
705
 
701
uglobal
706
uglobal
702
floppy_media_flags      rb      2
707
floppy_media_flags      rb      2
703
n_sector    dd 0  ; temporary save for sector value
708
n_sector    dd 0  ; temporary save for sector value
704
flp_number  db 0  ; 1- Floppy A, 2-Floppy B
709
flp_number  db 0  ; 1- Floppy A, 2-Floppy B
705
old_track   db 0  ; old value track
710
old_track   db 0  ; old value track
706
flp_label   rb 15*2 ; Label and ID of inserted floppy disk
711
flp_label   rb 15*2 ; Label and ID of inserted floppy disk
707
align 4
712
align 4
708
; Hardware does not allow to work with two floppies in parallel,
713
; Hardware does not allow to work with two floppies in parallel,
709
; so there is one mutex guarding access to any floppy.
714
; so there is one mutex guarding access to any floppy.
710
floppy_mutex    MUTEX
715
floppy_mutex    MUTEX
711
endg
716
endg
712
; Meaning of bits in floppy_media_flags
717
; Meaning of bits in floppy_media_flags
713
FLOPPY_MEDIA_PRESENT = 1        ; media was present when last asked
718
FLOPPY_MEDIA_PRESENT = 1        ; media was present when last asked
714
FLOPPY_MEDIA_NEED_RESCAN = 2    ; media was possibly changed, need to rescan
719
FLOPPY_MEDIA_NEED_RESCAN = 2    ; media was possibly changed, need to rescan
715
FLOPPY_MEDIA_LABEL_CHANGED = 4  ; temporary state
720
FLOPPY_MEDIA_LABEL_CHANGED = 4  ; temporary state
716
 
721
 
717
iglobal
722
iglobal
718
floppy1_name    db      'fd',0
723
floppy1_name    db      'fd',0
719
floppy2_name    db      'fd2',0
724
floppy2_name    db      'fd2',0
720
endg
725
endg
721
 
726
 
722
; This function is called in boot process.
727
; This function is called in boot process.
723
; It creates filesystems /fd and/or /fd2, if the system has one/two floppy drives.
728
; It creates filesystems /fd and/or /fd2, if the system has one/two floppy drives.
724
proc floppy_init
729
proc floppy_init
725
        mov     ecx, floppy_mutex
730
        mov     ecx, floppy_mutex
726
        call    mutex_init
731
        call    mutex_init
727
; First floppy is present if [DRIVE_DATA] and 0xF0 is nonzero.
732
; First floppy is present if [DRIVE_DATA] and 0xF0 is nonzero.
728
        test    byte [DRIVE_DATA], 0xF0
733
        test    byte [DRIVE_DATA], 0xF0
729
        jz      .no1
734
        jz      .no1
730
        stdcall disk_add, floppy_functions, floppy1_name, 1, DISK_NO_INSERT_NOTIFICATION
735
        stdcall disk_add, floppy_functions, floppy1_name, 1, DISK_NO_INSERT_NOTIFICATION
731
.no1:
736
.no1:
732
; Second floppy is present if [DRIVE_DATA] and 0x0F is nonzero.
737
; Second floppy is present if [DRIVE_DATA] and 0x0F is nonzero.
733
        test    byte [DRIVE_DATA], 0x0F
738
        test    byte [DRIVE_DATA], 0x0F
734
        jz      .no2
739
        jz      .no2
735
        stdcall disk_add, floppy_functions, floppy2_name, 2, DISK_NO_INSERT_NOTIFICATION
740
        stdcall disk_add, floppy_functions, floppy2_name, 2, DISK_NO_INSERT_NOTIFICATION
736
.no2:
741
.no2:
737
        ret
742
        ret
738
endp
743
endp
739
 
744
 
740
; Returns information about disk media.
745
; Returns information about disk media.
741
; Floppy drives do not support insert notifications,
746
; Floppy drives do not support insert notifications,
742
; DISK_NO_INSERT_NOTIFICATION is set,
747
; DISK_NO_INSERT_NOTIFICATION is set,
743
; the disk subsystem calls this function before each filesystem operation.
748
; the disk subsystem calls this function before each filesystem operation.
744
; If the media has changed, return error for the first call as signal
749
; If the media has changed, return error for the first call as signal
745
; to finalize work with old media and the true geometry for the second call.
750
; to finalize work with old media and the true geometry for the second call.
746
; Assume that media is (possibly) changed anytime when motor is off.
751
; Assume that media is (possibly) changed anytime when motor is off.
747
proc floppy_querymedia
752
proc floppy_querymedia
748
  virtual at esp+4
753
  virtual at esp+4
749
    .userdata dd ?
754
    .userdata dd ?
750
    .info dd ?
755
    .info dd ?
751
  end virtual
756
  end virtual
752
; 1. Acquire the global lock.
757
; 1. Acquire the global lock.
753
        mov     ecx, floppy_mutex
758
        mov     ecx, floppy_mutex
754
        call    mutex_lock
759
        call    mutex_lock
755
        mov     edx, [.userdata]        ; 1 for /fd, 2 for /fd2
760
        mov     edx, [.userdata]        ; 1 for /fd, 2 for /fd2
756
; 2. If the media was reported and has been changed, forget it and report an error.
761
; 2. If the media was reported and has been changed, forget it and report an error.
757
        mov     al, [floppy_media_flags+edx-1]
762
        mov     al, [floppy_media_flags+edx-1]
758
        and     al, FLOPPY_MEDIA_PRESENT + FLOPPY_MEDIA_NEED_RESCAN
763
        and     al, FLOPPY_MEDIA_PRESENT + FLOPPY_MEDIA_NEED_RESCAN
759
        cmp     al, FLOPPY_MEDIA_PRESENT + FLOPPY_MEDIA_NEED_RESCAN
764
        cmp     al, FLOPPY_MEDIA_PRESENT + FLOPPY_MEDIA_NEED_RESCAN
760
        jnz     .not_reported
765
        jnz     .not_reported
761
.no_media:
766
.no_media:
762
        mov     [floppy_media_flags+edx-1], 0
767
        mov     [floppy_media_flags+edx-1], 0
763
.return_no_media:
768
.return_no_media:
764
        mov     ecx, floppy_mutex
769
        mov     ecx, floppy_mutex
765
        call    mutex_unlock
770
        call    mutex_unlock
766
        mov     eax, DISK_STATUS_NO_MEDIA
771
        mov     eax, DISK_STATUS_NO_MEDIA
767
        retn    8
772
        retn    8
768
.not_reported:
773
.not_reported:
769
; 3. If we are in the temporary state LABEL_CHANGED, this is the second call
774
; 3. If we are in the temporary state LABEL_CHANGED, this is the second call
770
; after intermediate DISK_STATUS_NO_MEDIA due to media change;
775
; after intermediate DISK_STATUS_NO_MEDIA due to media change;
771
; clear the flag and return the current geometry without rereading the bootsector.
776
; clear the flag and return the current geometry without rereading the bootsector.
772
        cmp     [floppy_media_flags+edx-1], FLOPPY_MEDIA_LABEL_CHANGED
777
        cmp     [floppy_media_flags+edx-1], FLOPPY_MEDIA_LABEL_CHANGED
773
        jz      .report_geometry
778
        jz      .report_geometry
774
; 4. Try to read the bootsector.
779
; 4. Try to read the bootsector.
775
        mov     [flp_number], dl
780
        mov     [flp_number], dl
776
        mov     [FDC_Status], 0
781
        mov     [FDC_Status], 0
777
        call    floppy_read_bootsector
782
        call    floppy_read_bootsector
778
; 5. If reading bootsector failed, assume that media is not present.
783
; 5. If reading bootsector failed, assume that media is not present.
779
        mov     edx, [.userdata]
784
        mov     edx, [.userdata]
780
        cmp     [FDC_Status], 0
785
        cmp     [FDC_Status], 0
781
        jnz     .no_media
786
        jnz     .no_media
782
; 6. Check whether the previous status is "present". If not, go to 10.
787
; 6. Check whether the previous status is "present". If not, go to 10.
783
        push    esi edi
788
        push    esi edi
784
        imul    edi, edx, 15
789
        imul    edi, edx, 15
785
        add     edi, flp_label-15
790
        add     edi, flp_label-15
786
        mov     esi, FDD_BUFF+39
791
        mov     esi, FDD_BUFF+39
787
        mov     ecx, 15
792
        mov     ecx, 15
788
        test    [floppy_media_flags+edx-1], FLOPPY_MEDIA_PRESENT
793
        test    [floppy_media_flags+edx-1], FLOPPY_MEDIA_PRESENT
789
        jz      .set_label
794
        jz      .set_label
790
; 7. Compare the old label with the current one.
795
; 7. Compare the old label with the current one.
791
        rep cmpsb
796
        rep cmpsb
792
; 8. If the label has not changed, go to 11.
797
; 8. If the label has not changed, go to 11.
793
        jz      .ok
798
        jz      .ok
794
; 9. If the label has changed, store it, enter temporary state LABEL_CHANGED
799
; 9. If the label has changed, store it, enter temporary state LABEL_CHANGED
795
; and report DISK_STATUS_NO_MEDIA.
800
; and report DISK_STATUS_NO_MEDIA.
796
;       dbgstr 'floppy label changed'
801
;       dbgstr 'floppy label changed'
797
        add     esi, ecx
802
        add     esi, ecx
798
        add     edi, ecx
803
        add     edi, ecx
799
        mov     ecx, 15
804
        mov     ecx, 15
800
        sub     esi, ecx
805
        sub     esi, ecx
801
        sub     edi, ecx
806
        sub     edi, ecx
802
        rep movsb
807
        rep movsb
803
        mov     [floppy_media_flags+edx-1], FLOPPY_MEDIA_LABEL_CHANGED
808
        mov     [floppy_media_flags+edx-1], FLOPPY_MEDIA_LABEL_CHANGED
804
        pop     edi esi
809
        pop     edi esi
805
        jmp     .return_no_media
810
        jmp     .return_no_media
806
.set_label:
811
.set_label:
807
; 10. The previous state was "not present". Copy the label.
812
; 10. The previous state was "not present". Copy the label.
808
        rep movsb
813
        rep movsb
809
.ok:
814
.ok:
810
        pop     edi esi
815
        pop     edi esi
811
.report_geometry:
816
.report_geometry:
812
; 11. Fill DISKMEDIAINFO structure.
817
; 11. Fill DISKMEDIAINFO structure.
813
        mov     ecx, [.info]
818
        mov     ecx, [.info]
814
        and     [ecx+DISKMEDIAINFO.Flags], 0
819
        and     [ecx+DISKMEDIAINFO.Flags], 0
815
        mov     [ecx+DISKMEDIAINFO.SectorSize], 512
820
        mov     [ecx+DISKMEDIAINFO.SectorSize], 512
816
        mov     dword [ecx+DISKMEDIAINFO.Capacity], FLOPPY_CAPACITY
821
        mov     dword [ecx+DISKMEDIAINFO.Capacity], FLOPPY_CAPACITY
817
        and     dword [ecx+DISKMEDIAINFO.Capacity+4], 0
822
        and     dword [ecx+DISKMEDIAINFO.Capacity+4], 0
818
; 12. Update state: media is present, data are actual.
823
; 12. Update state: media is present, data are actual.
819
        mov     [floppy_media_flags+edx-1], FLOPPY_MEDIA_PRESENT
824
        mov     [floppy_media_flags+edx-1], FLOPPY_MEDIA_PRESENT
820
; 13. Release the global lock and return successful status.
825
; 13. Release the global lock and return successful status.
821
        mov     ecx, floppy_mutex
826
        mov     ecx, floppy_mutex
822
        call    mutex_unlock
827
        call    mutex_unlock
823
        xor     eax, eax
828
        xor     eax, eax
824
        retn    8
829
        retn    8
825
endp
830
endp
826
 
831
 
827
proc floppy_read_bootsector
832
proc floppy_read_bootsector
828
        pushad
833
        pushad
829
        mov     [FDD_Track], 0; Цилиндр
834
        mov     [FDD_Track], 0; Цилиндр
830
        mov     [FDD_Head], 0; Сторона
835
        mov     [FDD_Head], 0; Сторона
831
        mov     [FDD_Sector], 1; Сектор
836
        mov     [FDD_Sector], 1; Сектор
832
        call    FDDMotorON
837
        call    FDDMotorON
833
        call    RecalibrateFDD
838
        call    RecalibrateFDD
834
        cmp     [FDC_Status], 0
839
        cmp     [FDC_Status], 0
835
        jne     .nothing
840
        jne     .nothing
836
        call    SeekTrack
841
        call    SeekTrack
837
        cmp     [FDC_Status], 0
842
        cmp     [FDC_Status], 0
838
        jne     .nothing
843
        jne     .nothing
839
        call    ReadSectWithRetr
844
        call    ReadSectWithRetr
840
.nothing:
845
.nothing:
841
        popad
846
        popad
842
        ret
847
        ret
843
endp
848
endp
844
 
849
 
845
read_chs_sector:
850
read_chs_sector:
846
        call    calculate_chs
851
        call    calculate_chs
847
        call    ReadSectWithRetr
852
        call    ReadSectWithRetr
848
        ret
853
        ret
849
 
854
 
850
save_chs_sector:
855
save_chs_sector:
851
        call    calculate_chs
856
        call    calculate_chs
852
        call    WriteSectWithRetr
857
        call    WriteSectWithRetr
853
        ret
858
        ret
854
 
859
 
855
calculate_chs:
860
calculate_chs:
856
        mov     bl, [FDD_Track]
861
        mov     bl, [FDD_Track]
857
        mov     [old_track], bl
862
        mov     [old_track], bl
858
        mov     ebx, 18
863
        mov     ebx, 18
859
        xor     edx, edx
864
        xor     edx, edx
860
        div     ebx
865
        div     ebx
861
        inc     edx
866
        inc     edx
862
        mov     [FDD_Sector], dl
867
        mov     [FDD_Sector], dl
863
        mov     edx, eax
868
        mov     edx, eax
864
        shr     eax, 1
869
        shr     eax, 1
865
        and     edx, 1
870
        and     edx, 1
866
        mov     [FDD_Track], al
871
        mov     [FDD_Track], al
867
        mov     [FDD_Head], dl
872
        mov     [FDD_Head], dl
868
        mov     dl, [old_track]
873
        mov     dl, [old_track]
869
        cmp     dl, [FDD_Track]
874
        cmp     dl, [FDD_Track]
870
        je      no_seek_track_1
875
        je      no_seek_track_1
871
        call    SeekTrack
876
        call    SeekTrack
872
no_seek_track_1:
877
no_seek_track_1:
873
        ret
878
        ret
874
 
879
 
875
; Writes one or more sectors to the device.
880
; Writes one or more sectors to the device.
876
proc floppy_write
881
proc floppy_write
877
        mov     dl, 1
882
        mov     dl, 1
878
        jmp     floppy_read_write
883
        jmp     floppy_read_write
879
endp
884
endp
880
 
885
 
881
; Reads one or more sectors from the device.
886
; Reads one or more sectors from the device.
882
proc floppy_read
887
proc floppy_read
883
        mov     dl, 0
888
        mov     dl, 0
884
endp
889
endp
885
 
890
 
886
; Common part of floppy_read and floppy_write.
891
; Common part of floppy_read and floppy_write.
887
proc floppy_read_write userdata:dword, buffer:dword, start_sector:qword, numsectors_ptr:dword
892
proc floppy_read_write userdata:dword, buffer:dword, start_sector:qword, numsectors_ptr:dword
888
virtual at ebp-8
893
virtual at ebp-8
889
.sectors_todo   dd      ?
894
.sectors_todo   dd      ?
890
.operation      db      ?
895
.operation      db      ?
891
end virtual
896
end virtual
892
        push    edx             ; save operation code to [.operation]
897
        push    edx             ; save operation code to [.operation]
893
; 1. Get number of sectors to read/write
898
; 1. Get number of sectors to read/write
894
; and zero number of sectors that were actually read/written.
899
; and zero number of sectors that were actually read/written.
895
        mov     eax, [numsectors_ptr]
900
        mov     eax, [numsectors_ptr]
896
        push    dword [eax]     ; initialize [.sectors_todo]
901
        push    dword [eax]     ; initialize [.sectors_todo]
897
        and     dword [eax], 0
902
        and     dword [eax], 0
898
        push    ebx esi edi     ; save used registers to be stdcall
903
        push    ebx esi edi     ; save used registers to be stdcall
899
; 2. Acquire the global lock.
904
; 2. Acquire the global lock.
900
        mov     ecx, floppy_mutex
905
        mov     ecx, floppy_mutex
901
        call    mutex_lock
906
        call    mutex_lock
902
; 3. Set floppy number for this operation.
907
; 3. Set floppy number for this operation.
903
        mov     edx, [userdata]
908
        mov     edx, [userdata]
904
        mov     [flp_number], dl
909
        mov     [flp_number], dl
905
; 4. Read/write sector-by-sector.
910
; 4. Read/write sector-by-sector.
906
.operation_loop:
911
.operation_loop:
907
; 4a. Check that the sector is inside the media.
912
; 4a. Check that the sector is inside the media.
908
        cmp     dword [start_sector+4], 0
913
        cmp     dword [start_sector+4], 0
909
        jnz     .end_of_media
914
        jnz     .end_of_media
910
        mov     eax, dword [start_sector]
915
        mov     eax, dword [start_sector]
911
        cmp     eax, FLOPPY_CAPACITY
916
        cmp     eax, FLOPPY_CAPACITY
912
        jae     .end_of_media
917
        jae     .end_of_media
913
; 4b. For read operation, call read_chs_sector and then move data from FDD_BUFF to [buffer].
918
; 4b. For read operation, call read_chs_sector and then move data from FDD_BUFF to [buffer].
914
; For write operation, move data from [buffer] to FDD_BUFF and then call save_chs_sector.
919
; For write operation, move data from [buffer] to FDD_BUFF and then call save_chs_sector.
915
        cmp     [.operation], 0
920
        cmp     [.operation], 0
916
        jz      .read
921
        jz      .read
917
        mov     esi, [buffer]
922
        mov     esi, [buffer]
918
        mov     edi, FDD_BUFF
923
        mov     edi, FDD_BUFF
919
        mov     ecx, 512/4
924
        mov     ecx, 512/4
920
        rep movsd
925
        rep movsd
921
        mov     [buffer], esi
926
        mov     [buffer], esi
922
        call    save_chs_sector
927
        call    save_chs_sector
923
        jmp     @f
928
        jmp     @f
924
.read:
929
.read:
925
        call    read_chs_sector
930
        call    read_chs_sector
926
        mov     esi, FDD_BUFF
931
        mov     esi, FDD_BUFF
927
        mov     edi, [buffer]
932
        mov     edi, [buffer]
928
        mov     ecx, 512/4
933
        mov     ecx, 512/4
929
        rep movsd
934
        rep movsd
930
        mov     [buffer], edi
935
        mov     [buffer], edi
931
@@:
936
@@:
932
; 4c. If there was an error, propagate it to the caller.
937
; 4c. If there was an error, propagate it to the caller.
933
        cmp     [FDC_Status], 0
938
        cmp     [FDC_Status], 0
934
        jnz     .fail
939
        jnz     .fail
935
; 4d. Otherwise, increment number of sectors processed and continue the loop.
940
; 4d. Otherwise, increment number of sectors processed and continue the loop.
936
        mov     eax, [numsectors_ptr]
941
        mov     eax, [numsectors_ptr]
937
        inc     dword [eax]
942
        inc     dword [eax]
938
        inc     dword [start_sector]
943
        inc     dword [start_sector]
939
        dec     [.sectors_todo]
944
        dec     [.sectors_todo]
940
        jnz     .operation_loop
945
        jnz     .operation_loop
941
; 5. Release the global lock and return with the correct status.
946
; 5. Release the global lock and return with the correct status.
942
        push    0
947
        push    0
943
.return:
948
.return:
944
        mov     ecx, floppy_mutex
949
        mov     ecx, floppy_mutex
945
        call    mutex_unlock
950
        call    mutex_unlock
946
        pop     eax
951
        pop     eax
947
        pop     edi esi ebx     ; restore used registers to be stdcall
952
        pop     edi esi ebx     ; restore used registers to be stdcall
948
        ret     ; this translates to leave/retn N and purges local variables
953
        ret     ; this translates to leave/retn N and purges local variables
949
.fail:
954
.fail:
950
        push    -1
955
        push    -1
951
        jmp     .return
956
        jmp     .return
952
.end_of_media:
957
.end_of_media:
953
        push    DISK_STATUS_END_OF_MEDIA
958
        push    DISK_STATUS_END_OF_MEDIA
954
        jmp     .return
959
        jmp     .return
955
endp
960
endp