Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
431 serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
593 mikedld 8
$Revision: 996 $
9
 
10
 
87 mario79 11
;**********************************************************
12
;  Непосредственная работа с устройством СD (ATAPI)
13
;**********************************************************
618 mario79 14
; Автор части исходного текста Кулаков Владимир Геннадьевич
15
; Адаптация, доработка и разработка Mario79
87 mario79 16
 
996 serge 17
; Максимальное количество повторений операции чтени
543 spraid 18
MaxRetr equ 10
87 mario79 19
; Предельное время ожидания готовности к приему команды
20
; (в тиках)
21
BSYWaitTime equ 1000  ;2
538 spraid 22
NoTickWaitTime equ 0xfffff
758 mario79 23
 
87 mario79 24
;*************************************************
25
;*      ПОЛНОЕ ЧТЕНИЕ СЕКТОРА КОМПАКТ-ДИСКА      *
26
;* Считываются данные пользователя, информация   *
27
;* субканала и контрольная информация            *
28
;* Входные параметры передаются через глобальные *
29
;* перменные:                                    *
30
;* ChannelNumber - номер канала;                 *
31
;* DiskNumber - номер диска на канале;           *
32
;* CDSectorAddress - адрес считываемого сектора. *
33
;* Данные считывается в массив CDDataBuf.        *
34
;*************************************************
35
ReadCD:
585 mario79 36
	pusha
87 mario79 37
; Задать размер сектора
628 mario79 38
	mov	  [CDBlockSize],2048 ;2352
87 mario79 39
; Очистить буфер пакетной команды
585 mario79 40
	call  clear_packet_buffer
996 serge 41
; Сформировать пакетную команду для считывани
87 mario79 42
; сектора данных
585 mario79 43
	; Задать код команды Read CD
628 mario79 44
	mov	  [PacketCommand],byte 0x28  ;0xBE
585 mario79 45
	; Задать адрес сектора
628 mario79 46
	mov   AX,word [CDSectorAddress+2]
47
	xchg  AL,AH
48
	mov   word [PacketCommand+2],AX
49
	mov   AX,word [CDSectorAddress]
50
	xchg  AL,AH
51
	mov   word [PacketCommand+4],AX
87 mario79 52
;        mov   eax,[CDSectorAddress]
53
;        mov   [PacketCommand+2],eax
585 mario79 54
	; Задать количество считываемых секторов
628 mario79 55
	mov	  [PacketCommand+8],byte 1
585 mario79 56
	; Задать считывание данных в полном объеме
87 mario79 57
;        mov     [PacketCommand+9],byte 0xF8
58
; Подать команду
628 mario79 59
	call  SendPacketDatCommand
585 mario79 60
	popa
61
	ret
87 mario79 62
 
63
;********************************************
64
;*        ЧТЕНИЕ СЕКТОРА С ПОВТОРАМИ        *
65
;* Многократное повторение чтения при сбоях *
66
;********************************************
67
ReadCDWRetr:
585 mario79 68
;-----------------------------------------------------------
69
; input  : eax = block to read
70
;          ebx = destination
71
;-----------------------------------------------------------
72
    pushad
73
    mov   eax,[CDSectorAddress]
74
    mov   ebx,[CDDataBuf_pointer]
75
    call  cd_calculate_cache
76
    add   esi,8
77
    mov   edi,1
78
.hdreadcache:
79
;    cmp   dword [esi+4],0       ; empty
80
;    je    .nohdcache
81
    cmp   [esi],eax		; correct sector
82
    je	  .yeshdcache
83
.nohdcache:
84
    add   esi,8
85
    inc   edi
86
    dec   ecx
87
    jnz   .hdreadcache
88
    call  find_empty_slot_CD_cache	 ; ret in edi
89
 
90
    push  edi
91
    push  eax
92
    call  cd_calculate_cache_2
93
    shl   edi,11
94
    add   edi,eax
95
    mov   [CDDataBuf_pointer],edi
96
    pop   eax
97
    pop   edi
98
 
99
    call  ReadCDWRetr_1
628 mario79 100
    cmp   [DevErrorCode],0
101
    jne   .exit
102
 
585 mario79 103
    mov   [CDDataBuf_pointer],ebx
104
    call  cd_calculate_cache_1
105
    lea   esi,[edi*8+esi]
106
    mov   [esi],eax		; sector number
107
;    mov   dword [esi+4],1       ; hd read - mark as same as in hd
108
.yeshdcache:
109
    mov   esi,edi
110
    shl   esi,11    ;9
111
    push  eax
112
    call  cd_calculate_cache_2
113
    add   esi,eax
114
    pop   eax
115
    mov   edi,ebx   ;[CDDataBuf_pointer]
116
    mov   ecx,512   ;/4
