;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;; ;; Distributed under terms of the GNU General Public License ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; $Revision: 7136 $ ;----------------------------------------------------------------------------- ;********************************************************** ; Непосредственная работа с устройством СD (ATAPI) ;********************************************************** ; Автор части исходного текста Кулаков Владимир Геннадьевич ; Адаптация, доработка и разработка Mario79, ; Максимальное количество повторений операции чтения MaxRetr = 10 ; Предельное время ожидания готовности к приему команды ; (в тиках) BSYWaitTime = 1000 ;2 NoTickWaitTime = 0xfffff CDBlockSize = 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 ;-------------------------------------- align 4 .hdreadcache: cmp [esi], eax ; correct sector je .yeshdcache 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 ;-------------------------------------- .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 ;-------------------------------------- align 4 @@NextRetr: ; Подать команду ;************************************************* ;* ПОЛНОЕ ЧТЕНИЕ СЕКТОРА КОМПАКТ-ДИСКА * ;* Считываются данные пользователя, информация * ;* субканала и контрольная информация * ;* Входные параметры передаются через глобальные * ;* перменные: * ;* ChannelNumber - номер канала; * ;* DiskNumber - номер диска на канале; * ;* CDSectorAddress - адрес считываемого сектора. * ;* Данные считывается в массив CDDataBuf. * ;************************************************* ;ReadCD: push ecx ; Очистить буфер пакетной команды 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 [PacketCommand+8], byte 1 ; Подать команду call SendPacketDatCommand pop ecx 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 ;-------------------------------------- align 4 .wait: dec eax jz @@NextRetr jmp .wait ;-------------------------------------- align 4 @@: loop @@NextRetr ;-------------------------------------- @@End_4: mov dword [DevErrorCode], eax popad ret ;----------------------------------------------------------------------------- ; Универсальные процедуры, обеспечивающие выполнение ; пакетных команд в режиме PIO ; Максимально допустимое время ожидания реакции ; устройства на пакетную команду (в тиках) ;----------------------------------------------------------------------------- MaxCDWaitTime = 1000 ;200 ;10 секунд uglobal ; Область памяти для формирования пакетной команды PacketCommand: rb 12 ;DB 12 DUP (?) ; Адрес считываемого сектора данных 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 ; Задать режим CHS mov byte [ATAAddressMode], al ; Послать ATA-команду передачи пакетной команды mov byte [ATAFeatures], al mov byte [ATASectorCount], al mov byte [ATASectorNumber], al ; Загрузить размер передаваемого блока mov [ATAHead], al mov [ATACylinder], CDBlockSize mov [ATACommand], 0xA0 call SendCommandToHDD_1 test eax, eax jnz @@End_8 ;закончить, сохранив код ошибки ; Ожидание готовности дисковода к приему ; пакетной команды mov dx, [ATABasePortAddr] add dx, 7 ;порт 1х7h mov ecx, NoTickWaitTime ;-------------------------------------- align 4 @@WaitDevice0: cmp [timer_ticks_enable], 0 jne @f dec ecx jz @@Err1_1 jmp .test ;-------------------------------------- align 4 @@: call change_task ; Проверить время выполнения команды mov eax, [timer_ticks] sub eax, [TickCounter_1] cmp eax, BSYWaitTime ja @@Err1_1 ;ошибка тайм-аута ; Проверить готовность ;-------------------------------------- align 4 .test: in al, dx test al, 0x80 ;состояние сигнала BSY jnz @@WaitDevice0 test al, 1 ;состояние сигнала ERR jnz @@Err6 test al, 0x8 ;состояние сигнала 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 ;-------------------------------------- align 4 @@WaitDevice1: cmp [timer_ticks_enable], 0 jne @f dec ecx jz @@Err1_1 jmp .test_1 ;-------------------------------------- align 4 @@: call change_task ; Проверить время выполнения команды mov eax, [timer_ticks] sub eax, [TickCounter_1] cmp eax, MaxCDWaitTime ja @@Err1_1 ;ошибка тайм-аута ; Проверить готовность ;-------------------------------------- align 4 .test_1: in al, dx test al, 0x80 ;состояние сигнала BSY jnz @@WaitDevice1 test al, 1 ;состояние сигнала ERR jnz @@Err6_temp test al, 0x8 ;состояние сигнала DRQ jz @@WaitDevice1 ; Принять блок данных от контроллера mov edi, [CDDataBuf_pointer] ; Загрузить адрес регистра данных контроллера mov dx, [ATABasePortAddr] ; Загрузить в счетчик размер блока в байтах 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 ;-------------------------------------- @@Err6_temp: mov eax, 7 ret ;-------------------------------------- @@Err6: mov eax, 6 ret ;----------------------------------------------------------------------------- ;*********************************************** ;* ПОСЛАТЬ УСТРОЙСТВУ ATAPI ПАКЕТНУЮ КОМАНДУ, * ;* НЕ ПРЕДУСМАТРИВАЮЩУЮ ПЕРЕДАЧИ ДАННЫХ * ;* Входные параметры передаются через * ;* глобальные перменные: * ;* ChannelNumber - номер канала; * ;* DiskNumber - номер диска на канале; * ;* PacketCommand - 12-байтный командный пакет. * ;*********************************************** SendPacketNoDatCommand: pushad xor eax, eax ; Задать режим 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], 0xA0 call SendCommandToHDD_1 test eax, eax jnz @@End_9 ;закончить, сохранив код ошибки ; Ожидание готовности дисковода к приему ; пакетной команды mov dx, [ATABasePortAddr] add dx, 7 ;порт 1х7h ;-------------------------------------- align 4 @@WaitDevice0_1: call change_task ; Проверить время ожидания mov eax, [timer_ticks] sub eax, [TickCounter_1] cmp eax, BSYWaitTime ja @@Err1_3 ;ошибка тайм-аута ; Проверить готовность in al, dx test al, 0x80 ;состояние сигнала BSY jnz @@WaitDevice0_1 test al, 1 ;состояние сигнала ERR jnz @@Err6_1 test al, 0x8 ;состояние сигнала 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 ;-------------------------------------- align 4 @@WaitDevice1_1: call change_task ; Проверить время выполнения команды mov eax, [timer_ticks] sub eax, [TickCounter_1] cmp eax, MaxCDWaitTime ja @@Err1_3 ;ошибка тайм-аута ; Ожидать освобождения устройства in al, dx test al, 0x80 ;состояние сигнала BSY jnz @@WaitDevice1_1 test al, 1 ;состояние сигнала ERR jnz @@Err6_1 test al, 0x40 ;состояние сигнала 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: ; Проверить значение кода режима cmp [ATAAddressMode], 1 ja @@Err2_4 ; Проверить корректность номера канала movzx ebx, [ChannelNumber] dec ebx cmp ebx, 1 ja @@Err3_4 ; Установить базовый адрес shl ebx, 2 mov eax, [cdpos] dec eax shr eax, 2 imul eax, sizeof.IDE_DATA add eax, IDE_controller_1 add eax, ebx mov ax, [eax+IDE_DATA.BAR0_val] 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 ;-------------------------------------- align 4 @@WaitHDReady_2: cmp [timer_ticks_enable], 0 jne @f dec ecx jz @@Err1_4 jmp .test ;-------------------------------------- align 4 @@: call change_task ; Проверить время ожидания mov eax, [timer_ticks] sub eax, [TickCounter_1] cmp eax, BSYWaitTime ;300 ;ожидать 3 сек. ja @@Err1_4 ;ошибка тайм-аута ;-------------------------------------- align 4 .test: in al, dx ; Прочитать регистр состояния ; Проверить состояние сигнала BSY test al, 0x80 jnz @@WaitHDReady_2 ; Проверить состояние сигнала DRQ test al, 0x8 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], 0xF ;проверить номер головки 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 ;-------------------------------------- @@End_10: xor eax, eax ret ;-------------------------------------- ; Записать код ошибки @@Err1_4: xor eax, eax inc eax ret ;-------------------------------------- @@Err2_4: mov eax, 2 ret ;-------------------------------------- @@Err3_4: mov eax, 3 ret ;-------------------------------------- @@Err4_4: mov eax, 4 ret ;-------------------------------------- @@Err5_4: mov eax, 5 ret ;----------------------------------------------------------------------------- ;************************************************* ;* ОЖИДАНИЕ ГОТОВНОСТИ УСТРОЙСТВА К РАБОТЕ * ;* Входные параметры передаются через глобальные * ;* перменные: * ;* ChannelNumber - номер канала; * ;* DiskNumber - номер диска на канале. * ;************************************************* WaitUnitReady: pusha ; Запомнить время начала операции mov eax, [timer_ticks] mov [WURStartTime], eax ; Очистить буфер пакетной команды call clear_packet_buffer ; Сформировать команду TEST UNIT READY mov [PacketCommand], word 0 ; ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ УСТРОЙСТВА mov ecx, NoTickWaitTime ;-------------------------------------- align 4 @@SendCommand: ; Подать команду проверки готовности call SendPacketNoDatCommand cmp [timer_ticks_enable], 0 jne @f cmp [DevErrorCode], 0 je @@End_11 dec ecx jz .Error jmp @@SendCommand ;-------------------------------------- align 4 @@: 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 0 ; Подать команду 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 0x1B ; Задать операцию загрузки носителя mov [PacketCommand+4], word 00000011b ; Подать команду call SendPacketNoDatCommand popa ret ;----------------------------------------------------------------------------- ;************************************************* ;* ИЗВЛЕЧЬ НОСИТЕЛЬ ИЗ ДИСКОВОДА * ;* Входные параметры передаются через глобальные * ;* перменные: * ;* ChannelNumber - номер канала; * ;* DiskNumber - номер диска на канале. * ;************************************************* EjectMedium: pusha ; Очистить буфер пакетной команды call clear_packet_buffer ; Сформировать команду START/STOP UNIT ; Задать код команды mov [PacketCommand], word 0x1B ; Задать операцию извлечения носителя 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 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 pushfd 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 ;-------------------------------------- .ide7_1: mov al, [DRIVE_DATA+6] and al, 11b cmp al, 10b jz .ide7 ;-------------------------------------- .ide6_1: mov al, [DRIVE_DATA+6] and al, 1100b cmp al, 1000b jz .ide6 ;-------------------------------------- .ide5_1: mov al, [DRIVE_DATA+6] and al, 110000b cmp al, 100000b jz .ide5 ;-------------------------------------- .ide4_1: mov al, [DRIVE_DATA+6] and al, 11000000b cmp al, 10000000b jz .ide4 ;-------------------------------------- .ide11_1: mov al, [DRIVE_DATA+11] and al, 11b cmp al, 10b jz .ide11 ;-------------------------------------- .ide10_1: mov al, [DRIVE_DATA+11] and al, 1100b cmp al, 1000b jz .ide10 ;-------------------------------------- .ide9_1: mov al, [DRIVE_DATA+11] and al, 110000b cmp al, 100000b jz .ide9 ;-------------------------------------- .ide8_1: mov al, [DRIVE_DATA+11] and al, 11000000b cmp al, 10000000b jz .ide8 ;-------------------------------------- .end: popfd mov eax, [timer_ticks] mov [timer_ATAPI_check], eax ;-------------------------------------- .end_1: popa ret ;----------------------------------------------------------------------------- .ide3: cli cmp [ATAPI_IDE3_lock], 1 jne .ide2_1 cmp [cd_status], 0 jne .end 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 jne @f call .eject ;-------------------------------------- @@: call syscall_cdaudio.free jmp .ide2_1 ;----------------------------------------------------------------------------- .ide2: cli cmp [ATAPI_IDE2_lock], 1 jne .ide1_1 cmp [cd_status], 0 jne .end 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 jne @f call .eject ;-------------------------------------- @@: call syscall_cdaudio.free jmp .ide1_1 ;----------------------------------------------------------------------------- .ide1: cli cmp [ATAPI_IDE1_lock], 1 jne .ide0_1 cmp [cd_status], 0 jne .end 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 jne @f call .eject ;-------------------------------------- @@: call syscall_cdaudio.free jmp .ide0_1 ;----------------------------------------------------------------------------- .ide0: cli cmp [ATAPI_IDE0_lock], 1 jne .ide7_1 cmp [cd_status], 0 jne .end 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 jne @f call .eject ;-------------------------------------- @@: call syscall_cdaudio.free jmp .ide7_1 ;----------------------------------------------------------------------------- .ide7: cli cmp [ATAPI_IDE7_lock], 1 jne .ide6_1 cmp [cd_status], 0 jne .end mov ecx, ide_channel4_mutex call mutex_lock call reserve_ok2 mov [ChannelNumber], 2 mov [DiskNumber], 1 mov [cdpos], 8 call GetEvent_StatusNotification cmp [CDDataBuf+4], byte 1 jne @f call .eject ;-------------------------------------- @@: call syscall_cdaudio.free jmp .ide6_1 ;----------------------------------------------------------------------------- .ide6: cli cmp [ATAPI_IDE6_lock], 1 jne .ide5_1 cmp [cd_status], 0 jne .end mov ecx, ide_channel4_mutex call mutex_lock call reserve_ok2 mov [ChannelNumber], 2 mov [DiskNumber], 0 mov [cdpos], 7 call GetEvent_StatusNotification cmp [CDDataBuf+4], byte 1 jne @f call .eject ;-------------------------------------- @@: call syscall_cdaudio.free jmp .ide5_1 ;----------------------------------------------------------------------------- .ide5: cli cmp [ATAPI_IDE5_lock], 1 jne .ide4_1 cmp [cd_status], 0 jne .end mov ecx, ide_channel3_mutex call mutex_lock call reserve_ok2 mov [ChannelNumber], 1 mov [DiskNumber], 1 mov [cdpos], 6 call GetEvent_StatusNotification cmp [CDDataBuf+4], byte 1 jne @f call .eject ;-------------------------------------- @@: call syscall_cdaudio.free jmp .ide4_1 ;----------------------------------------------------------------------------- .ide4: cli cmp [ATAPI_IDE4_lock], 1 jne .ide11_1 cmp [cd_status], 0 jne .end mov ecx, ide_channel3_mutex call mutex_lock call reserve_ok2 mov [ChannelNumber], 1 mov [DiskNumber], 0 mov [cdpos], 5 call GetEvent_StatusNotification cmp [CDDataBuf+4], byte 1 jne @f call .eject ;-------------------------------------- @@: call syscall_cdaudio.free jmp .ide11_1 ;----------------------------------------------------------------------------- .ide11: cli cmp [ATAPI_IDE11_lock], 1 jne .ide10_1 cmp [cd_status], 0 jne .end mov ecx, ide_channel6_mutex call mutex_lock call reserve_ok2 mov [ChannelNumber], 2 mov [DiskNumber], 1 mov [cdpos], 12 call GetEvent_StatusNotification cmp [CDDataBuf+4], byte 1 jne @f call .eject ;-------------------------------------- @@: call syscall_cdaudio.free jmp .ide10_1 ;----------------------------------------------------------------------------- .ide10: cli cmp [ATAPI_IDE10_lock], 1 jne .ide9_1 cmp [cd_status], 0 jne .end mov ecx, ide_channel6_mutex call mutex_lock call reserve_ok2 mov [ChannelNumber], 2 mov [DiskNumber], 0 mov [cdpos], 11 call GetEvent_StatusNotification cmp [CDDataBuf+4], byte 1 jne @f call .eject ;-------------------------------------- @@: call syscall_cdaudio.free jmp .ide9_1 ;----------------------------------------------------------------------------- .ide9: cli cmp [ATAPI_IDE9_lock], 1 jne .ide8_1 cmp [cd_status], 0 jne .end mov ecx, ide_channel5_mutex call mutex_lock call reserve_ok2 mov [ChannelNumber], 1 mov [DiskNumber], 1 mov [cdpos], 10 call GetEvent_StatusNotification cmp [CDDataBuf+4], byte 1 jne @f call .eject ;-------------------------------------- @@: call syscall_cdaudio.free jmp .ide8_1 ;----------------------------------------------------------------------------- .ide8: cli cmp [ATAPI_IDE8_lock], 1 jne .end cmp [cd_status], 0 jne .end mov ecx, ide_channel5_mutex call mutex_lock call reserve_ok2 mov [ChannelNumber], 1 mov [DiskNumber], 0 mov [cdpos], 9 call GetEvent_StatusNotification cmp [CDDataBuf+4], byte 1 jne @f 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 ATAPI_IDE4_lock db 0 ATAPI_IDE5_lock db 0 ATAPI_IDE6_lock db 0 ATAPI_IDE7_lock db 0 ATAPI_IDE8_lock db 0 ATAPI_IDE9_lock db 0 ATAPI_IDE10_lock db 0 ATAPI_IDE11_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 ;-----------------------------------------------------------------------------