Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 4428 → Rev 4429

/kernel/branches/kolibri-process/blkdev/cd_drv.inc
0,0 → 1,953
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision: 3742 $
 
 
;**********************************************************
; Непосредственная работа с устройством СD (ATAPI)
;**********************************************************
; Автор части исходного текста Кулаков Владимир Геннадьевич
; Адаптация, доработка и разработка Mario79,<Lrz>
 
; Максимальное количество повторений операции чтения
MaxRetr equ 10
; Предельное время ожидания готовности к приему команды
; (в тиках)
BSYWaitTime equ 1000 ;2
NoTickWaitTime equ 0xfffff
CDBlockSize equ 2048
;********************************************
;* ЧТЕНИЕ СЕКТОРА С ПОВТОРАМИ *
;* Многократное повторение чтения при сбоях *
;********************************************
ReadCDWRetr:
;-----------------------------------------------------------
; input : eax = block to read
; ebx = destination
;-----------------------------------------------------------
pushad
mov eax, [CDSectorAddress]
mov ebx, [CDDataBuf_pointer]
call cd_calculate_cache
xor edi, edi
add esi, 8
inc edi
.hdreadcache:
; cmp dword [esi+4],0 ; empty
; je .nohdcache
cmp [esi], eax ; correct sector
je .yeshdcache
.nohdcache:
add esi, 8
inc edi
dec ecx
jnz .hdreadcache
call find_empty_slot_CD_cache ; ret in edi
 
push edi
push eax
call cd_calculate_cache_2
shl edi, 11
add edi, eax
mov [CDDataBuf_pointer], edi
pop eax
pop edi
 
call ReadCDWRetr_1
cmp [DevErrorCode], 0
jne .exit
 
mov [CDDataBuf_pointer], ebx
call cd_calculate_cache_1
lea esi, [edi*8+esi]
mov [esi], eax ; sector number
; mov dword [esi+4],1 ; hd read - mark as same as in hd
.yeshdcache:
mov esi, edi
shl esi, 11;9
push eax
call cd_calculate_cache_2
add esi, eax
pop eax
mov edi, ebx;[CDDataBuf_pointer]
mov ecx, 512;/4
cld
rep movsd ; move data
.exit:
popad
ret
 
ReadCDWRetr_1:
pushad
 
; Цикл, пока команда не выполнена успешно или не
; исчерпано количество попыток
mov ECX, MaxRetr
@@NextRetr:
; Подать команду
;*************************************************
;* ПОЛНОЕ ЧТЕНИЕ СЕКТОРА КОМПАКТ-ДИСКА *
;* Считываются данные пользователя, информация *
;* субканала и контрольная информация *
;* Входные параметры передаются через глобальные *
;* перменные: *
;* ChannelNumber - номер канала; *
;* DiskNumber - номер диска на канале; *
;* CDSectorAddress - адрес считываемого сектора. *
;* Данные считывается в массив CDDataBuf. *
;*************************************************
;ReadCD:
push ecx
; pusha
; Задать размер сектора
; mov [CDBlockSize],2048 ;2352
; Очистить буфер пакетной команды
call clear_packet_buffer
; Сформировать пакетную команду для считывания
; сектора данных
; Задать код команды Read CD
mov [PacketCommand], byte 0x28;0xBE
; Задать адрес сектора
mov AX, word [CDSectorAddress+2]
xchg AL, AH
mov word [PacketCommand+2], AX
mov AX, word [CDSectorAddress]
xchg AL, AH
mov word [PacketCommand+4], AX
; mov eax,[CDSectorAddress]
; mov [PacketCommand+2],eax
; Задать количество считываемых секторов
mov [PacketCommand+8], byte 1
; Задать считывание данных в полном объеме
; mov [PacketCommand+9],byte 0xF8
; Подать команду
call SendPacketDatCommand
pop ecx
; ret
 
; cmp [DevErrorCode],0
test eax, eax
jz @@End_4
 
or ecx, ecx ;{SPraid.simba} (for cd load)
jz @@End_4
dec ecx
 