117
    cld
118
    rep   movsd 		; move data
628 mario79 119
.exit:
585 mario79 120
    popad
121
    ret
122
 
123
ReadCDWRetr_1:
124
	pushad
125
 
87 mario79 126
; Цикл, пока команда не выполнена успешно или не
127
; исчерпано количество попыток
628 mario79 128
	mov	  ECX,MaxRetr
87 mario79 129
@@NextRetr:
130
; Подать команду
628 mario79 131
	call  ReadCD
132
	cmp	  [DevErrorCode],0
133
	je	  @@End_4
585 mario79 134
 
758 mario79 135
	or    ecx,ecx		;{SPraid.simba} (for cd load)
628 mario79 136
	jz    @@End_4
137
	dec   ecx
585 mario79 138
 
628 mario79 139
	cmp   [timer_ticks_enable],0
140
	jne   @f
141
	mov   eax,NoTickWaitTime
538 spraid 142
.wait:
628 mario79 143
	dec   eax
144
	cmp   eax,0
145
	je    @@NextRetr
146
	jmp	  .wait
538 spraid 147
@@:
87 mario79 148
; Задержка на 2,5 секунды
758 mario79 149
;       mov     EAX,[timer_ticks]
150
;       add     EAX,50  ;250
628 mario79 151
;@@Wait:
758 mario79 152
;       call    change_task
153
;       cmp     EAX,[timer_ticks]
154
;       ja      @@Wait
628 mario79 155
	loop  @@NextRetr
87 mario79 156
@@End_4:
585 mario79 157
	popad
158
	ret
87 mario79 159
 
160
 
161
;   Универсальные процедуры, обеспечивающие выполнение
162
;             пакетных команд в режиме PIO
163
 
164
; Максимально допустимое время ожидания реакции
165
; устройства на пакетную команду (в тиках)
166
MaxCDWaitTime equ 1000 ;200 ;10 секунд
167
 
168
; Область памяти для формирования пакетной команды
585 mario79 169
PacketCommand:	 rb 12	;DB 12 DUP (?)
87 mario79 170
; Область памяти для приема данных от дисковода
171
; Размер принимаемого блока данных в байтах
585 mario79 172
CDBlockSize	DW ?
87 mario79 173
; Адрес считываемого сектора данных
174
CDSectorAddress: DD ?
175
; Время начала очередной операции с диском
176
TickCounter_1 DD 0
177
; Время начала ожидания готовности устройства
178
WURStartTime DD 0
996 serge 179
; указатель буфера для считывани
87 mario79 180
CDDataBuf_pointer dd 0
181
 
182
;****************************************************
183
;*    ПОСЛАТЬ УСТРОЙСТВУ ATAPI ПАКЕТНУЮ КОМАНДУ,    *
184
;* ПРЕДУСМАТРИВАЮЩУЮ ПЕРЕДАЧУ ОДНОГО СЕКТОРА ДАННЫХ *
185
;*     РАЗМЕРОМ 2048 БАЙТ ОТ УСТРОЙСТВА К ХОСТУ     *
186
;* Входные параметры передаются через глобальные    *
187
;* перменные:                                       *
188
;* ChannelNumber - номер канала;                    *
189
;* DiskNumber - номер диска на канале;              *
190
;* PacketCommand - 12-байтный командный пакет;      *
191
;* CDBlockSize - размер принимаемого блока данных.  *
192
;****************************************************
193
SendPacketDatCommand:
585 mario79 194
	pushad
628 mario79 195
	mov   [DevErrorCode],0
87 mario79 196
; Задать режим CHS
585 mario79 197
	mov	[ATAAddressMode],0
87 mario79 198
; Послать ATA-команду передачи пакетной команды
585 mario79 199
	mov	[ATAFeatures],0
200
	mov	[ATASectorCount],0
201
	mov	[ATASectorNumber],0
202
	; Загрузить размер передаваемого блока
203
	mov	AX,[CDBlockSize]
204
	mov	[ATACylinder],AX
205
	mov	[ATAHead],0
206
	mov	[ATACommand],0A0h
207
	call	SendCommandToHDD_1
208
	cmp	[DevErrorCode],0 ;проверить код ошибки
209
	jne	@@End_8    ;закончить, сохранив код ошибки
87 mario79 210
 
211
; Ожидание готовности дисковода к приему
212
; пакетной команды
585 mario79 213
	mov	DX,[ATABasePortAddr]
214
	add	DX,7	 ;порт 1х7h
215
	mov	ecx,NoTickWaitTime
87 mario79 216
@@WaitDevice0:
585 mario79 217
	cmp	[timer_ticks_enable],0
218
	jne	@f
219
	dec	ecx
220
	cmp	ecx,0
221
	je	@@Err1_1
