Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
425 victor 1
$Revision: 425 $
87 mario79 2
;**********************************************************
3
;  Непосредственная работа с устройством СD (ATAPI)
4
;**********************************************************
5
; Автор исходного текста  Кулаков Владимир Геннадьевич.
6
; Адаптация и доработка Mario79
7
 
8
;        Процедура для полного считывания всех
9
;           данных из сектора компакт-диска
10
; Автор текста программы Кулаков Владимир Геннадьевич.
11
 
12
 
13
; Максимальное количество повторений операции чтения
14
MaxRetr equ 3
15
; Предельное время ожидания готовности к приему команды
16
; (в тиках)
17
BSYWaitTime equ 1000  ;2
18
 
19
;*************************************************
20
;*      ПОЛНОЕ ЧТЕНИЕ СЕКТОРА КОМПАКТ-ДИСКА      *
21
;* Считываются данные пользователя, информация   *
22
;* субканала и контрольная информация            *
23
;* Входные параметры передаются через глобальные *
24
;* перменные:                                    *
25
;* ChannelNumber - номер канала;                 *
26
;* DiskNumber - номер диска на канале;           *
27
;* CDSectorAddress - адрес считываемого сектора. *
28
;* Данные считывается в массив CDDataBuf.        *
29
;*************************************************
30
ReadCD:
31
        pusha
32
; Задать размер сектора
33
        mov     [CDBlockSize],2048 ;2352
34
; Очистить буфер пакетной команды
35
        call  clear_packet_buffer
36
; Сформировать пакетную команду для считывания
37
; сектора данных
38
        ; Задать код команды Read CD
39
        mov     [PacketCommand],byte 0x28  ;0xBE
40
        ; Задать адрес сектора
41
        mov     AX,word [CDSectorAddress+2]
42
        xchg    AL,AH
43
        mov     word [PacketCommand+2],AX
44
        mov     AX,word [CDSectorAddress]
45
        xchg    AL,AH
46
        mov     word [PacketCommand+4],AX
47
;        mov   eax,[CDSectorAddress]
48
;        mov   [PacketCommand+2],eax
49
        ; Задать количество считываемых секторов
50
        mov     [PacketCommand+8],byte 1
51
        ; Задать считывание данных в полном объеме
52
;        mov     [PacketCommand+9],byte 0xF8
53
; Подать команду
54
        call    SendPacketDatCommand
55
;        call test_mario79
56
        popa
57
        ret
58
 
59
;********************************************
60
;*        ЧТЕНИЕ СЕКТОРА С ПОВТОРАМИ        *
61
;* Многократное повторение чтения при сбоях *
62
;********************************************
63
ReadCDWRetr:
64
        pusha
65
; Цикл, пока команда не выполнена успешно или не
66
; исчерпано количество попыток
67
        mov     ECX,MaxRetr
68
@@NextRetr:
69
; Подать команду
70
        call    ReadCD
71
        cmp     [DevErrorCode],0
72
        je      @@End_4
73
; Задержка на 2,5 секунды
74
        mov     EAX,[timer_ticks]
75
        add     EAX,250 ;50
76
@@Wait:
77
        call    change_task
78
        cmp     EAX,[timer_ticks]
79
        ja      @@Wait
80
        loop    @@NextRetr
81
;        call test_mario79
82
; Сообщение об ошибке
83
;        mov     SI,offset ErrS
84
;        call    FatalError
85
@@End_4:
86
        popa
87
        ret
88
 
89
 
90
;   Универсальные процедуры, обеспечивающие выполнение
91
;             пакетных команд в режиме PIO
92
;
93
; Автор текста программы Кулаков Владимир Геннадьевич.
94
 
95
; Максимально допустимое время ожидания реакции
96
; устройства на пакетную команду (в тиках)
97
MaxCDWaitTime equ 1000 ;200 ;10 секунд
98
 
99
; Область памяти для формирования пакетной команды
100
PacketCommand:   rb 12  ;DB 12 DUP (?)
101
; Область памяти для приема данных от дисковода
102
;CDDataBuf       DB 4096 DUP (0)
103
; Размер принимаемого блока данных в байтах
104
CDBlockSize     DW ?
105
; Адрес считываемого сектора данных
106
CDSectorAddress: DD ?
107
; Время начала очередной операции с диском
108
TickCounter_1 DD 0
109
; Время начала ожидания готовности устройства
110
WURStartTime DD 0
111
; указатель буфера для считывания
112
CDDataBuf_pointer dd 0
113
 
114
;****************************************************
115
;*    ПОСЛАТЬ УСТРОЙСТВУ ATAPI ПАКЕТНУЮ КОМАНДУ,    *
116
;* ПРЕДУСМАТРИВАЮЩУЮ ПЕРЕДАЧУ ОДНОГО СЕКТОРА ДАННЫХ *
117
;*     РАЗМЕРОМ 2048 БАЙТ ОТ УСТРОЙСТВА К ХОСТУ     *
118
;* Входные параметры передаются через глобальные    *
119
;* перменные:                                       *
120
;* ChannelNumber - номер канала;                    *
121
;* DiskNumber - номер диска на канале;              *
122
;* PacketCommand - 12-байтный командный пакет;      *
123
;* CDBlockSize - размер принимаемого блока данных.  *
124
;****************************************************
125
SendPacketDatCommand:
126
        pushad
127
; Задать режим CHS
128
        mov     [ATAAddressMode],0
129
; Послать ATA-команду передачи пакетной команды
130
        mov     [ATAFeatures],0
131
        mov     [ATASectorCount],0
132
        mov     [ATASectorNumber],0
133
        ; Загрузить размер передаваемого блока
134
        mov     AX,[CDBlockSize]
135
        mov     [ATACylinder],AX
136
        mov     [ATAHead],0
137
        mov     [ATACommand],0A0h
138
        call    SendCommandToHDD_1
139
;        call test_mario79
140
        cmp     [DevErrorCode],0 ;проверить код ошибки
141
        jne     @@End_8    ;закончить, сохранив код ошибки
142
 
143
; Ожидание готовности дисковода к приему
144
; пакетной команды
145
        mov     DX,[ATABasePortAddr]
146
        add     DX,7     ;порт 1х7h
147
@@WaitDevice0:
148
        call    change_task
149
        ; Проверить время выполнения команды
150
        mov     EAX,[timer_ticks]
151
        sub     EAX,[TickCounter_1]
152
        cmp     EAX,BSYWaitTime
153
        ja      @@Err1_1   ;ошибка тайм-аута
154
        ; Проверить готовность
155
        in      AL,DX
156
        test    AL,80h   ;состояние сигнала BSY
157
        jnz     @@WaitDevice0
158
        test    AL,1     ;состояние сигнала ERR
159
        jnz     @@Err6
160
        test    AL,08h   ;состояние сигнала DRQ
161
        jz      @@WaitDevice0
162
; Послать пакетную команду
163
        cli
164
        mov     DX,[ATABasePortAddr]
165
        mov     AX,[PacketCommand]
166
        out     DX,AX
167
        mov     AX,[PacketCommand+2]
168
        out     DX,AX
169
        mov     AX,[PacketCommand+4]
170
        out     DX,AX
171
        mov     AX,[PacketCommand+6]
172
        out     DX,AX
173
        mov     AX,[PacketCommand+8]
174
        out     DX,AX
175
        mov     AX,[PacketCommand+10]
176
        out     DX,AX
177
        sti
178
; Ожидание готовности данных
179
        mov     DX,[ATABasePortAddr]
180
        add     DX,7   ;порт 1х7h
181
@@WaitDevice1:
182
        call    change_task
183
        ; Проверить время выполнения команды
184
        mov     EAX,[timer_ticks]
185
        sub     EAX,[TickCounter_1]
186
        cmp     EAX,MaxCDWaitTime
187
        ja      @@Err1_1   ;ошибка тайм-аута
188
        ; Проверить готовность
189
        in      AL,DX
190
        test    AL,80h   ;состояние сигнала BSY
191
        jnz     @@WaitDevice1
192
        test    AL,1     ;состояние сигнала ERR
193
        jnz     @@Err6_temp
194
        test    AL,08h   ;состояние сигнала DRQ
195
        jz      @@WaitDevice1
196
        cli
197
; Принять блок данных от контроллера
198
        mov     EDI,[CDDataBuf_pointer] ;0x7000  ;CDDataBuf
199
        ; Загрузить адрес регистра данных контроллера
200
        mov     DX,[ATABasePortAddr] ;порт 1x0h
201
        ; Загрузить в счетчик размер блока в байтах
202
        mov     CX,[CDBlockSize]
203
        ; Вычислить размер блока в 16-разрядных словах
204
        shr     CX,1 ;разделить размер блока на 2
205
        ; Принять блок данных
206
        cld
207
        rep     insw
208
        sti
209
        ; Успешное завершение приема данных
210
        jmp @@End_8
