Subversion Repositories Kolibri OS

Rev

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

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