222
	jmp	.test
538 spraid 223
@@:
585 mario79 224
	call	change_task
225
	; Проверить время выполнения команды
226
	mov	EAX,[timer_ticks]
227
	sub	EAX,[TickCounter_1]
228
	cmp	EAX,BSYWaitTime
229
	ja	@@Err1_1   ;ошибка тайм-аута
230
	; Проверить готовность
538 spraid 231
.test:
585 mario79 232
	in	AL,DX
233
	test	AL,80h	 ;состояние сигнала BSY
234
	jnz	@@WaitDevice0
235
	test	AL,08h	 ;состояние сигнала DRQ
236
	jz	@@WaitDevice0
237
	test	AL,1	 ;состояние сигнала ERR
238
	jnz	@@Err6
87 mario79 239
; Послать пакетную команду
585 mario79 240
	cli
241
	mov	DX,[ATABasePortAddr]
242
	mov	AX,[PacketCommand]
243
	out	DX,AX
244
	mov	AX,[PacketCommand+2]
245
	out	DX,AX
246
	mov	AX,[PacketCommand+4]
247
	out	DX,AX
248
	mov	AX,[PacketCommand+6]
249
	out	DX,AX
250
	mov	AX,[PacketCommand+8]
251
	out	DX,AX
252
	mov	AX,[PacketCommand+10]
253
	out	DX,AX
254
	sti
87 mario79 255
; Ожидание готовности данных
585 mario79 256
	mov	DX,[ATABasePortAddr]
257
	add	DX,7   ;порт 1х7h
258
	mov	ecx,NoTickWaitTime
87 mario79 259
@@WaitDevice1:
585 mario79 260
	cmp	[timer_ticks_enable],0
261
	jne	@f
262
	dec	ecx
263
	cmp	ecx,0
264
	je	@@Err1_1
265
	jmp	.test_1
538 spraid 266
@@:
585 mario79 267
	call	change_task
268
	; Проверить время выполнения команды
269
	mov	EAX,[timer_ticks]
270
	sub	EAX,[TickCounter_1]
271
	cmp	EAX,MaxCDWaitTime
272
	ja	@@Err1_1   ;ошибка тайм-аута
273
	; Проверить готовность
538 spraid 274
.test_1:
585 mario79 275
	in	AL,DX
276
	test	AL,80h	 ;состояние сигнала BSY
277
	jnz	@@WaitDevice1
278
	test	AL,08h	 ;состояние сигнала DRQ
279
	jz	@@WaitDevice1
280
	test	AL,1	 ;состояние сигнала ERR
281
	jnz	@@Err6_temp
87 mario79 282
; Принять блок данных от контроллера
585 mario79 283
	mov	EDI,[CDDataBuf_pointer] ;0x7000  ;CDDataBuf
284
	; Загрузить адрес регистра данных контроллера
285
	mov	DX,[ATABasePortAddr] ;порт 1x0h
286
	; Загрузить в счетчик размер блока в байтах
287
	xor	ecx,ecx
288
	mov	CX,[CDBlockSize]
289
	; Вычислить размер блока в 16-разрядных словах
290
	shr	CX,1 ;разделить размер блока на 2
291
	; Принять блок данных
292
	cli
293
	cld
294
	rep	insw
295
	sti
296
	; Успешное завершение приема данных
297
	jmp @@End_8
87 mario79 298
 
299
; Записать код ошибки
300
@@Err1_1:
585 mario79 301
	mov	[DevErrorCode],1
302
	jmp @@End_8
87 mario79 303
@@Err6_temp:
585 mario79 304
	mov	[DevErrorCode],7
305
	jmp @@End_8
87 mario79 306
@@Err6:
585 mario79 307
	mov	[DevErrorCode],6
87 mario79 308
@@End_8:
585 mario79 309
	popad
310
	ret
87 mario79 311
 
312
 
313
 
314
;***********************************************
315
;*  ПОСЛАТЬ УСТРОЙСТВУ ATAPI ПАКЕТНУЮ КОМАНДУ, *
316
;*     НЕ ПРЕДУСМАТРИВАЮЩУЮ ПЕРЕДАЧИ ДАННЫХ    *
317
;* Входные параметры передаются через          *
318
;* глобальные перменные:                       *
319
;* ChannelNumber - номер канала;               *
320
;* DiskNumber - номер диска на канале;         *
321
;* PacketCommand - 12-байтный командный пакет. *
322
;***********************************************
323
SendPacketNoDatCommand:
585 mario79 324
	pushad
628 mario79 325
    mov   [DevErrorCode],0
87 mario79 326
; Задать режим CHS
585 mario79 327
	mov	[ATAAddressMode],0
87 mario79 328
; Послать ATA-команду передачи пакетной команды
585 mario79 329
	mov	[ATAFeatures],0