211
 
212
; Записать код ошибки
213
@@Err1_1:
214
        mov     [DevErrorCode],1
215
        jmp @@End_8
216
@@Err6_temp:
217
        mov     [DevErrorCode],7
218
        jmp @@End_8
219
@@Err6:
220
        mov     [DevErrorCode],6
221
 
222
@@End_8:
223
        popad
224
        ret
225
 
226
 
227
 
228
;***********************************************
229
;*  ПОСЛАТЬ УСТРОЙСТВУ ATAPI ПАКЕТНУЮ КОМАНДУ, *
230
;*     НЕ ПРЕДУСМАТРИВАЮЩУЮ ПЕРЕДАЧИ ДАННЫХ    *
231
;* Входные параметры передаются через          *
232
;* глобальные перменные:                       *
233
;* ChannelNumber - номер канала;               *
234
;* DiskNumber - номер диска на канале;         *
235
;* PacketCommand - 12-байтный командный пакет. *
236
;***********************************************
237
SendPacketNoDatCommand:
238
        pushad
239
; Задать режим CHS
240
        mov     [ATAAddressMode],0
241
; Послать ATA-команду передачи пакетной команды
242
        mov     [ATAFeatures],0
243
        mov     [ATASectorCount],0
244
        mov     [ATASectorNumber],0
245
        mov     [ATACylinder],0
246
        mov     [ATAHead],0
247
        mov     [ATACommand],0A0h
248
        call    SendCommandToHDD_1
249
        cmp     [DevErrorCode],0 ;проверить код ошибки
250
        jne     @@End_9  ;закончить, сохранив код ошибки
251
; Ожидание готовности дисковода к приему
252
; пакетной команды
253
        mov     DX,[ATABasePortAddr]
254
        add     DX,7   ;порт 1х7h
255
@@WaitDevice0_1:
256
        call    change_task
257
        ; Проверить время ожидания
258
        mov     EAX,[timer_ticks]
259
        sub     EAX,[TickCounter_1]
260
        cmp     EAX,BSYWaitTime
261
        ja      @@Err1_3   ;ошибка тайм-аута
262
        ; Проверить готовность
263
        in      AL,DX
264
        test    AL,80h   ;состояние сигнала BSY
265
        jnz     @@WaitDevice0_1
266
        test    AL,1     ;состояние сигнала ERR
267
        jnz     @@Err6_1
268
        test    AL,08h   ;состояние сигнала DRQ
269
        jz      @@WaitDevice0_1
270
; Послать пакетную команду
271
;        cli
272
        mov     DX,[ATABasePortAddr]
273
        mov     AX,word [PacketCommand]
274
        out     DX,AX
275
        mov     AX,word [PacketCommand+2]
276
        out     DX,AX
277
        mov     AX,word [PacketCommand+4]
278
        out     DX,AX
279
        mov     AX,word [PacketCommand+6]
280
        out     DX,AX
281
        mov     AX,word [PacketCommand+8]
282
        out     DX,AX
283
        mov     AX,word [PacketCommand+10]
284
        out     DX,AX
285
;        sti
286
; Ожидание подтверждения приема команды
287
        mov     DX,[ATABasePortAddr]
288
        add     DX,7   ;порт 1х7h
289
@@WaitDevice1_1:
290
        call    change_task
291
        ; Проверить время выполнения команды
292
        mov     EAX,[timer_ticks]
293
        sub     EAX,[TickCounter_1]
294
        cmp     EAX,MaxCDWaitTime
295
        ja      @@Err1_3   ;ошибка тайм-аута
296
        ; Ожидать освобождения устройства
297
        in      AL,DX
298
        test    AL,80h   ;состояние сигнала BSY
299
        jnz     @@WaitDevice1_1
300
        test    AL,1     ;состояние сигнала ERR
301
        jnz     @@Err6_1
302
        test    AL,40h   ;состояние сигнала DRDY
303
        jz      @@WaitDevice1_1
304
        jmp @@End_9
305
 
306
; Записать код ошибки
307
@@Err1_3:
308
        mov     [DevErrorCode],1
309
        jmp @@End_9
310
@@Err6_1:
311
        mov     [DevErrorCode],6
312
@@End_9:
313
        popad
314
        ret
315
 
