Subversion Repositories Kolibri OS

Rev

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

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