330
	mov	[ATASectorCount],0
331
	mov	[ATASectorNumber],0
332
	mov	[ATACylinder],0
333
	mov	[ATAHead],0
334
	mov	[ATACommand],0A0h
335
	call	SendCommandToHDD_1
336
	cmp	[DevErrorCode],0 ;проверить код ошибки
337
	jne	@@End_9  ;закончить, сохранив код ошибки
87 mario79 338
; Ожидание готовности дисковода к приему
339
; пакетной команды
585 mario79 340
	mov	DX,[ATABasePortAddr]
341
	add	DX,7   ;порт 1х7h
87 mario79 342
@@WaitDevice0_1:
585 mario79 343
	call	change_task
996 serge 344
	; Проверить время ожидани
585 mario79 345
	mov	EAX,[timer_ticks]
346
	sub	EAX,[TickCounter_1]
347
	cmp	EAX,BSYWaitTime
348
	ja	@@Err1_3   ;ошибка тайм-аута
349
	; Проверить готовность
350
	in	AL,DX
351
	test	AL,80h	 ;состояние сигнала BSY
352
	jnz	@@WaitDevice0_1
353
	test	AL,1	 ;состояние сигнала ERR
354
	jnz	@@Err6_1
355
	test	AL,08h	 ;состояние сигнала DRQ
356
	jz	@@WaitDevice0_1
87 mario79 357
; Послать пакетную команду
358
;        cli
585 mario79 359
	mov	DX,[ATABasePortAddr]
360
	mov	AX,word [PacketCommand]
361
	out	DX,AX
362
	mov	AX,word [PacketCommand+2]
363
	out	DX,AX
364
	mov	AX,word [PacketCommand+4]
365
	out	DX,AX
366
	mov	AX,word [PacketCommand+6]
367
	out	DX,AX
368
	mov	AX,word [PacketCommand+8]
369
	out	DX,AX
370
	mov	AX,word [PacketCommand+10]
371
	out	DX,AX
87 mario79 372
;        sti
618 mario79 373
    cmp [ignore_CD_eject_wait],1
628 mario79 374
    je	@@End_9
87 mario79 375
; Ожидание подтверждения приема команды
585 mario79 376
	mov	DX,[ATABasePortAddr]
377
	add	DX,7   ;порт 1х7h
87 mario79 378
@@WaitDevice1_1:
585 mario79 379
	call	change_task
380
	; Проверить время выполнения команды
381
	mov	EAX,[timer_ticks]
382
	sub	EAX,[TickCounter_1]
383
	cmp	EAX,MaxCDWaitTime
384
	ja	@@Err1_3   ;ошибка тайм-аута
385
	; Ожидать освобождения устройства
386
	in	AL,DX
387
	test	AL,80h	 ;состояние сигнала BSY
388
	jnz	@@WaitDevice1_1
389
	test	AL,1	 ;состояние сигнала ERR
390
	jnz	@@Err6_1
391
	test	AL,40h	 ;состояние сигнала DRDY
392
	jz	@@WaitDevice1_1
393
	jmp @@End_9
87 mario79 394
 
395
; Записать код ошибки
396
@@Err1_3:
585 mario79 397
	mov	[DevErrorCode],1
398
	jmp @@End_9
87 mario79 399
@@Err6_1:
585 mario79 400
	mov	[DevErrorCode],6
87 mario79 401
@@End_9:
585 mario79 402
	popad
403
	ret
87 mario79 404
 
405
;****************************************************
406
;*          ПОСЛАТЬ КОМАНДУ ЗАДАННОМУ ДИСКУ         *
407
;* Входные параметры передаются через глобальные    *
408
;* переменные:                                      *
409
;* ChannelNumber - номер канала (1 или 2);          *
410
;* DiskNumber - номер диска (0 или 1);              *
411
;* ATAFeatures - "особенности";                     *
412
;* ATASectorCount - количество секторов;            *
413
;* ATASectorNumber - номер начального сектора;      *
414
;* ATACylinder - номер начального цилиндра;         *
415
;* ATAHead - номер начальной головки;               *
416
;* ATAAddressMode - режим адресации (0-CHS, 1-LBA); *
417
;* ATACommand - код команды.                        *
418
;* После успешного выполнения функции:              *
419
;* в ATABasePortAddr - базовый адрес HDD;           *
420
;* в DevErrorCode - ноль.                           *
421
;* При возникновении ошибки в DevErrorCode будет    *
422
;* возвращен код ошибки.                            *
423
;****************************************************
424
SendCommandToHDD_1:
585 mario79 425
	pushad
628 mario79 426
    mov   [DevErrorCode],0
87 mario79 427
; Проверить значение кода режима
585 mario79 428
	cmp	[ATAAddressMode],1
