Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1159 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
8
$Revision: 593 $
9
 
10
 
11
;**********************************************************
12
;  Непосредственная работа с контроллером гибкого диска
13
;**********************************************************
14
; Автор исходного текста  Кулаков Владимир Геннадьевич.
15
; Адаптация и доработка Mario79
16
 
17
;give_back_application_data:  ; переслать приложению
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
23
     xor ecx,ecx
24
     mov cx,128
25
     cld
26
     rep movsd
27
     ret
28
 
29
;take_data_from_application:   ; взять из приложени
30
;     mov esi,[TASK_BASE]
31
;     mov esi,[esi+TASKDATA.mem_start]
32
;     add esi,ecx
33
take_data_from_application_1:
34
     mov edi,FDD_BUFF   ;FDD_DataBuffer  ;0x40000
35
     xor ecx,ecx
36
     mov cx,128
37
     cld
38
     rep movsd
39
     ret
40
 
41
; Коды завершения операции с контроллером (FDC_Status)
42
FDC_Normal         equ 0 ;нормальное завершение
43
FDC_TimeOut        equ 1 ;ошибка тайм-аута
44
FDC_DiskNotFound   equ 2 ;в дисководе нет диска
45
FDC_TrackNotFound  equ 3 ;дорожка не найдена
46
FDC_SectorNotFound equ 4 ;сектор не найден
47
 
48
; Максимальные значения координат сектора (заданные
49
; значения соответствуют параметрам стандартного
50
; трехдюймового гибкого диска объемом 1,44 Мб)
51
MAX_Track   equ 79
52
MAX_Head    equ  1
53
MAX_Sector  equ 18
54
 
55
uglobal
56
; Счетчик тиков таймера
57
TickCounter dd ?
58
; Код завершения операции с контроллером НГМД
59
FDC_Status  DB ?
60
; Флаг прерывания от НГМД
61
FDD_IntFlag DB ?
62
; Момент начала последней операции с НГМД
63
FDD_Time    DD ?
64
; Номер дисковода
65
FDD_Type    db 0
66
; Координаты сектора
67
FDD_Track   DB ?
68
FDD_Head    DB ?
69
FDD_Sector  DB ?
70
 
71
; Блок результата операции
72
FDC_ST0 DB ?
73
FDC_ST1 DB ?
74
FDC_ST2 DB ?
75
FDC_C   DB ?
76
FDC_H   DB ?
77
FDC_R   DB ?
78
FDC_N   DB ?
79
; Счетчик повторения операции чтени
80
ReadRepCounter  DB ?
81
; Счетчик повторения операции рекалибровки
82
RecalRepCounter DB ?
83
endg
84
; Область памяти для хранения прочитанного сектора
85
;FDD_DataBuffer:  times 512 db 0   ;DB 512 DUP (?)
86
fdd_motor_status db 0
87
timer_fdd_motor  dd 0
88
 
89
;*************************************
90
;* ИНИЦИАЛИЗАЦИЯ РЕЖИМА ПДП ДЛЯ НГМД *
91
;*************************************
92
Init_FDC_DMA:
93
        pushad
94
        mov al,0
95
        out 0x0c,al     ; reset the flip-flop to a known state.
96
        mov al,6                ; mask channel 2 so we can reprogram it.
97
        out 0x0a,al
98
        mov al,[dmamode] ; 0x46 -> Read from floppy - 0x4A Write to floppy
99
        out 0x0b,al
100
        mov al,0
101
        out 0x0c,al     ; reset the flip-flop to a known state.
102
        mov eax,0xD000
103
        out 0x04,al     ; set the channel 2 starting address to 0
104
        shr eax,8
105
        out 0x04,al
106
        shr eax,8
107
        out 0x81,al
108
        mov al,0
109
        out 0x0c, al    ; reset flip-flop
110
        mov al, 0xff    ;set count (actual size -1)
111
        out 0x5, al
112
        mov al,0x1  ;[dmasize]       ;(0x1ff = 511 / 0x23ff =9215)
113
        out 0x5,al
114
        mov al,2
115
        out 0xa,al
116
        popad
117
        ret
118
 