cmp [timer_ticks_enable], 0
jne @f
mov eax, NoTickWaitTime
.wait:
dec eax
; test eax,eax
jz @@NextRetr
jmp .wait
@@:
; Задержка на 2,5 секунды
; mov EAX,[timer_ticks]
; add EAX,50 ;250
;@@Wait:
; call change_task
; cmp EAX,[timer_ticks]
; ja @@Wait
loop @@NextRetr
@@End_4:
mov dword [DevErrorCode], eax
popad
ret
 
 
; Универсальные процедуры, обеспечивающие выполнение
; пакетных команд в режиме PIO
 
; Максимально допустимое время ожидания реакции
; устройства на пакетную команду (в тиках)
 
MaxCDWaitTime equ 1000 ;200 ;10 секунд
uglobal
; Область памяти для формирования пакетной команды
PacketCommand:
rb 12 ;DB 12 DUP (?)
; Область памяти для приема данных от дисковода
;CDDataBuf DB 4096 DUP (0)
; Размер принимаемого блока данных в байтах
;CDBlockSize DW ?
; Адрес считываемого сектора данных
CDSectorAddress:
DD ?
; Время начала очередной операции с диском
TickCounter_1 DD 0
; Время начала ожидания готовности устройства
WURStartTime DD 0
; указатель буфера для считывания
CDDataBuf_pointer dd 0
endg
;****************************************************
;* ПОСЛАТЬ УСТРОЙСТВУ ATAPI ПАКЕТНУЮ КОМАНДУ, *
;* ПРЕДУСМАТРИВАЮЩУЮ ПЕРЕДАЧУ ОДНОГО СЕКТОРА ДАННЫХ *
;* РАЗМЕРОМ 2048 БАЙТ ОТ УСТРОЙСТВА К ХОСТУ *
;* Входные параметры передаются через глобальные *
;* перменные: *
;* ChannelNumber - номер канала; *
;* DiskNumber - номер диска на канале; *
;* PacketCommand - 12-байтный командный пакет; *
;* CDBlockSize - размер принимаемого блока данных. *
; return eax DevErrorCode
;****************************************************
SendPacketDatCommand:
xor eax, eax
; mov byte [DevErrorCode],al
; Задать режим CHS
mov byte [ATAAddressMode], al
; Послать ATA-команду передачи пакетной команды
mov byte [ATAFeatures], al
mov byte [ATASectorCount], al
mov byte [ATASectorNumber], al
; Загрузить размер передаваемого блока
mov [ATAHead], al
; mov AX,[CDBlockSize]
mov [ATACylinder], CDBlockSize
mov [ATACommand], 0A0h
call SendCommandToHDD_1
test eax, eax
; cmp [DevErrorCode],0 ;проверить код ошибки
jnz @@End_8 ;закончить, сохранив код ошибки
 
; Ожидание готовности дисковода к приему
; пакетной команды
mov DX, [ATABasePortAddr]
add DX, 7 ;порт 1х7h
mov ecx, NoTickWaitTime
@@WaitDevice0:
cmp [timer_ticks_enable], 0
jne @f
dec ecx
; test ecx,ecx
jz @@Err1_1
jmp .test
@@:
call change_task
; Проверить время выполнения команды
mov EAX, [timer_ticks]
sub EAX, [TickCounter_1]
cmp EAX, BSYWaitTime
ja @@Err1_1 ;ошибка тайм-аута
; Проверить готовность
.test:
in AL, DX
test AL, 80h ;состояние сигнала BSY
jnz @@WaitDevice0
test AL, 1 ;состояние сигнала ERR
jnz @@Err6
test AL, 08h ;состояние сигнала DRQ
jz @@WaitDevice0
; Послать пакетную команду
cli
mov DX, [ATABasePortAddr]
mov AX, [PacketCommand]
out DX, AX
mov AX, [PacketCommand+2]
out DX, AX
mov AX, [PacketCommand+4]
out DX, AX
mov AX, [PacketCommand+6]
out DX, AX
mov AX, [PacketCommand+8]
out DX, AX
mov AX, [PacketCommand+10]
out DX, AX
sti
; Ожидание готовности данных
mov DX, [ATABasePortAddr]
add DX, 7 ;порт 1х7h
mov ecx, NoTickWaitTime
@@WaitDevice1:
cmp [timer_ticks_enable], 0
jne @f
dec ecx
; test ecx,ecx
jz @@Err1_1
jmp .test_1
@@:
call change_task
; Проверить время выполнения команды
mov EAX, [timer_ticks]
sub EAX, [TickCounter_1]
cmp EAX, MaxCDWaitTime
ja @@Err1_1 ;ошибка тайм-аута
; Проверить готовность
.test_1:
in AL, DX
test AL, 80h ;состояние сигнала BSY
jnz @@WaitDevice1
test AL, 1 ;состояние сигнала ERR
jnz @@Err6_temp
test AL, 08h ;состояние сигнала DRQ
jz @@WaitDevice1
; Принять блок данных от контроллера
mov EDI, [CDDataBuf_pointer];0x7000 ;CDDataBuf
; Загрузить адрес регистра данных контроллера
mov DX, [ATABasePortAddr];порт 1x0h
; Загрузить в счетчик размер блока в байтах
xor ecx, ecx
mov CX, CDBlockSize
; Вычислить размер блока в 16-разрядных словах
shr CX, 1;разделить размер блока на 2
; Принять блок данных
cli
cld
rep insw
sti
; Успешное завершение приема данных
@@End_8:
xor eax, eax
ret
 
; Записать код ошибки
@@Err1_1:
xor eax, eax
inc eax
ret
; mov [DevErrorCode],1
; ret
@@Err6_temp:
mov eax, 7
ret
; mov [DevErrorCode],7
; ret
@@Err6:
mov eax, 6
ret
; mov [DevErrorCode],6
;@@End_8:
; ret
 
 
 
;***********************************************
;* ПОСЛАТЬ УСТРОЙСТВУ ATAPI ПАКЕТНУЮ КОМАНДУ, *
;* НЕ ПРЕДУСМАТРИВАЮЩУЮ ПЕРЕДАЧИ ДАННЫХ *
;* Входные параметры передаются через *
;* глобальные перменные: *
;* ChannelNumber - номер канала; *
;* DiskNumber - номер диска на канале; *
;* PacketCommand - 12-байтный командный пакет. *
;***********************************************
SendPacketNoDatCommand:
pushad
xor eax, eax
; mov byte [DevErrorCode],al
; Задать режим CHS
mov byte [ATAAddressMode], al
; Послать ATA-команду передачи пакетной команды
mov byte [ATAFeatures], al
mov byte [ATASectorCount], al
mov byte [ATASectorNumber], al
mov word [ATACylinder], ax
mov byte [ATAHead], al
mov [ATACommand], 0A0h
call SendCommandToHDD_1
; cmp [DevErrorCode],0 ;проверить код ошибки
test eax, eax
jnz @@End_9 ;закончить, сохранив код ошибки
; Ожидание готовности дисковода к приему
; пакетной команды
mov DX, [ATABasePortAddr]
add DX, 7 ;порт 1х7h
@@WaitDevice0_1:
call change_task
; Проверить время ожидания
mov EAX, [timer_ticks]
sub EAX, [TickCounter_1]
cmp EAX, BSYWaitTime
ja @@Err1_3 ;ошибка тайм-аута
; Проверить готовность
in AL, DX
test AL, 80h ;состояние сигнала BSY
jnz @@WaitDevice0_1
test AL, 1 ;состояние сигнала ERR
jnz @@Err6_1
test AL, 08h ;состояние сигнала DRQ
jz @@WaitDevice0_1
; Послать пакетную команду
; cli
mov DX, [ATABasePortAddr]
mov AX, word [PacketCommand]
out DX, AX
mov AX, word [PacketCommand+2]
out DX, AX
mov AX, word [PacketCommand+4]
out DX, AX
mov AX, word [PacketCommand+6]
out DX, AX
mov AX, word [PacketCommand+8]
out DX, AX
mov AX, word [PacketCommand+10]
out DX, AX
; sti
cmp [ignore_CD_eject_wait], 1
je @@clear_DEC
; Ожидание подтверждения приема команды
mov DX, [ATABasePortAddr]
add DX, 7 ;порт 1х7h
@@WaitDevice1_1:
call change_task
; Проверить время выполнения команды
mov EAX, [timer_ticks]
sub EAX, [TickCounter_1]
cmp EAX, MaxCDWaitTime
ja @@Err1_3 ;ошибка тайм-аута
; Ожидать освобождения устройства
in AL, DX
test AL, 80h ;состояние сигнала BSY
jnz @@WaitDevice1_1
test AL, 1 ;состояние сигнала ERR
jnz @@Err6_1
test AL, 40h ;состояние сигнала DRDY
jz @@WaitDevice1_1
@@clear_DEC:
and [DevErrorCode], 0
popad
ret
; Записать код ошибки
@@Err1_3:
xor eax, eax
inc eax
jmp @@End_9
@@Err6_1:
mov eax, 6
@@End_9:
mov [DevErrorCode], eax
popad
ret
 