429
	ja	@@Err2_4
87 mario79 430
; Проверить корректность номера канала
585 mario79 431
	mov	BX,[ChannelNumber]
432
	cmp	BX,1
433
	jb	@@Err3_4
434
	cmp	BX,2
435
	ja	@@Err3_4
87 mario79 436
; Установить базовый адрес
585 mario79 437
	dec	BX
438
	shl	BX,1
439
	movzx	ebx,bx
440
	mov	AX,[ebx+StandardATABases]
441
	mov	[ATABasePortAddr],AX
87 mario79 442
; Ожидание готовности HDD к приему команды
585 mario79 443
	; Выбрать нужный диск
444
	mov	DX,[ATABasePortAddr]
445
	add	DX,6	;адрес регистра головок
446
	mov	AL,[DiskNumber]
447
	cmp	AL,1	;проверить номера диска
448
	ja	@@Err4_4
449
	shl	AL,4
450
	or	AL,10100000b
451
	out	DX,AL
452
	; Ожидать, пока диск не будет готов
453
	inc	DX
454
	mov	eax,[timer_ticks]
455
	mov	[TickCounter_1],eax
456
	mov	ecx,NoTickWaitTime
87 mario79 457
@@WaitHDReady_2:
585 mario79 458
	cmp    [timer_ticks_enable],0
459
	jne    @f
460
	dec    ecx
461
	cmp    ecx,0
462
	je     @@Err1_4
463
	jmp    .test
538 spraid 464
@@:
585 mario79 465
	call	change_task
996 serge 466
	; Проверить время ожидани
585 mario79 467
	mov	eax,[timer_ticks]
468
	sub	eax,[TickCounter_1]
469
	cmp	eax,BSYWaitTime ;300    ;ожидать 3 сек.
470
	ja	@@Err1_4   ;ошибка тайм-аута
996 serge 471
	; Прочитать регистр состояни
538 spraid 472
.test:
585 mario79 473
	in	AL,DX
474
	; Проверить состояние сигнала BSY
475
	test	AL,80h
476
	jnz	@@WaitHDReady_2
477
	; Проверить состояние сигнала DRQ
478
	test	AL,08h
479
	jnz	@@WaitHDReady_2
538 spraid 480
 
87 mario79 481
; Загрузить команду в регистры контроллера
585 mario79 482
	cli
483
	mov	DX,[ATABasePortAddr]
484
	inc	DX	;регистр "особенностей"
485
	mov	AL,[ATAFeatures]
486
	out	DX,AL
487
	inc	DX	;счетчик секторов
488
	mov	AL,[ATASectorCount]
489
	out	DX,AL
490
	inc	DX	;регистр номера сектора
491
	mov	AL,[ATASectorNumber]
492
	out	DX,AL
493
	inc	DX	;номер цилиндра (младший байт)
494
	mov	AX,[ATACylinder]
495
	out	DX,AL
496
	inc	DX	;номер цилиндра (старший байт)
497
	mov	AL,AH
498
	out	DX,AL
499
	inc	DX	;номер головки/номер диска
500
	mov	AL,[DiskNumber]
501
	shl	AL,4
502
	cmp	[ATAHead],0Fh ;проверить номер головки
503
	ja	@@Err5_4
504
	or	AL,[ATAHead]
505
	or	AL,10100000b
506
	mov	AH,[ATAAddressMode]
507
	shl	AH,6
508
	or	AL,AH
509
	out	DX,AL
87 mario79 510
; Послать команду
585 mario79 511
	mov	AL,[ATACommand]
512
	inc	DX	;регистр команд
513
	out	DX,AL
514
	sti
87 mario79 515
; Сбросить признак ошибки
585 mario79 516
	mov	[DevErrorCode],0
517
	jmp @@End_10
87 mario79 518
; Записать код ошибки
519
@@Err1_4:
585 mario79 520
	mov	[DevErrorCode],1
521
	jmp @@End_10
87 mario79 522
@@Err2_4:
585 mario79 523
	mov	[DevErrorCode],2
524
	jmp @@End_10
87 mario79 525
@@Err3_4:
585 mario79 526
	mov	[DevErrorCode],3
527
	jmp @@End_10
87 mario79 528
@@Err4_4:
585 mario79 529
	mov	[DevErrorCode],4
530
	jmp @@End_10
87 mario79 531
@@Err5_4:
585 mario79 532
	mov	[DevErrorCode],5
87 mario79 533
; Завершение работы программы
534
@@End_10:
538 spraid 535
;        sti
585 mario79 536
	popad
537
	ret
538
 