119
;***********************************
120
;* ЗАПИСАТЬ БАЙТ В ПОРТ ДАННЫХ FDC *
121
;* Параметры:                      *
122
;* AL - выводимый байт.            *
123
;***********************************
124
FDCDataOutput:
125
;        pusha
126
        push eax ecx edx
127
        mov     AH,AL     ;запомнить байт в AH
128
; Сбросить переменную состояния контроллера
129
        mov     [FDC_Status],FDC_Normal
130
; Проверить готовность контроллера к приему данных
131
        mov     DX,3F4h   ;(порт состояния FDC)
132
        mov     ecx, 0x10000 ;установить счетчик тайм-аута
133
@@TestRS:
134
        in      AL,DX     ;прочитать регистр RS
135
        and     AL,0C0h   ;выделить разряды 6 и 7
136
        cmp     AL,80h    ;проверить разряды 6 и 7
137
        je      @@OutByteToFDC
138
        loop    @@TestRS
139
; Ошибка тайм-аута
140
        mov     [FDC_Status],FDC_TimeOut
141
        jmp @@End_5
142
; Вывести байт в порт данных
143
@@OutByteToFDC:
144
        inc     DX
145
        mov     AL,AH
146
        out     DX,AL
147
@@End_5:
148
;        popa
149
        pop edx ecx eax
150
        ret
151
 
152
;******************************************
153
;*   ПРОЧИТАТЬ БАЙТ ИЗ ПОРТА ДАННЫХ FDC   *
154
;* Процедура не имеет входных параметров. *
155
;* Выходные данные:                       *
156
;* AL - считанный байт.                   *
157
;******************************************
158
FDCDataInput:
159
        push    ECX
160
        push    DX
161
; Сбросить переменную состояния контроллера
162
        mov     [FDC_Status],FDC_Normal
163
; Проверить готовность контроллера к передаче данных
164
        mov     DX,3F4h   ;(порт состояния FDC)
165
        xor     CX,CX     ;установить счетчик тайм-аута
166
@@TestRS_1:
167
        in      AL,DX     ;прочитать регистр RS
168
        and     AL,0C0h   ;выдлить разряды 6 и 7
169
        cmp     AL,0C0h   ;проверить разряды 6 и 7
170
        je      @@GetByteFromFDC
171
        loop    @@TestRS_1
172
; Ошибка тайм-аута
173
        mov     [FDC_Status],FDC_TimeOut
174
        jmp @@End_6
175
; Ввести байт из порта данных
176
@@GetByteFromFDC:
177
        inc     DX
178
        in      AL,DX
179
@@End_6:  pop     DX
180
        pop     ECX
181
        ret
182
 
183
;*********************************************
184
;* ОБРАБОТЧИК ПРЕРЫВАНИЯ ОТ КОНТРОЛЛЕРА НГМД *
185
;*********************************************
186
FDCInterrupt:
187
; Установить флаг прерывани
188
        mov     [FDD_IntFlag],1
189
        ret
190
 
191
 
192
;******************************************
193
;* УСТАНОВИТЬ НОВЫЙ ОБРАБОТЧИК ПРЕРЫВАНИЙ *
194
;*             НГМД                       *
195
;******************************************
196
SetUserInterrupts:
197
         mov     [fdc_irq_func],FDCInterrupt
198
         ret
199
 
200
;*******************************************
201
;* ОЖИДАНИЕ ПРЕРЫВАНИЯ ОТ КОНТРОЛЛЕРА НГМД *
202
;*******************************************
203
WaitFDCInterrupt:
204
        pusha
205
; Сбросить байт состояния операции
206
        mov     [FDC_Status],FDC_Normal
207
; Сбросить флаг прерывани
208
        mov     [FDD_IntFlag],0
209
; Обнулить счетчик тиков
210
        mov     eax,[timer_ticks]
211
        mov     [TickCounter],eax
212
; Ожидать установки флага прерывания НГМД
213
@@TestRS_2:
214
        cmp     [FDD_IntFlag],0
215
        jnz     @@End_7           ;прерывание произошло
216
        call    change_task
217
        mov     eax,[timer_ticks]
