Subversion Repositories Kolibri OS

Rev

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

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