87 mario79 539
;*************************************************
540
;*    ОЖИДАНИЕ ГОТОВНОСТИ УСТРОЙСТВА К РАБОТЕ    *
541
;* Входные параметры передаются через глобальные *
542
;* перменные:                                    *
543
;* ChannelNumber - номер канала;                 *
544
;* DiskNumber - номер диска на канале.           *
545
;*************************************************
546
WaitUnitReady:
585 mario79 547
	pusha
87 mario79 548
; Запомнить время начала операции
585 mario79 549
	mov	EAX,[timer_ticks]
550
	mov	[WURStartTime],EAX
87 mario79 551
; Очистить буфер пакетной команды
585 mario79 552
	call  clear_packet_buffer
87 mario79 553
; Сформировать команду TEST UNIT READY
585 mario79 554
	mov	[PacketCommand],word 00h
87 mario79 555
; ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ УСТРОЙСТВА
637 mario79 556
	mov	ecx,NoTickWaitTime
87 mario79 557
@@SendCommand:
585 mario79 558
	; Подать команду проверки готовности
559
	call	SendPacketNoDatCommand
637 mario79 560
	cmp	[timer_ticks_enable],0
561
	jne	@f
562
	cmp	[DevErrorCode],0
563
	je	@@End_11
564
	dec	ecx
565
	cmp	ecx,0
566
	je	.Error
567
	jmp	@@SendCommand
568
@@:
585 mario79 569
	call	change_task
570
	; Проверить код ошибки
571
	cmp	[DevErrorCode],0
572
	je	@@End_11
573
	; Проверить время ожидания готовности
574
	mov	EAX,[timer_ticks]
575
	sub	EAX,[WURStartTime]
576
	cmp	EAX,MaxCDWaitTime
577
	jb	@@SendCommand
637 mario79 578
.Error:
585 mario79 579
	; Ошибка тайм-аута
580
	mov	[DevErrorCode],1
87 mario79 581
@@End_11:
585 mario79 582
	popa
583
	ret
87 mario79 584
 
585
;*************************************************
585 mario79 586
;*            ЗАПРЕТИТЬ СМЕНУ ДИСКА              *
587
;* Входные параметры передаются через глобальные *
588
;* перменные:                                    *
589
;* ChannelNumber - номер канала;                 *
590
;* DiskNumber - номер диска на канале.           *
591
;*************************************************
592
prevent_medium_removal:
593
	pusha
594
; Очистить буфер пакетной команды
595
	call  clear_packet_buffer
596
; Задать код команды
597
	mov  [PacketCommand],byte 0x1E
598
; Задать код запрета
599
    mov  [PacketCommand+4],byte 11b
600
; Подать команду
601
	call SendPacketNoDatCommand
618 mario79 602
	mov  eax,ATAPI_IDE0_lock
603
	add  eax,[cdpos]
604
	dec  eax
605
	mov  [eax],byte 1
585 mario79 606
	popa
607
	ret
608
 
609
;*************************************************
610
;*            РАЗРЕШИТЬ СМЕНУ ДИСКА              *
611
;* Входные параметры передаются через глобальные *
612
;* перменные:                                    *
613
;* ChannelNumber - номер канала;                 *
614
;* DiskNumber - номер диска на канале.           *
618 mario79 615
;*************************************************
585 mario79 616
allow_medium_removal:
617
	pusha
618
; Очистить буфер пакетной команды
619
	call  clear_packet_buffer
620
; Задать код команды
621
	mov  [PacketCommand],byte 0x1E
622
; Задать код запрета
623
    mov  [PacketCommand+4],byte 00b
624
; Подать команду
625
	call SendPacketNoDatCommand
618 mario79 626
	mov  eax,ATAPI_IDE0_lock
627
	add  eax,[cdpos]
628
	dec  eax
629
	mov  [eax],byte 0
585 mario79 630
	popa
631
	ret
632
 
633
;*************************************************
87 mario79 634
;*         ЗАГРУЗИТЬ НОСИТЕЛЬ В ДИСКОВОД         *
635
;* Входные параметры передаются через глобальные *
636
;* перменные:                                    *
637
;* ChannelNumber - номер канала;                 *
638
;* DiskNumber - номер диска на канале.           *
639
;*************************************************
640
LoadMedium:
585 mario79 641
	pusha
87 mario79 642
; Очистить буфер пакетной команды
585 mario79 643
	call  clear_packet_buffer
87 mario79 644
; Сформировать команду START/STOP UNIT
585 mario79 645
	; Задать код команды
646
	mov	[PacketCommand],word 1Bh
996 serge 647
	; Задать операцию загрузки носител
585 mario79 648
	mov	[PacketCommand+4],word 00000011b
87 mario79 649
; Подать команду
585 mario79 650
	call	SendPacketNoDatCommand
651
	popa
652
	ret
87 mario79 653
 