;****************************************************
;* ПОСЛАТЬ КОМАНДУ ЗАДАННОМУ ДИСКУ *
;* Входные параметры передаются через глобальные *
;* переменные: *
;* ChannelNumber - номер канала (1 или 2); *
;* DiskNumber - номер диска (0 или 1); *
;* ATAFeatures - "особенности"; *
;* ATASectorCount - количество секторов; *
;* ATASectorNumber - номер начального сектора; *
;* ATACylinder - номер начального цилиндра; *
;* ATAHead - номер начальной головки; *
;* ATAAddressMode - режим адресации (0-CHS, 1-LBA); *
;* ATACommand - код команды. *
;* После успешного выполнения функции: *
;* в ATABasePortAddr - базовый адрес HDD; *
;* в DevErrorCode - ноль. *
;* При возникновении ошибки в DevErrorCode будет *
;* возвращен код ошибки в eax *
;****************************************************
SendCommandToHDD_1:
; pushad
; mov [DevErrorCode],0 not need
; Проверить значение кода режима
cmp [ATAAddressMode], 1
ja @@Err2_4
; Проверить корректность номера канала
mov BX, [ChannelNumber]
cmp BX, 1
jb @@Err3_4
cmp BX, 2
ja @@Err3_4
; Установить базовый адрес
dec BX
shl BX, 1
movzx ebx, bx
mov AX, [ebx+StandardATABases]
mov [ATABasePortAddr], AX
; Ожидание готовности HDD к приему команды
; Выбрать нужный диск
mov DX, [ATABasePortAddr]
add DX, 6 ;адрес регистра головок
mov AL, [DiskNumber]
cmp AL, 1 ;проверить номера диска
ja @@Err4_4
shl AL, 4
or AL, 10100000b
out DX, AL
; Ожидать, пока диск не будет готов
inc DX
mov eax, [timer_ticks]
mov [TickCounter_1], eax
mov ecx, NoTickWaitTime
@@WaitHDReady_2:
cmp [timer_ticks_enable], 0
jne @f
dec ecx
; test ecx,ecx
jz @@Err1_4
jmp .test
@@:
call change_task
; Проверить время ожидания
mov eax, [timer_ticks]
sub eax, [TickCounter_1]
cmp eax, BSYWaitTime;300 ;ожидать 3 сек.
ja @@Err1_4 ;ошибка тайм-аута
; Прочитать регистр состояния
.test:
in AL, DX
; Проверить состояние сигнала BSY
test AL, 80h
jnz @@WaitHDReady_2
; Проверить состояние сигнала DRQ
test AL, 08h
jnz @@WaitHDReady_2
 