316
;****************************************************
317
;*          ПОСЛАТЬ КОМАНДУ ЗАДАННОМУ ДИСКУ         *
318
;* Входные параметры передаются через глобальные    *
319
;* переменные:                                      *
320
;* ChannelNumber - номер канала (1 или 2);          *
321
;* DiskNumber - номер диска (0 или 1);              *
322
;* ATAFeatures - "особенности";                     *
323
;* ATASectorCount - количество секторов;            *
324
;* ATASectorNumber - номер начального сектора;      *
325
;* ATACylinder - номер начального цилиндра;         *
326
;* ATAHead - номер начальной головки;               *
327
;* ATAAddressMode - режим адресации (0-CHS, 1-LBA); *
328
;* ATACommand - код команды.                        *
329
;* После успешного выполнения функции:              *
330
;* в ATABasePortAddr - базовый адрес HDD;           *
331
;* в DevErrorCode - ноль.                           *
332
;* При возникновении ошибки в DevErrorCode будет    *
333
;* возвращен код ошибки.                            *
334
;****************************************************
335
SendCommandToHDD_1:
336
        pushad
337
; Проверить значение кода режима
338
        cmp     [ATAAddressMode],1
339
        ja      @@Err2_4
340
; Проверить корректность номера канала
341
        mov     BX,[ChannelNumber]
342
        cmp     BX,1
343
        jb      @@Err3_4
344
        cmp     BX,2
345
        ja      @@Err3_4
346
; Установить базовый адрес
347
        dec     BX
348
        shl     BX,1
349
        movzx   ebx,bx
350
        mov     AX,[ebx+StandardATABases]
351
        mov     [ATABasePortAddr],AX
352
; Ожидание готовности HDD к приему команды
353
        ; Выбрать нужный диск
354
        mov     DX,[ATABasePortAddr]
355
        add     DX,6    ;адрес регистра головок
356
        mov     AL,[DiskNumber]
357
        cmp     AL,1    ;проверить номера диска
358
        ja      @@Err4_4
359
        shl     AL,4
360
        or      AL,10100000b
361
        out     DX,AL
362
        ; Ожидать, пока диск не будет готов
363
        inc     DX
364
;        mov  ecx,0xfff
365
        mov     eax,[timer_ticks]
366
        mov     [TickCounter_1],eax
367
@@WaitHDReady_2:
368
        call    change_task
369
        ; Проверить время ожидания
370
;        dec  ecx
371
;        cmp  ecx,0
372
;        je     @@Err1
373
        mov     eax,[timer_ticks]
374
        sub     eax,[TickCounter_1]
375
        cmp     eax,BSYWaitTime ;300    ;ожидать 3 сек.
376
        ja      @@Err1_4   ;ошибка тайм-аута
377
        ; Прочитать регистр состояния
378
        in      AL,DX
379
        ; Проверить состояние сигнала BSY
380
        test    AL,80h
381
        jnz     @@WaitHDReady_2
382
        ; Проверить состояние сигнала DRQ
383
        test    AL,08h
384
        jnz     @@WaitHDReady_2
385
; Загрузить команду в регистры контроллера
386
        cli
387
        mov     DX,[ATABasePortAddr]
388
        inc     DX      ;регистр "особенностей"
389
        mov     AL,[ATAFeatures]
390
        out     DX,AL
391
        inc     DX      ;счетчик секторов
392
        mov     AL,[ATASectorCount]
393
        out     DX,AL
394
        inc     DX      ;регистр номера сектора
395
        mov     AL,[ATASectorNumber]
396
        out     DX,AL
397
        inc     DX      ;номер цилиндра (младший байт)
398
        mov     AX,[ATACylinder]
399
        out     DX,AL
400
        inc     DX      ;номер цилиндра (старший байт)
401
        mov     AL,AH
402
        out     DX,AL
403
        inc     DX      ;номер головки/номер диска
404
        mov     AL,[DiskNumber]
405
        shl     AL,4
406
        cmp     [ATAHead],0Fh ;проверить номер головки
407
        ja      @@Err5_4
408
        or      AL,[ATAHead]
409
        or      AL,10100000b
410
        mov     AH,[ATAAddressMode]
411
        shl     AH,6
412
        or      AL,AH
413
        out     DX,AL
414
; Послать команду
415
        mov     AL,[ATACommand]
416
        inc     DX      ;регистр команд
417
        out     DX,AL
418
        sti
419
; Сбросить признак ошибки
420
        mov     [DevErrorCode],0
421
        jmp @@End_10
422
; Записать код ошибки
423
@@Err1_4:
424
        mov     [DevErrorCode],1
425
        jmp @@End_10
426
@@Err2_4:
427
        mov     [DevErrorCode],2
428
        jmp @@End_10