218
        sub     eax,[TickCounter]
219
        cmp     eax,50  ;25   ;5 ;ожидать 5 тиков
220
        jb      @@TestRS_2
221
;        jl      @@TestRS_2
222
; Ошибка тайм-аута
223
        mov     [FDC_Status],FDC_TimeOut
224
;        mov   [flp_status],0
225
@@End_7:  popa
226
        ret
227
 
228
;*********************************
229
;* ВКЛЮЧИТЬ МОТОР ДИСКОВОДА "A:" *
230
;*********************************
231
FDDMotorON:
232
        pusha
233
;        cmp     [fdd_motor_status],1
234
;        je      fdd_motor_on
235
        mov     al,[flp_number]
236
        cmp     [fdd_motor_status],al
237
        je      fdd_motor_on
238
; Произвести сброс контроллера НГМД
239
        mov     DX,3F2h ;порт управления двигателями
240
        mov     AL,0
241
        out     DX,AL
242
; Выбрать и включить мотор дисковода
243
        cmp     [flp_number],1
244
        jne     FDDMotorON_B
245
;        call    FDDMotorOFF_B
246
        mov     AL,1Ch    ; Floppy A
247
        jmp     FDDMotorON_1
248
FDDMotorON_B:
249
;        call    FDDMotorOFF_A
250
        mov     AL,2Dh    ; Floppy B
251
FDDMotorON_1:
252
        out     DX,AL
253
; Обнулить счетчик тиков
254
        mov     eax,[timer_ticks]
255
        mov     [TickCounter],eax
256
; Ожидать 0,5 с
257
@@dT:
258
        call    change_task
259
        mov     eax,[timer_ticks]
260
        sub     eax,[TickCounter]
261
        cmp     eax,50  ;10
262
        jb      @@dT
263
        cmp     [flp_number],1
264
        jne     fdd_motor_on_B
265
        mov     [fdd_motor_status],1
266
        jmp     fdd_motor_on
267
fdd_motor_on_B:
268
        mov     [fdd_motor_status],2
269
fdd_motor_on:
270
        call    save_timer_fdd_motor
271
        popa
272
        ret
273
 
274
;*****************************************
275
;*  СОХРАНЕНИЕ УКАЗАТЕЛЯ ВРЕМЕНИ         *
276
;*****************************************
277
save_timer_fdd_motor:
278
        mov     eax,[timer_ticks]
279
        mov     [timer_fdd_motor],eax
280
        ret
281
 
282
;*****************************************
283
;*  ПРОВЕРКА ЗАДЕРЖКИ ВЫКЛЮЧЕНИЯ МОТОРА  *
284
;*****************************************
285
check_fdd_motor_status:
286
        cmp     [fdd_motor_status],0
287
        je      end_check_fdd_motor_status_1
288
        mov     eax,[timer_ticks]
289
        sub     eax,[timer_fdd_motor]
290
        cmp     eax,500
291
        jb      end_check_fdd_motor_status
292
        call    FDDMotorOFF
293
        mov     [fdd_motor_status],0
294
end_check_fdd_motor_status_1:
295
        mov     [flp_status],0
296
end_check_fdd_motor_status:
297
        ret
298
 
299
;**********************************
300
;* ВЫКЛЮЧИТЬ МОТОР ДИСКОВОДА      *
301
;**********************************
302
FDDMotorOFF:
303
        push    AX
304
        push    DX
305
        cmp     [flp_number],1
306
        jne     FDDMotorOFF_1
307
        call    FDDMotorOFF_A
308
        jmp     FDDMotorOFF_2
309
FDDMotorOFF_1:
310
        call    FDDMotorOFF_B
311
FDDMotorOFF_2:
312
        pop     DX
313
        pop     AX
314
        ; сброс флагов кеширования в связи с устареванием информации
315
        mov    [root_read],0
316
        mov    [flp_fat],0
317
        ret
318
 
319
FDDMotorOFF_A:
320
        mov     DX,3F2h ;порт управления двигателями
321
        mov     AL,0Ch  ; Floppy A
322
        out     DX,AL
323
        ret
324
 