; Загрузить команду в регистры контроллера
cli
mov DX, [ATABasePortAddr]
inc DX ;регистр "особенностей"
mov AL, [ATAFeatures]
out DX, AL
inc DX ;счетчик секторов
mov AL, [ATASectorCount]
out DX, AL
inc DX ;регистр номера сектора
mov AL, [ATASectorNumber]
out DX, AL
inc DX ;номер цилиндра (младший байт)
mov AX, [ATACylinder]
out DX, AL
inc DX ;номер цилиндра (старший байт)
mov AL, AH
out DX, AL
inc DX ;номер головки/номер диска
mov AL, [DiskNumber]
shl AL, 4
cmp [ATAHead], 0Fh;проверить номер головки
ja @@Err5_4
or AL, [ATAHead]
or AL, 10100000b
mov AH, [ATAAddressMode]
shl AH, 6
or AL, AH
out DX, AL
; Послать команду
mov AL, [ATACommand]
inc DX ;регистр команд
out DX, AL
sti
; Сбросить признак ошибки
; mov [DevErrorCode],0
@@End_10:
xor eax, eax
ret
; Записать код ошибки
@@Err1_4:
xor eax, eax
inc eax
; mov [DevErrorCode],1
ret
@@Err2_4:
mov eax, 2
; mov [DevErrorCode],2
ret
@@Err3_4:
mov eax, 3
; mov [DevErrorCode],3
ret
@@Err4_4:
mov eax, 4
; mov [DevErrorCode],4
ret
@@Err5_4:
mov eax, 5
; mov [DevErrorCode],5
; Завершение работы программы
ret
; sti
; popad
 
;*************************************************
;* ОЖИДАНИЕ ГОТОВНОСТИ УСТРОЙСТВА К РАБОТЕ *
;* Входные параметры передаются через глобальные *
;* перменные: *
;* ChannelNumber - номер канала; *
;* DiskNumber - номер диска на канале. *
;*************************************************
WaitUnitReady:
pusha
; Запомнить время начала операции
mov EAX, [timer_ticks]
mov [WURStartTime], EAX
; Очистить буфер пакетной команды
call clear_packet_buffer
; Сформировать команду TEST UNIT READY
mov [PacketCommand], word 00h
; ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ УСТРОЙСТВА
mov ecx, NoTickWaitTime
@@SendCommand:
; Подать команду проверки готовности
call SendPacketNoDatCommand
cmp [timer_ticks_enable], 0
jne @f
cmp [DevErrorCode], 0
je @@End_11
dec ecx
; cmp ecx,0
jz .Error
jmp @@SendCommand
@@:
call change_task
; Проверить код ошибки
cmp [DevErrorCode], 0
je @@End_11
; Проверить время ожидания готовности
mov EAX, [timer_ticks]
sub EAX, [WURStartTime]
cmp EAX, MaxCDWaitTime
jb @@SendCommand
.Error:
; Ошибка тайм-аута
mov [DevErrorCode], 1
@@End_11:
popa
ret
 
;*************************************************
;* ЗАПРЕТИТЬ СМЕНУ ДИСКА *
;* Входные параметры передаются через глобальные *
;* перменные: *
;* ChannelNumber - номер канала; *
;* DiskNumber - номер диска на канале. *
;*************************************************
prevent_medium_removal:
pusha
; Очистить буфер пакетной команды
call clear_packet_buffer
; Задать код команды
mov [PacketCommand], byte 0x1E
; Задать код запрета
mov [PacketCommand+4], byte 11b
; Подать команду
call SendPacketNoDatCommand
mov eax, ATAPI_IDE0_lock
add eax, [cdpos]
dec eax
mov [eax], byte 1
popa
ret
 
;*************************************************
;* РАЗРЕШИТЬ СМЕНУ ДИСКА *
;* Входные параметры передаются через глобальные *
;* перменные: *
;* ChannelNumber - номер канала; *
;* DiskNumber - номер диска на канале. *
;*************************************************
allow_medium_removal:
pusha
; Очистить буфер пакетной команды
call clear_packet_buffer
; Задать код команды
mov [PacketCommand], byte 0x1E
; Задать код запрета
mov [PacketCommand+4], byte 00b
; Подать команду
call SendPacketNoDatCommand
mov eax, ATAPI_IDE0_lock
add eax, [cdpos]
dec eax
mov [eax], byte 0
popa
ret
 