429
@@Err3_4:
430
        mov     [DevErrorCode],3
431
        jmp @@End_10
432
@@Err4_4:
433
        mov     [DevErrorCode],4
434
        jmp @@End_10
435
@@Err5_4:
436
        mov     [DevErrorCode],5
437
; Завершение работы программы
438
@@End_10:
439
        sti
440
        popad
441
        ret
442
 
443
;*************************************************
444
;*    ОЖИДАНИЕ ГОТОВНОСТИ УСТРОЙСТВА К РАБОТЕ    *
445
;* Входные параметры передаются через глобальные *
446
;* перменные:                                    *
447
;* ChannelNumber - номер канала;                 *
448
;* DiskNumber - номер диска на канале.           *
449
;*************************************************
450
WaitUnitReady:
451
        pusha
452
; Запомнить время начала операции
453
        mov     EAX,[timer_ticks]
454
        mov     [WURStartTime],EAX
455
; Очистить буфер пакетной команды
456
        call  clear_packet_buffer
457
; Сформировать команду TEST UNIT READY
458
        mov     [PacketCommand],word 00h
459
; ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ УСТРОЙСТВА
460
@@SendCommand:
461
        ; Подать команду проверки готовности
462
        call    SendPacketNoDatCommand
463
        call    change_task
464
        ; Проверить код ошибки
465
        cmp     [DevErrorCode],0
466
        je      @@End_11
467
        ; Проверить время ожидания готовности
468
        mov     EAX,[timer_ticks]
469
        sub     EAX,[WURStartTime]
470
        cmp     EAX,MaxCDWaitTime
471
        jb      @@SendCommand
472
        ; Ошибка тайм-аута
473
        mov     [DevErrorCode],1
474
@@End_11:
475
        popa
476
        ret
477
 
478
 
479
;*************************************************
480
;*         ЗАГРУЗИТЬ НОСИТЕЛЬ В ДИСКОВОД         *
481
;* Входные параметры передаются через глобальные *
482
;* перменные:                                    *
483
;* ChannelNumber - номер канала;                 *
484
;* DiskNumber - номер диска на канале.           *
485
;*************************************************
486
LoadMedium:
487
        pusha
488
; Очистить буфер пакетной команды
489
        call  clear_packet_buffer
490
; Сформировать команду START/STOP UNIT
491
        ; Задать код команды
492
        mov     [PacketCommand],word 1Bh
493
        ; Задать операцию загрузки носителя
494
        mov     [PacketCommand+4],word 00000011b
495
; Подать команду
496
        call    SendPacketNoDatCommand
497
        popa
498
        ret
499
 
500
;*************************************************
501
;*         ИЗВЛЕЧЬ НОСИТЕЛЬ ИЗ ДИСКОВОДА         *
502
;* Входные параметры передаются через глобальные *
503
;* перменные:                                    *
504
;* ChannelNumber - номер канала;                 *
505
;* DiskNumber - номер диска на канале.           *
506
;*************************************************
507
UnloadMedium:
508
        pusha
509
; Очистить буфер пакетной команды
510
        call  clear_packet_buffer
511
; Сформировать команду START/STOP UNIT
512
        ; Задать код команды
513
        mov     [PacketCommand],word 1Bh
514
        ; Задать операцию извлечения носителя
515
        mov     [PacketCommand+4],word 00000010b
516
; Подать команду
517
        call    SendPacketNoDatCommand
518
        popa
519
        ret
520
 
521
;*************************************************
522
;* ОПРЕДЕЛИТЬ ОБЩЕЕ КОЛИЧЕСТВО СЕКТОРОВ НА ДИСКЕ *
523
;* Входные параметры передаются через глобальные *
524
;* переменные:                                   *
525
;* ChannelNumber - номер канала;                 *
526
;* DiskNumber - номер диска на канале.           *
527
;*************************************************
528
ReadCapacity:
529
        pusha
530
; Очистить буфер пакетной команды
531
        call  clear_packet_buffer
532
; Задать размер буфера в байтах
533
        mov     [CDBlockSize],8
534
; Сформировать команду READ CAPACITY
535
        mov     [PacketCommand],word 25h
536
; Подать команду
537
        call    SendPacketDatCommand
538
        popa
539
        ret
540
 
541
clear_packet_buffer:
542
; Очистить буфер пакетной команды
543
        mov     [PacketCommand],dword 0
544
        mov     [PacketCommand+4],dword 0
545
        mov     [PacketCommand+8],dword 0
546
        ret
547