325
FDDMotorOFF_B:
326
        mov     DX,3F2h ;порт управления двигателями
327
        mov     AL,5h  ; Floppy B
328
        out     DX,AL
329
        ret
330
 
331
;*******************************
332
;* РЕКАЛИБРОВКА ДИСКОВОДА "A:" *
333
;*******************************
334
RecalibrateFDD:
335
        pusha
336
        call    save_timer_fdd_motor
337
; Подать команду "Рекалибровка"
338
        mov     AL,07h
339
        call    FDCDataOutput
340
        mov     AL,00h
341
        call    FDCDataOutput
342
; Ожидать завершения операции
343
        call    WaitFDCInterrupt
344
;        cmp    [FDC_Status],0
345
;        je    no_fdc_status_error
346
;        mov   [flp_status],0
347
;no_fdc_status_error:
348
        call    save_timer_fdd_motor
349
        popa
350
        ret
351
 
352
;*****************************************************
353
;*                    ПОИСК ДОРОЖКИ                  *
354
;* Параметры передаются через глобальные переменные: *
355
;* FDD_Track - номер дорожки (0-79);                 *
356
;* FDD_Head - номер головки (0-1).                   *
357
;* Результат операции заносится в FDC_Status.        *
358
;*****************************************************
359
SeekTrack:
360
        pusha
361
        call    save_timer_fdd_motor
362
; Подать команду "Поиск"
363
        mov     AL,0Fh
364
        call    FDCDataOutput
365
        ; Передать байт номера головки/накопител
366
        mov     AL,[FDD_Head]
367
        shl     AL,2
368
        call    FDCDataOutput
369
        ; Передать байт номера дорожки
370
        mov     AL,[FDD_Track]
371
        call    FDCDataOutput
372
; Ожидать завершения операции
373
        call    WaitFDCInterrupt
374
        cmp     [FDC_Status],FDC_Normal
375
        jne     @@Exit
376
; Сохранить результат поиска
377
        mov     AL,08h
378
        call    FDCDataOutput
379
        call    FDCDataInput
380
        mov     [FDC_ST0],AL
381
        call    FDCDataInput
382
        mov     [FDC_C],AL
383
; Проверить результат поиска
384
        ; Поиск завершен?
385
        test    [FDC_ST0],100000b
386
        je      @@Err
387
        ; Заданный трек найден?
388
        mov     AL,[FDC_C]
389
        cmp     AL,[FDD_Track]
390
        jne     @@Err
391
        ; Номер головки совпадает с заданным?
392
        mov     AL,[FDC_ST0]
393
        and     AL,100b
394
        shr     AL,2
395
        cmp     AL,[FDD_Head]
396
        jne     @@Err
397
        ; Операция завершена успешно
398
        mov     [FDC_Status],FDC_Normal
399
        jmp @@Exit
400
@@Err:  ; Трек не найден
401
        mov     [FDC_Status],FDC_TrackNotFound
402
;        mov   [flp_status],0
403
@@Exit:
404
        call    save_timer_fdd_motor
405
        popa
406
        ret
407
 
408
;*******************************************************
409
;*               ЧТЕНИЕ СЕКТОРА ДАННЫХ                 *
410
;* Параметры передаются через глобальные переменные:   *
411
;* FDD_Track - номер дорожки (0-79);                   *
412
;* FDD_Head - номер головки (0-1);                     *
413
;* FDD_Sector - номер сектора (1-18).                  *
414
;* Результат операции заносится в FDC_Status.          *
415
;* В случае успешного выполнения операции чтения       *
416
;* содержимое сектора будет занесено в FDD_DataBuffer. *
417
;*******************************************************
418
ReadSector:
419
        pushad
420
        call    save_timer_fdd_motor
421
; Установить скорость передачи 500 Кбайт/с
422
        mov     AX,0
423
        mov     DX,03F7h
424
        out     DX,AL
425
; Инициализировать канал прямого доступа к памяти
426
        mov     [dmamode],0x46
427
        call    Init_FDC_DMA
428
; Подать команду "Чтение данных"
429
        mov     AL,0E6h  ;чтение в мультитрековом режиме
430
        call    FDCDataOutput
