Subversion Repositories Kolibri OS

Rev

Rev 4115 | Rev 4695 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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