Subversion Repositories Kolibri OS

Rev

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

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