431
        mov     AL,[FDD_Head]
432
        shl     AL,2
433
        call    FDCDataOutput
434
        mov     AL,[FDD_Track]
435
        call    FDCDataOutput
436
        mov     AL,[FDD_Head]
437
        call    FDCDataOutput
438
        mov     AL,[FDD_Sector]
439
        call    FDCDataOutput
440
        mov     AL,2    ;код размера сектора (512 байт)
441
        call    FDCDataOutput
442
        mov     AL,18  ;+1; 3Fh  ;число секторов на дорожке
443
        call    FDCDataOutput
444
        mov     AL,1Bh  ;значение GPL
445
        call    FDCDataOutput
446
        mov     AL,0FFh ;значение DTL
447
        call    FDCDataOutput
448
; Ожидаем прерывание по завершении операции
449
        call    WaitFDCInterrupt
450
        cmp     [FDC_Status],FDC_Normal
451
        jne     @@Exit_1
452
; Считываем статус завершения операции
453
        call    GetStatusInfo
454
        test    [FDC_ST0],11011000b
455
        jnz     @@Err_1
456
        mov     [FDC_Status],FDC_Normal
457
        jmp @@Exit_1
458
@@Err_1:  mov     [FDC_Status],FDC_SectorNotFound
459
;        mov   [flp_status],0
460
@@Exit_1:
461
        call    save_timer_fdd_motor
462
        popad
463
        ret
464
 
465
;*******************************************************
466
;*   ЧТЕНИЕ СЕКТОРА (С ПОВТОРЕНИЕМ ОПЕРАЦИИ ПРИ СБОЕ)  *
467
;* Параметры передаются через глобальные переменные:   *
468
;* FDD_Track - номер дорожки (0-79);                   *
469
;* FDD_Head - номер головки (0-1);                     *
470
;* FDD_Sector - номер сектора (1-18).                  *
471
;* Результат операции заносится в FDC_Status.          *
472
;* В случае успешного выполнения операции чтения       *
473
;* содержимое сектора будет занесено в FDD_DataBuffer. *
474
;*******************************************************
475
ReadSectWithRetr:
476
        pusha
477
; Обнулить счетчик повторения операции рекалибровки
478
        mov     [RecalRepCounter],0
479
@@TryAgain:
480
; Обнулить счетчик повторения операции чтени
481
        mov     [ReadRepCounter],0
482
@@ReadSector_1:
483
        call    ReadSector
484
        cmp     [FDC_Status],0
485
        je      @@Exit_2
486
        cmp     [FDC_Status],1
487
        je      @@Err_3
488
        ; Троекратное повторение чтени
489
        inc     [ReadRepCounter]
490
        cmp     [ReadRepCounter],3
491
        jb      @@ReadSector_1
492
        ; Троекратное повторение рекалибровки
493
        call    RecalibrateFDD
494
        call    SeekTrack
495
        inc     [RecalRepCounter]
496
        cmp     [RecalRepCounter],3
497
        jb      @@TryAgain
498
;        mov   [flp_status],0
499
@@Exit_2:
500
        popa
501
        ret
502
@@Err_3:
503
        mov   [flp_status],0
504
        popa
505
        ret
506
 
507
;*******************************************************
508
;*               ЗАПИСЬ СЕКТОРА ДАННЫХ                 *
509
;* Параметры передаются через глобальные переменные:   *
510
;* FDD_Track - номер дорожки (0-79);                   *
511
;* FDD_Head - номер головки (0-1);                     *
512
;* FDD_Sector - номер сектора (1-18).                  *
513
;* Результат операции заносится в FDC_Status.          *
514
;* В случае успешного выполнения операции записи       *
515
;* содержимое FDD_DataBuffer будет занесено в сектор.  *
516
;*******************************************************
517
WriteSector:
518
        pushad
519
        call    save_timer_fdd_motor
520
; Установить скорость передачи 500 Кбайт/с
521
        mov     AX,0
522
        mov     DX,03F7h
523
        out     DX,AL
524
; Инициализировать канал прямого доступа к памяти
525
        mov     [dmamode],0x4A
526
        call    Init_FDC_DMA
527
; Подать команду "Запись данных"
528
        mov     AL,0xC5  ;0x45  ;запись в мультитрековом режиме
529
        call    FDCDataOutput
530
        mov     AL,[FDD_Head]
531
        shl     AL,2
532
        call    FDCDataOutput
533
        mov     AL,[FDD_Track]
534
        call    FDCDataOutput
535
        mov     AL,[FDD_Head]
536
        call    FDCDataOutput
537
        mov     AL,[FDD_Sector]
538
        call    FDCDataOutput
539
        mov     AL,2    ;код размера сектора (512 байт)
540
        call    FDCDataOutput
541
        mov     AL,18; 3Fh  ;число секторов на дорожке
542
        call    FDCDataOutput
543
        mov     AL,1Bh  ;значение GPL
544
        call    FDCDataOutput
545
        mov     AL,0FFh ;значение DTL
546
        call    FDCDataOutput
547
; Ожидаем прерывание по завершении операции
548
        call    WaitFDCInterrupt
549
        cmp     [FDC_Status],FDC_Normal
550
        jne     @@Exit_3
551
; Считываем статус завершения операции
552
        call    GetStatusInfo
553
        test    [FDC_ST0],11000000b  ;11011000b
554
        jnz     @@Err_2
555
        mov     [FDC_Status],FDC_Normal
556
        jmp @@Exit_3
557
@@Err_2:  mov     [FDC_Status],FDC_SectorNotFound
558
@@Exit_3:
559
        call    save_timer_fdd_motor
560
        popad
561
        ret
562
 
563
;*******************************************************
564
;*   ЗАПИСЬ СЕКТОРА (С ПОВТОРЕНИЕМ ОПЕРАЦИИ ПРИ СБОЕ)  *
565
;* Параметры передаются через глобальные переменные:   *
566
;* FDD_Track - номер дорожки (0-79);                   *
567
;* FDD_Head - номер головки (0-1);                     *
568
;* FDD_Sector - номер сектора (1-18).                  *
569
;* Результат операции заносится в FDC_Status.          *
570
;* В случае успешного выполнения операции записи       *
571
;* содержимое FDD_DataBuffer будет занесено в сектор.  *
572
;*******************************************************
573
WriteSectWithRetr:
574
        pusha
575
; Обнулить счетчик повторения операции рекалибровки
576
        mov     [RecalRepCounter],0
577
@@TryAgain_1:
578
; Обнулить счетчик повторения операции чтени
579
        mov     [ReadRepCounter],0
580
@@WriteSector_1:
581
        call    WriteSector
582
        cmp     [FDC_Status],0
583
        je      @@Exit_4
584
        cmp     [FDC_Status],1
585
        je      @@Err_4
586
        ; Троекратное повторение чтени
587
        inc     [ReadRepCounter]
588
        cmp     [ReadRepCounter],3
589
        jb      @@WriteSector_1
590
        ; Троекратное повторение рекалибровки
591
        call    RecalibrateFDD
592
        call    SeekTrack
593
        inc     [RecalRepCounter]
594
        cmp     [RecalRepCounter],3
595
        jb      @@TryAgain_1
596
@@Exit_4:
597
        popa
598
        ret
599
@@Err_4:
600
        mov   [flp_status],0
601
        popa
602
        ret
603
 
604
;*********************************************
605
;* ПОЛУЧИТЬ ИНФОРМАЦИЮ О РЕЗУЛЬТАТЕ ОПЕРАЦИИ *
606
;*********************************************
607
GetStatusInfo:
608
        push    AX
609
        call    FDCDataInput
610
        mov     [FDC_ST0],AL
611
        call    FDCDataInput
612
        mov     [FDC_ST1],AL
613
        call    FDCDataInput
614
        mov     [FDC_ST2],AL
615
        call    FDCDataInput
616
        mov     [FDC_C],AL
617
        call    FDCDataInput
618
        mov     [FDC_H],AL
619
        call    FDCDataInput
620
        mov     [FDC_R],AL
621
        call    FDCDataInput
622
        mov     [FDC_N],AL
623
        pop     AX
624
        ret
625