;*************************************************
;* ЗАГРУЗИТЬ НОСИТЕЛЬ В ДИСКОВОД *
;* Входные параметры передаются через глобальные *
;* перменные: *
;* ChannelNumber - номер канала; *
;* DiskNumber - номер диска на канале. *
;*************************************************
LoadMedium:
pusha
; Очистить буфер пакетной команды
call clear_packet_buffer
; Сформировать команду START/STOP UNIT
; Задать код команды
mov [PacketCommand], word 1Bh
; Задать операцию загрузки носителя
mov [PacketCommand+4], word 00000011b
; Подать команду
call SendPacketNoDatCommand
popa
ret
 
;*************************************************
;* ИЗВЛЕЧЬ НОСИТЕЛЬ ИЗ ДИСКОВОДА *
;* Входные параметры передаются через глобальные *
;* перменные: *
;* ChannelNumber - номер канала; *
;* DiskNumber - номер диска на канале. *
;*************************************************
EjectMedium:
pusha
; Очистить буфер пакетной команды
call clear_packet_buffer
; Сформировать команду START/STOP UNIT
; Задать код команды
mov [PacketCommand], word 1Bh
; Задать операцию извлечения носителя
mov [PacketCommand+4], word 00000010b
; Подать команду
call SendPacketNoDatCommand
popa
ret
 
;*************************************************
;* Проверить событие нажатия кнопки извлечения *
;* диска *
;* Входные параметры передаются через глобальные *
;* переменные: *
;* ChannelNumber - номер канала; *
;* DiskNumber - номер диска на канале. *
;*************************************************
proc check_ATAPI_device_event_has_work?
mov eax, [timer_ticks]
sub eax, [timer_ATAPI_check]
cmp eax, 100
jb .no
.yes:
xor eax, eax
inc eax
ret
.no:
xor eax, eax
ret
endp
 
align 4
check_ATAPI_device_event:
pusha
mov eax, [timer_ticks]
sub eax, [timer_ATAPI_check]
cmp eax, 100
jb .end_1
mov al, [DRIVE_DATA+1]
and al, 11b
cmp al, 10b
jz .ide3
.ide2_1:
mov al, [DRIVE_DATA+1]
and al, 1100b
cmp al, 1000b
jz .ide2
.ide1_1:
mov al, [DRIVE_DATA+1]
and al, 110000b
cmp al, 100000b
jz .ide1
.ide0_1:
mov al, [DRIVE_DATA+1]
and al, 11000000b
cmp al, 10000000b
jz .ide0
.end:
 
sti
mov eax, [timer_ticks]
mov [timer_ATAPI_check], eax
.end_1:
popa
ret
 
.ide3:
cli
cmp [ATAPI_IDE3_lock], 1
jne .ide2_1
cmp [IDE_Channel_2], 0
jne .ide1_1
cmp [cd_status], 0
jne .end
mov [IDE_Channel_2], 1
mov ecx, ide_channel2_mutex
call mutex_lock
call reserve_ok2
mov [ChannelNumber], 2
mov [DiskNumber], 1
mov [cdpos], 4
call GetEvent_StatusNotification
cmp [CDDataBuf+4], byte 1
je .eject_ide3
call syscall_cdaudio.free
jmp .ide2_1
.eject_ide3:
call .eject
call syscall_cdaudio.free
jmp .ide2_1
 
.ide2:
cli
cmp [ATAPI_IDE2_lock], 1
jne .ide1_1
cmp [IDE_Channel_2], 0
jne .ide1_1
cmp [cd_status], 0
jne .end
mov [IDE_Channel_2], 1
mov ecx, ide_channel2_mutex
call mutex_lock
call reserve_ok2
mov [ChannelNumber], 2
mov [DiskNumber], 0
mov [cdpos], 3
call GetEvent_StatusNotification
cmp [CDDataBuf+4], byte 1
je .eject_ide2
call syscall_cdaudio.free
jmp .ide1_1
.eject_ide2:
call .eject
call syscall_cdaudio.free
jmp .ide1_1
 
.ide1:
cli
cmp [ATAPI_IDE1_lock], 1
jne .ide0_1
cmp [IDE_Channel_1], 0
jne .end
cmp [cd_status], 0
jne .end
mov [IDE_Channel_1], 1
mov ecx, ide_channel1_mutex
call mutex_lock
call reserve_ok2
mov [ChannelNumber], 1
mov [DiskNumber], 1
mov [cdpos], 2
call GetEvent_StatusNotification
cmp [CDDataBuf+4], byte 1
je .eject_ide1
call syscall_cdaudio.free
jmp .ide0_1
.eject_ide1:
call .eject
call syscall_cdaudio.free
jmp .ide0_1
 
.ide0:
cli
cmp [ATAPI_IDE0_lock], 1
jne .end
cmp [IDE_Channel_1], 0
jne .end
cmp [cd_status], 0
jne .end
mov [IDE_Channel_1], 1
mov ecx, ide_channel1_mutex
call mutex_lock
call reserve_ok2
mov [ChannelNumber], 1
mov [DiskNumber], 0
mov [cdpos], 1
call GetEvent_StatusNotification
cmp [CDDataBuf+4], byte 1
je .eject_ide0
call syscall_cdaudio.free
jmp .end
.eject_ide0:
call .eject
call syscall_cdaudio.free
jmp .end
 
.eject:
call clear_CD_cache
call allow_medium_removal
mov [ignore_CD_eject_wait], 1
call EjectMedium
mov [ignore_CD_eject_wait], 0
ret
iglobal
timer_ATAPI_check dd 0
ATAPI_IDE0_lock db 0
ATAPI_IDE1_lock db 0
ATAPI_IDE2_lock db 0
ATAPI_IDE3_lock db 0
ignore_CD_eject_wait db 0
endg
;*************************************************
;* Получить сообщение о событии или состоянии *
;* устройства *
;* Входные параметры передаются через глобальные *
;* переменные: *
;* ChannelNumber - номер канала; *
;* DiskNumber - номер диска на канале. *
;*************************************************
GetEvent_StatusNotification:
pusha
mov [CDDataBuf_pointer], CDDataBuf
; Очистить буфер пакетной команды
call clear_packet_buffer
; Задать код команды
mov [PacketCommand], byte 4Ah
mov [PacketCommand+1], byte 00000001b
; Задать запрос класса сообщений
mov [PacketCommand+4], byte 00010000b
; Размер выделенной области
mov [PacketCommand+7], byte 8h
mov [PacketCommand+8], byte 0h
; Подать команду
call SendPacketDatCommand
popa
ret
 
;*************************************************
; прочитать информацию из TOC
;* Входные параметры передаются через глобальные *
;* переменные: *
;* ChannelNumber - номер канала; *
;* DiskNumber - номер диска на канале. *
;*************************************************
Read_TOC:
pusha
mov [CDDataBuf_pointer], CDDataBuf
; Очистить буфер пакетной команды
call clear_packet_buffer
; Сформировать пакетную команду для считывания
; сектора данных
mov [PacketCommand], byte 0x43
; Задать формат
mov [PacketCommand+2], byte 1
; Размер выделенной области
mov [PacketCommand+7], byte 0xFF
mov [PacketCommand+8], byte 0h
; Подать команду
call SendPacketDatCommand
popa
ret
 
;*************************************************
;* ОПРЕДЕЛИТЬ ОБЩЕЕ КОЛИЧЕСТВО СЕКТОРОВ НА ДИСКЕ *
;* Входные параметры передаются через глобальные *
;* переменные: *
;* ChannelNumber - номер канала; *
;* DiskNumber - номер диска на канале. *
;*************************************************
;ReadCapacity:
; pusha
;; Очистить буфер пакетной команды
; call clear_packet_buffer
;; Задать размер буфера в байтах
; mov [CDBlockSize],8
;; Сформировать команду READ CAPACITY
; mov [PacketCommand],word 25h
;; Подать команду
; call SendPacketDatCommand
; popa
; ret
 
clear_packet_buffer:
; Очистить буфер пакетной команды
and [PacketCommand], dword 0
and [PacketCommand+4], dword 0
and [PacketCommand+8], dword 0
ret