kolibrios-gitea/kernel/trunk/detect/dev_hdcd.inc

516 lines
18 KiB
PHP
Raw Normal View History

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$Revision$
;******************************************************
; поиск приводов HDD и CD
; автор исходного текста Кулаков Владимир Геннадьевич.
; адаптация и доработка Mario79
;******************************************************
;****************************************************
;* ПОИСК HDD и CD *
;****************************************************
cmp [ecx+IDE_DATA.ProgrammingInterface], 0
je EndFindHDD
FindHDD:
push ecx
xor ebx, ebx
inc ebx
cmp ecx, IDE_controller_2
jne @f
add bl, 5
jmp .find
@@:
cmp ecx, IDE_controller_3
jne .find
add bl, 10
;--------------------------------------
.find:
mov [ChannelNumber], 1
mov [DiskNumber], 0
call FindHDD_2
mov [DiskNumber], 1
call FindHDD_2
inc [ChannelNumber]
mov [DiskNumber], 0
call FindHDD_2
mov [DiskNumber], 1
call FindHDD_1
pop ecx
jmp EndFindHDD
;-----------------------------------------------------------------------------
FindHDD_2:
call FindHDD_1
shl byte [ebx+DRIVE_DATA], 2
ret
;-----------------------------------------------------------------------------
FindHDD_1:
DEBUGF 1, "K : Channel %d ",[ChannelNumber]:2
DEBUGF 1, "Disk %d\n",[DiskNumber]:1
push ebx ecx
call ReadHDD_ID
pop ecx ebx
cmp [DevErrorCode], 7
je .end
cmp [DevErrorCode], 0
jne .FindCD
cmp [Sector512+6], word 16
ja .FindCD
cmp [Sector512+12], word 255
ja .FindCD
inc byte [ebx+DRIVE_DATA]
jmp .Print_Device_Name
;--------------------------------------
.FindCD:
push ebx ecx
call DeviceReset
pop ecx ebx
cmp [DevErrorCode], 0
jne .end
push ebx ecx
call ReadCD_ID
pop ecx ebx
cmp [DevErrorCode], 0
jne .end
add [ebx+DRIVE_DATA], byte 2
;--------------------------------------
.Print_Device_Name:
pushad
pushfd
xor ebx, ebx
mov bx, [ChannelNumber]
dec ebx
shl ebx, 1
add bl, [DiskNumber]
shl ebx, 1
call calculate_IDE_device_values_storage
;--------------------------------------
.copy_dev_name:
mov esi, Sector512+27*2
mov edi, dev_name
mov ecx, 20
cld
;--------------------------------------
@@:
lodsw
xchg ah, al
stosw
loop @b
DEBUGF 1, "K : Dev: %s \n", dev_name
xor eax, eax
mov ax, [Sector512+64*2]
DEBUGF 1, "K : PIO possible modes %x\n", al
mov ax, [Sector512+51*2]
mov al, ah
call convert_Sector512_value
DEBUGF 1, "K : PIO set mode %x\n", ah
mov ax, [Sector512+63*2]
DEBUGF 1, "K : Multiword DMA possible modes %x\n", al
mov al, ah
call convert_Sector512_value
DEBUGF 1, "K : Multiword DMA set mode %x\n", ah
mov ax, [Sector512+88*2]
DEBUGF 1, "K : Ultra DMA possible modes %x\n", al
mov [ebx+IDE_DEVICE.UDMA_possible_modes], al
mov al, ah
call convert_Sector512_value
DEBUGF 1, "K : Ultra DMA set mode %x\n", ah
mov [ebx+IDE_DEVICE.UDMA_set_mode], ah
popfd
popad
ret
;--------------------------------------
.end:
DEBUGF 1, "K : Device not found\n"
ret
;-----------------------------------------------------------------------------
calculate_IDE_device_values_storage:
cmp ecx, IDE_controller_1
jne @f
add ebx, IDE_device_1
jmp .exit
;--------------------------------------
@@:
cmp ecx, IDE_controller_2
jne @f
add ebx, IDE_device_2
jmp .exit
;--------------------------------------
@@:
add ebx, IDE_device_3
;--------------------------------------
.exit:
ret
;-----------------------------------------------------------------------------
convert_Sector512_value:
mov ecx, 8
xor ah, ah
;--------------------------------------
@@:
test al, 1b
jnz .end
shr al, 1
inc ah
loop @b
xor ah, ah
;--------------------------------------
.end:
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], 0xEC
call SendCommandToHDD
cmp [DevErrorCode], 0 ;проверить код ошибки
jne @@End ;закончить, сохранив код ошибки
mov dx, [ATABasePortAddr]
add dx, 7 ;адрес регистра состояни
mov ecx, 0xffff
@@WaitCompleet:
; Проверить время выполнения команды
dec ecx
jz @@Error1 ;ошибка тайм-аута
; Проверить готовность
in al, dx
test al, 80h ;состояние сигнала BSY
jnz @@WaitCompleet
test al, 1 ;состояние сигнала ERR
jnz @@Error6
test al, 08h ;состояние сигнала DRQ
jz @@WaitCompleet
; Принять блок данных от контроллера
mov edi, Sector512
mov dx, [ATABasePortAddr];регистр данных
mov cx, 256 ;число считываемых слов
rep insw ;принять блок данных
ret
; Записать код ошибки
@@Error1:
mov [DevErrorCode], 1
ret
@@Error6:
mov [DevErrorCode], 6
@@End:
ret
;-----------------------------------------------------------------------------
uglobal
; Стандартные базовые адреса каналов 1 и 2
StandardATABases dw ?, ? ; 1F0h, 170h
; Номер канала
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 - ошибка при выполнении
; команды, 7 - таймаут при выборе канала)
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
@@WaitHDReady:
; Проверить время ожидани
dec ecx
jz @@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], 0xF ;проверить номер головки
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], 7
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], 0xA1
call SendCommandToHDD
cmp [DevErrorCode], 0;проверить код ошибки
jne @@End_1 ;закончить, сохранив код ошибки
; Ожидать готовность данных HDD
mov dx, [ATABasePortAddr]
add dx, 7 ;порт 1х7h
mov ecx, 0xffff
@@WaitCompleet_1:
; Проверить врем
dec ecx
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 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, 0x8
inc dx ;регистр команд
out dx, al
mov ecx, 0x80000
@@WaitHDReady_1:
; Проверить время ожидани
dec ecx
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: