;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; ;; Distributed under terms of the GNU General Public License ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; $Revision$ ;****************************************************** ; поиск приводов HDD и CD ; автор исходного текста Кулаков Владимир Геннадьевич. ; адаптация и доработка Mario79 ;****************************************************** ;**************************************************** ;* ПОИСК HDD и CD * ;**************************************************** FindHDD: mov [ChannelNumber], 1 mov [DiskNumber], 0 call FindHDD_3 ; mov ax,[Sector512+176] ; mov [DRIVE_DATA+6],ax ; mov ax,[Sector512+126] ; mov [DRIVE_DATA+8],ax ; mov ax,[Sector512+128] ; mov [DRIVE_DATA+8],ax mov [DiskNumber], 1 call FindHDD_3 ; mov al,[Sector512+176] ; mov [DRIVE_DATA+7],al inc [ChannelNumber] mov [DiskNumber], 0 call FindHDD_3 ; mov al,[Sector512+176] ; mov [DRIVE_DATA+8],al mov [DiskNumber], 1 call FindHDD_1 ; mov al,[Sector512+176] ; mov [DRIVE_DATA+9],al jmp EndFindHDD FindHDD_1: DEBUGF 1, "K : Channel %d ",[ChannelNumber]:2 DEBUGF 1, "Disk %d\n",[DiskNumber]:1 call ReadHDD_ID cmp [DevErrorCode], 0 jne FindHDD_2 cmp [Sector512+6], word 16 ja FindHDD_2 cmp [Sector512+12], word 255 ja FindHDD_2 inc byte [DRIVE_DATA+1] jmp Print_Device_Name FindHDD_2: call DeviceReset cmp [DevErrorCode], 0 jne FindHDD_2_2 call ReadCD_ID cmp [DevErrorCode], 0 jne FindHDD_2_2 inc byte [DRIVE_DATA+1] inc byte [DRIVE_DATA+1] Print_Device_Name: pushad pushfd mov esi,Sector512+27*2 mov edi,dev_name mov ecx,20 cld @@: lodsw xchg ah,al stosw loop @b popfd popad DEBUGF 1, "K : Dev: %s \n", dev_name FindHDD_2_2: ret FindHDD_3: call FindHDD_1 shl byte [DRIVE_DATA+1], 2 ret ; Адрес считываемого сектора в режиме LBA uglobal SectorAddress DD ? dev_name: rb 41 endg ;************************************************* ;* ЧТЕНИЕ ИДЕНТИФИКАТОРА ЖЕСТКОГО ДИСКА * ;* Входные параметры передаются через глобальные * ;* переменные: * ;* ChannelNumber - номер канала (1 или 2); * ;* DiskNumber - номер диска на канале (0 или 1). * ;* Идентификационный блок данных считывается * ;* в массив Sector512. * ;************************************************* ReadHDD_ID: ; Задать режим CHS mov [ATAAddressMode], 0 ; Послать команду идентификации устройства mov [ATAFeatures], 0 mov [ATAHead], 0 mov [ATACommand], 0ECh call SendCommandToHDD cmp [DevErrorCode], 0;проверить код ошибки jne @@End ;закончить, сохранив код ошибки mov DX, [ATABasePortAddr] add DX, 7 ;адрес регистра состояни mov ecx, 0xffff @@WaitCompleet: ; Проверить время выполнения команды dec ecx ; cmp ecx,0 jz @@Error1 ;ошибка тайм-аута ; Проверить готовность in AL, DX test AL, 80h ;состояние сигнала BSY jnz @@WaitCompleet test AL, 1 ;состояние сигнала ERR jnz @@Error6 test AL, 08h ;состояние сигнала DRQ jz @@WaitCompleet ; Принять блок данных от контроллера ; mov AX,DS ; mov ES,AX mov EDI, Sector512 ;offset Sector512 mov DX, [ATABasePortAddr];регистр данных mov CX, 256 ;число считываемых слов rep insw ;принять блок данных ret ; Записать код ошибки @@Error1: mov [DevErrorCode], 1 ret @@Error6: mov [DevErrorCode], 6 @@End: ret iglobal ; Стандартные базовые адреса каналов 1 и 2 StandardATABases DW 1F0h, 170h endg uglobal ; Номер канала ChannelNumber DW ? ; Номер диска DiskNumber DB ? ; Базовый адрес группы портов контроллера ATA ATABasePortAddr DW ? ; Параметры ATA-команды ATAFeatures DB ? ;особенности ATASectorCount DB ? ;количество обрабатываемых секторов ATASectorNumber DB ? ;номер начального сектора ATACylinder DW ? ;номер начального цилиндра ATAHead DB ? ;номер начальной головки ATAAddressMode DB ? ;режим адресации (0 - CHS, 1 - LBA) ATACommand DB ? ;код команды, подлежащей выполнению ; Код ошибки (0 - нет ошибок, 1 - превышен допустимый ; интервал ожидания, 2 - неверный код режима адресации, ; 3 - неверный номер канала, 4 - неверный номер диска, ; 5 - неверный номер головки, 6 - ошибка при выполнении ; команды) DevErrorCode dd ? endg ;**************************************************** ;* ПОСЛАТЬ КОМАНДУ ЗАДАННОМУ ДИСКУ * ;* Входные параметры передаются через глобальные * ;* переменные: * ;* ChannelNumber - номер канала (1 или 2); * ;* DiskNumber - номер диска (0 или 1); * ;* ATAFeatures - "особенности"; * ;* ATASectorCount - количество секторов; * ;* ATASectorNumber - номер начального сектора; * ;* ATACylinder - номер начального цилиндра; * ;* ATAHead - номер начальной головки; * ;* ATAAddressMode - режим адресации (0-CHS, 1-LBA); * ;* ATACommand - код команды. * ;* После успешного выполнения функции: * ;* в ATABasePortAddr - базовый адрес HDD; * ;* в DevErrorCode - ноль. * ;* При возникновении ошибки в DevErrorCode будет * ;* возвращен код ошибки. * ;**************************************************** SendCommandToHDD: ; Проверить значение кода режима cmp [ATAAddressMode], 1 ja @@Err2 ; Проверить корректность номера канала mov BX, [ChannelNumber] cmp BX, 1 jb @@Err3 cmp BX, 2 ja @@Err3 ; Установить базовый адрес 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 shl AL, 4 or AL, 10100000b out DX, AL ; Ожидать, пока диск не будет готов inc DX mov ecx, 0xfff ; mov eax,[timer_ticks] ; mov [TickCounter_1],eax @@WaitHDReady: ; Проверить время ожидани dec ecx ; cmp ecx,0 jz @@Err1 ; mov eax,[timer_ticks] ; sub eax,[TickCounter_1] ; cmp eax,300 ;ожидать 300 тиков ; ja @@Err1 ;ошибка тайм-аута ; Прочитать регистр состояни in AL, DX ; Проверить состояние сигнала BSY test AL, 80h jnz @@WaitHDReady ; Проверить состояние сигнала DRQ test AL, 08h jnz @@WaitHDReady ; Загрузить команду в регистры контроллера 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 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 ret ; Записать код ошибки @@Err1: mov [DevErrorCode], 1 ret @@Err2: mov [DevErrorCode], 2 ret @@Err3: mov [DevErrorCode], 3 ret @@Err4: mov [DevErrorCode], 4 ret @@Err5: mov [DevErrorCode], 5 ; Завершение работы программы ret ;************************************************* ;* ЧТЕНИЕ ИДЕНТИФИКАТОРА УСТРОЙСТВА ATAPI * ;* Входные параметры передаются через глобальные * ;* перменные: * ;* ChannelNumber - номер канала; * ;* DiskNumber - номер диска на канале. * ;* Идентификационный блок данных считывается * ;* в массив Sector512. * ;************************************************* ReadCD_ID: ; Задать режим CHS mov [ATAAddressMode], 0 ; Послать команду идентификации устройства mov [ATAFeatures], 0 mov [ATASectorCount], 0 mov [ATASectorNumber], 0 mov [ATACylinder], 0 mov [ATAHead], 0 mov [ATACommand], 0A1h call SendCommandToHDD cmp [DevErrorCode], 0;проверить код ошибки jne @@End_1 ;закончить, сохранив код ошибки ; Ожидать готовность данных HDD mov DX, [ATABasePortAddr] add DX, 7 ;порт 1х7h mov ecx, 0xffff @@WaitCompleet_1: ; Проверить врем dec ecx ; cmp ecx,0 jz @@Error1_1 ;ошибка тайм-аута ; Проверить готовность in AL, DX test AL, 80h ;состояние сигнала BSY jnz @@WaitCompleet_1 test AL, 1 ;состояние сигнала ERR jnz @@Error6_1 test AL, 08h ;состояние сигнала DRQ jz @@WaitCompleet_1 ; Принять блок данных от контроллера ; mov AX,DS ; mov ES,AX mov EDI, Sector512 ;offset Sector512 mov DX, [ATABasePortAddr];порт 1x0h mov CX, 256;число считываемых слов rep insw ret ; Записать код ошибки @@Error1_1: mov [DevErrorCode], 1 ret @@Error6_1: mov [DevErrorCode], 6 @@End_1: ret ;************************************************* ;* СБРОС УСТРОЙСТВА * ;* Входные параметры передаются через глобальные * ;* переменные: * ;* ChannelNumber - номер канала (1 или 2); * ;* DiskNumber - номер диска (0 или 1). * ;************************************************* DeviceReset: ; Проверить корректность номера канала mov BX, [ChannelNumber] cmp BX, 1 jb @@Err3_2 cmp BX, 2 ja @@Err3_2 ; Установить базовый адрес dec BX shl BX, 1 movzx ebx, bx mov DX, [ebx+StandardATABases] mov [ATABasePortAddr], DX ; Выбрать нужный диск add DX, 6 ;адрес регистра головок mov AL, [DiskNumber] cmp AL, 1 ;проверить номера диска ja @@Err4_2 shl AL, 4 or AL, 10100000b out DX, AL ; Послать команду "Сброс" mov AL, 08h inc DX ;регистр команд out DX, AL mov ecx, 0x80000 @@WaitHDReady_1: ; Проверить время ожидани dec ecx ; cmp ecx,0 je @@Err1_2 ;ошибка тайм-аута ; Прочитать регистр состояни in AL, DX ; Проверить состояние сигнала BSY test AL, 80h jnz @@WaitHDReady_1 ; Сбросить признак ошибки mov [DevErrorCode], 0 ret ; Обработка ошибок @@Err1_2: mov [DevErrorCode], 1 ret @@Err3_2: mov [DevErrorCode], 3 ret @@Err4_2: mov [DevErrorCode], 4 ; Записать код ошибки ret EndFindHDD: