Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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