654
;*************************************************
655
;*         ИЗВЛЕЧЬ НОСИТЕЛЬ ИЗ ДИСКОВОДА         *
656
;* Входные параметры передаются через глобальные *
657
;* перменные:                                    *
658
;* ChannelNumber - номер канала;                 *
659
;* DiskNumber - номер диска на канале.           *
660
;*************************************************
585 mario79 661
EjectMedium:
662
	pusha
87 mario79 663
; Очистить буфер пакетной команды
585 mario79 664
	call  clear_packet_buffer
87 mario79 665
; Сформировать команду START/STOP UNIT
585 mario79 666
	; Задать код команды
667
	mov	[PacketCommand],word 1Bh
996 serge 668
	; Задать операцию извлечения носител
585 mario79 669
	mov	[PacketCommand+4],word 00000010b
87 mario79 670
; Подать команду
585 mario79 671
	call	SendPacketNoDatCommand
672
	popa
673
	ret
87 mario79 674
 
675
;*************************************************
618 mario79 676
;* Проверить событие нажатия кнопки извлечения   *
677
;*                     диска                     *
87 mario79 678
;* Входные параметры передаются через глобальные *
679
;* переменные:                                   *
680
;* ChannelNumber - номер канала;                 *
681
;* DiskNumber - номер диска на канале.           *
682
;*************************************************
618 mario79 683
check_ATAPI_device_event:
585 mario79 684
	pusha
618 mario79 685
    mov  eax,[timer_ticks]
686
    sub  eax,[timer_ATAPI_check]
687
    cmp  eax,100
688
    jb	 .end_1
689
    mov  al,[DRIVE_DATA+1]
690
    and al,11b
691
    cmp al,10b
692
    jz	.ide3
693
.ide2_1:
694
    mov  al,[DRIVE_DATA+1]
695
    and al,1100b
696
    cmp al,1000b
697
    jz	.ide2
698
.ide1_1:
699
    mov  al,[DRIVE_DATA+1]
700
    and al,110000b
701
    cmp al,100000b
702
    jz	.ide1
703
.ide0_1:
704
    mov  al,[DRIVE_DATA+1]
705
    and al,11000000b
706
    cmp al,10000000b
707
    jz	.ide0
708
.end:
709
 
710
    sti
711
    mov  eax,[timer_ticks]
712
    mov  [timer_ATAPI_check],eax
713
.end_1:
714
	popa
715
	ret
716
 
717
.ide3:
718
    cli
719
    cmp  [ATAPI_IDE3_lock],1
720
    jne  .ide2_1
721
    cmp  [IDE_Channel_2],0
722
    jne  .ide1_1
723
    cmp  [cd_status],0
724
    jne  .end
725
	mov  [IDE_Channel_2],1
726
    call reserve_ok2
727
	mov  [ChannelNumber],2
728
	mov  [DiskNumber],1
729
	mov	 [cdpos],4
730
	call GetEvent_StatusNotification
731
	cmp  [CDDataBuf+4],byte 1
732
	je   .eject_ide3
733
	call syscall_cdaudio.free
734
    jmp  .ide2_1
735
.eject_ide3:
736
    call .eject
737
	call syscall_cdaudio.free
738
    jmp  .ide2_1
739
 
740
.ide2:
741
    cli
742
    cmp  [ATAPI_IDE2_lock],1
743
    jne  .ide1_1
744
    cmp  [IDE_Channel_2],0
745
    jne  .ide1_1
746
    cmp  [cd_status],0
747
    jne  .end
748
	mov  [IDE_Channel_2],1
749
    call  reserve_ok2
750
	mov  [ChannelNumber],2
751
	mov  [DiskNumber],0
752
	mov	[cdpos],3
753
	call GetEvent_StatusNotification
754
	cmp  [CDDataBuf+4],byte 1
755
	je   .eject_ide2
756
	call syscall_cdaudio.free
757
    jmp  .ide1_1
758
.eject_ide2:
759
    call .eject
760
	call syscall_cdaudio.free
761
    jmp  .ide1_1
762
 
763
.ide1:
764
    cli
765
    cmp  [ATAPI_IDE1_lock],1
766
    jne  .ide0_1
767
    cmp  [IDE_Channel_1],0
768
    jne  .end
769
    cmp  [cd_status],0
770
    jne  .end
771
	mov  [IDE_Channel_1],1
772
    call reserve_ok2
773
	mov  [ChannelNumber],1
774
	mov  [DiskNumber],1
775
	mov	[cdpos],2
776
	call GetEvent_StatusNotification
777
	cmp  [CDDataBuf+4],byte 1
778
	je   .eject_ide1
779
	call syscall_cdaudio.free
780
    jmp  .ide0_1
781
.eject_ide1:
782
    call .eject
783
	call syscall_cdaudio.free
784
    jmp  .ide0_1
785
 
786
.ide0:
787
    cli
788
    cmp  [ATAPI_IDE0_lock],1
789
    jne  .end
790
    cmp  [IDE_Channel_1],0
791
    jne  .end
792
    cmp  [cd_status],0
793
    jne  .end
794
	mov  [IDE_Channel_1],1
795
    call reserve_ok2
796
	mov  [ChannelNumber],1
797
	mov  [DiskNumber],0
798
	mov	[cdpos],1
799
	call GetEvent_StatusNotification
800
	cmp  [CDDataBuf+4],byte 1
801
	je   .eject_ide0
802
	call syscall_cdaudio.free
803
    jmp  .end
804
.eject_ide0:
805
    call .eject
806
	call syscall_cdaudio.free
807
    jmp  .end
808
 
809
.eject:
810
	call clear_CD_cache
811
	call allow_medium_removal
812
	mov  [ignore_CD_eject_wait],1
813
	call EjectMedium
814
	mov  [ignore_CD_eject_wait],0
815
	ret
816
 
817
timer_ATAPI_check dd 0
818
ATAPI_IDE0_lock db 0
819
ATAPI_IDE1_lock db 0
820
ATAPI_IDE2_lock db 0
821
ATAPI_IDE3_lock db 0
822
ignore_CD_eject_wait db 0
823
 
824
;*************************************************
825
;* Получить сообщение о событии или состоянии    *
826
;*                  устройства                   *
827
;* Входные параметры передаются через глобальные *
828
;* переменные:                                   *
829
;* ChannelNumber - номер канала;                 *
830
;* DiskNumber - номер диска на канале.           *
831
;*************************************************
832
GetEvent_StatusNotification:
833
	pusha
628 mario79 834
	mov	[CDDataBuf_pointer],CDDataBuf
87 mario79 835
; Очистить буфер пакетной команды
585 mario79 836
	call  clear_packet_buffer
618 mario79 837
; Задать код команды
628 mario79 838
	mov	[PacketCommand],byte 4Ah
618 mario79 839
	mov	[PacketCommand+1],byte 00000001b
840
; Задать запрос класса сообщений
841
	mov	[PacketCommand+4],byte 00010000b
628 mario79 842
; Размер выделенной области
843
	mov	[PacketCommand+7],byte 8h
844
	mov	[PacketCommand+8],byte 0h
87 mario79 845
; Подать команду
585 mario79 846
	call	SendPacketDatCommand
847
	popa
848
	ret
87 mario79 849
 
618 mario79 850
;*************************************************
758 mario79 851
; прочитать информацию из TOC
852
;* Входные параметры передаются через глобальные *
853
;* переменные:                                   *
854
;* ChannelNumber - номер канала;                 *
855
;* DiskNumber - номер диска на канале.           *
856
;*************************************************
857
Read_TOC:
858
	pusha
859
	mov	[CDDataBuf_pointer],CDDataBuf
860
; Очистить буфер пакетной команды
861
	call  clear_packet_buffer
862
; Сформировать пакетную команду для считывания
863
; сектора данных
864
	mov	  [PacketCommand],byte 0x43
865
	; Задать формат
866
	mov	  [PacketCommand+2],byte 1
867
; Размер выделенной области
868
	mov	[PacketCommand+7],byte 0xFF
869
	mov	[PacketCommand+8],byte 0h
870
; Подать команду
871
	call  SendPacketDatCommand
872
	popa
873
	ret
874
 
875
;*************************************************
618 mario79 876
;* ОПРЕДЕЛИТЬ ОБЩЕЕ КОЛИЧЕСТВО СЕКТОРОВ НА ДИСКЕ *
877
;* Входные параметры передаются через глобальные *
878
;* переменные:                                   *
879
;* ChannelNumber - номер канала;                 *
880
;* DiskNumber - номер диска на канале.           *
881
;*************************************************
882
;ReadCapacity:
628 mario79 883
;       pusha
618 mario79 884
;; Очистить буфер пакетной команды
628 mario79 885
;       call  clear_packet_buffer
618 mario79 886
;; Задать размер буфера в байтах
628 mario79 887
;       mov     [CDBlockSize],8
618 mario79 888
;; Сформировать команду READ CAPACITY
628 mario79 889
;       mov     [PacketCommand],word 25h
618 mario79 890
;; Подать команду
628 mario79 891
;       call    SendPacketDatCommand
892
;       popa
893
;       ret
618 mario79 894
 
585 mario79 895
clear_packet_buffer:
87 mario79 896
; Очистить буфер пакетной команды
585 mario79 897
	mov	[PacketCommand],dword 0
898
	mov	[PacketCommand+4],dword 0
899
	mov	[PacketCommand+8],dword 0
900
	ret