;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; ;; Distributed under terms of the GNU General Public License ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; $Revision$ ;********************************************************** ; Непосредственная работа с устройством СD (ATAPI) ;********************************************************** ; Автор части исходного текста Кулаков Владимир Геннадьевич ; Адаптация, доработка и разработка Mario79, ; Максимальное количество повторений операции чтения 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