Здравствуйте, в ходе работы надо было произвести сабж, но в буффере постоянно получаются нули. Есть аналогичный код для LBA28, он работает, а 48 нет. Ошибку пока найти не получается, может кто сможет подсказать где косяк. Код основан на книге Кулакова "Программирование дисковых подсистем". Вот соответсвенно процедуры посылки команды и чтения сектора: Код (Text): SendCommandToHDDLBA48 proc pushad debug 88h mov eax, ds:[046ch] mov ds:[OPERATION_TIMER], eax ; Проверить корректность номера канала mov BX,ds:[CHANNEL_NUMBER] ; Установить базовый адрес cmp BX, 1 db 66h jne @@SecondChannel mov word ptr ds:[ATA_BASE_PORT_ADDR],01f0h db 66h jmp @@PortSelected @@SecondChannel: mov word ptr ds:[ATA_BASE_PORT_ADDR],0170h @@PortSelected: ; Ожидание готовности HDD к приему команды ; Выбрать нужный диск mov DX,ds:[ATA_BASE_PORT_ADDR] add DX,6 ;адрес регистра головок mov AL,ds:[DISK_NUMBER] shl AL,4 or AL,10100000b out DX,AL ; Ожидать, пока диск не будет готов inc DX @@WaitHDReady: ; Проверить время ожидания mov EAX,ds:[046Ch] sub EAX,ds:[OPERATION_TIMER] cmp EAX,BSY_WAIT_TIME db 66h ja @@Err1 ;ошибка тайм-аута ; Прочитать регистр состояния in AL,DX ; Проверить состояние сигнала BSY test AL,80h db 66h jnz @@WaitHDReady ; Проверить состояние сигнала DRQ test AL,08h db 66h jnz @@WaitHDReady ; Загрузить команду в регистры контроллера mov DX,ds:[ATA_BASE_PORT_ADDR] add DX,2 ;счетчик секторов +2 xor al, al out DX,AL ;SECTOR_COUNT 15...8 == 0 mov AL,ds:[ATA_SECTOR_COUNT] out DX,AL ;SECTOR_COUNT 7...0 inc DX ;LBA low +3 mov AL,ds:[LBA_24_31] out DX,AL mov AL,ds:[LBA_0_7] out DX,AL inc DX ;LBA mid +4 mov Al,ds:[LBA_32_39] out DX,AL mov AL,ds:[LBA_8_15] out DX,AL inc DX ;LBA high +5 mov Al,ds:[LBA_40_47] out DX,AL mov AL,ds:[LBA_16_23] out DX,AL inc DX ;номер головки/номер диска +6 mov AL,ds:[DISK_NUMBER] shl AL,4 or AL,10100000b mov AH,ds:[ATA_ADDRESS_MODE] shl AH,6 or AL,AH out DX,AL ; Послать команду mov AL,byte ptr ds:[ATA_COMMAND] inc DX ;регистр команд out DX,AL mov dword ptr ds:[DEVICE_ERROR_CODE], 0 db 66h jmp @@exit @@Err1: mov dword ptr ds:[DEVICE_ERROR_CODE], 1 @@exit: debug 89h popad MyRet SendCommandToHDDLBA48 endp ;**************************************************** ; Процедура чтения секторов hdd в режиме LBA48 ; Вход: eax - биты 0-31 адреса ; dx - биты 32-47 ; cx - Число секторов ; edi - адрес буфера приемника ; [DISK_NUMBER] - диск primary/slave ; [CHANNEL_NUMBER] - канал IDE ReadHDDSectorLBA48 proc pushad debug 86h ; Задать режим LBA mov byte ptr ds:[ATA_ADDRESS_MODE],1 ; Послать команду чтения сектора (с повторами) mov byte ptr ds:[ATA_SECTOR_COUNT],cl mov ds:[LBA_0_7],EAX mov ds:[LBA_32_39], dx mov byte ptr ds:[ATA_COMMAND],24h call large near ptr SendCommandToHDDLBA48 cmp dword ptr ds:[DEVICE_ERROR_CODE],0 db 66h jne @@End ;закончить, сохранив код ошибки ; Ожидать готовность данных HDD mov DX,ds:[ATA_BASE_PORT_ADDR] add DX,7 ;адрес регистра состояния @@WaitCompleet: ; Проверить время выполнения команды mov EAX,ds:[046Ch] sub EAX,ds:[OPERATION_TIMER] cmp EAX, MAX_HDD_WAIT_TIME db 66h ja @@Error1 ;ошибка тайм-аута ; Проверить готовность in AL,DX test AL, 1 db 66h jnz @@Error2 test AL,80h ;состояние сигнала BSY db 66h jnz @@WaitCompleet test AL,08h ;состояние сигнала DRQ db 66h jz @@WaitCompleet ; Принять сектор mov EDX,ds:[ATA_BASE_PORT_ADDR] ;регистр данных mov EAX,256 ;число считываемых слов mul CX mov ECX, EAX db 67h rep insw ;принять блок данных ; Сбросить признак ошибки mov dword ptr ds:[DEVICE_ERROR_CODE],0 db 66h jmp @@End ; Записать номер ошибки @@Error1: mov dword ptr ds:[DEVICE_ERROR_CODE],1 ;ошибка тайм-аута db 66h jmp @@End @@Error2: mov dword ptr ds:[DEVICE_ERROR_CODE],2 ;ошибка @@End: debug 87h popad MyRet ReadHDDSectorLBA48 endp Для сравнения также выкладывают код для LBA28: Код (Text): ;**************************************************** ;* ПОСЛАТЬ КОМАНДУ ЗАДАННОМУ ДИСКУ * ;* Входные параметры передаются через глобальные * ;* переменные: * ;* ChannelNumber - номер канала (1 или 2); * ;* DiskNumber - номер диска (0 или 1); * ;* ATAFeatures - "особенности"; * ;* ATASectorCount - количество секторов; * ;* ATASectorNumber - номер начального сектора; * ;* ATACylinder - номер начального цилиндра; * ;* ATAHead - номер начальной головки; * ;* ATAAddressMode - режим адресации (0-CHS, 1-LBA); * ;* ATACommand - код команды. * ;* После успешного выполнения функции: * ;* в ATABasePortAddr - базовый адрес HDD; * ;* в OpTime - момент начала выполнения команды; * ;* в DevErrorCode - ноль. * ;* При возникновении ошибки в DevErrorCode будет * ;* возвращен код ошибки. * ;**************************************************** SendCommandToHDD proc pushad debug 84h mov eax, ds:[046ch] mov ds:[OPERATION_TIMER], eax ; Проверить корректность номера канала mov BX,ds:[CHANNEL_NUMBER] ; Установить базовый адрес cmp BX, 1 db 66h jne @@SecondChannel mov word ptr ds:[ATA_BASE_PORT_ADDR],01f0h db 66h jmp @@PortSelected @@SecondChannel: mov word ptr ds:[ATA_BASE_PORT_ADDR],0170h @@PortSelected: ; Ожидание готовности HDD к приему команды ; Выбрать нужный диск mov DX,ds:[ATA_BASE_PORT_ADDR] add DX,6 ;адрес регистра головок mov AL,ds:[DISK_NUMBER] shl AL,4 or AL,10100000b out DX,AL ; Ожидать, пока диск не будет готов inc DX @@WaitHDReady: ; Проверить время ожидания mov EAX,ds:[046Ch] sub EAX,ds:[OPERATION_TIMER] cmp EAX,BSY_WAIT_TIME db 66h ja @@Err1 ;ошибка тайм-аута ; Прочитать регистр состояния in AL,DX ; Проверить состояние сигнала BSY test AL,80h db 66h jnz @@WaitHDReady ; Проверить состояние сигнала DRQ test AL,08h db 66h jnz @@WaitHDReady ; Загрузить команду в регистры контроллера mov DX,ds:[ATA_BASE_PORT_ADDR] inc DX ;регистр "особенностей" +1 mov AL,ds:[ATA_FEATURES] out DX,AL inc DX ;счетчик секторов +2 mov AL,ds:[ATA_SECTOR_COUNT] out DX,AL inc DX ;регистр номера сектора +3 mov AL,ds:[ATA_SECTOR_NUMBER] out DX,AL inc DX ;номер цилиндра (младший байт) +4 mov AX,ds:[ATA_CYLINDER] out DX,AL inc DX ;номер цилиндра (старший байт) +5 mov AL,AH out DX,AL inc DX ;номер головки/номер диска +6 mov AL,ds:[DISK_NUMBER] shl AL,4 push ax mov al, byte ptr ds:[LBA_24_31] and al, 0fh mov byte ptr ds:[ATA_HEAD],al ;LBA_24_27 pop ax or AL,ds:[ATA_HEAD] or AL,10100000b mov AH,ds:[ATA_ADDRESS_MODE] shl AH,6 or AL,AH out DX,AL ; Послать команду mov AL,byte ptr ds:[ATA_COMMAND] inc DX ;регистр команд out DX,AL mov dword ptr ds:[DEVICE_ERROR_CODE], 0 db 66h jmp @@exit @@Err1: mov dword ptr ds:[DEVICE_ERROR_CODE], 1 db 66h jmp @@exit @@exit: debug 85h popad MyRet SendCommandToHDD endp ;************************************************* ;* ЧТЕНИЕ СЕКТОРА ЖЕСТКОГО ДИСКА В РЕЖИМЕ LBA * ;* Входные параметры передаются через глобальные * ;* перменные: * ;* ChannelNumber - номер канала (1 или 2); * ;* DiskNumber - номер диска на канале (0 или 1); * ;* SectorAddress - номер считываемого сектора. * ;* Сектор считывается основной сегмент данных, * ;* в массив Sector512. * ;************************************************* ReadHDDSector proc pushad debug 86h ; Задать режим LBA mov byte ptr ds:[ATA_ADDRESS_MODE],1 ; Послать команду чтения сектора (с повторами) mov byte ptr ds:[ATA_FEATURES],0 mov byte ptr ds:[ATA_SECTOR_COUNT],1 mov EAX,0 mov ds:[ATA_SECTOR_NUMBER],EAX mov byte ptr ds:[ATA_COMMAND],20h call large near ptr SendCommandToHDD cmp dword ptr ds:[DEVICE_ERROR_CODE],0 db 66h jne @@End ;закончить, сохранив код ошибки ; Ожидать готовность данных HDD mov DX,ds:[ATA_BASE_PORT_ADDR] add DX,7 ;адрес регистра состояния @@WaitCompleet: ; Проверить время выполнения команды mov EAX,ds:[046Ch] sub EAX,ds:[OPERATION_TIMER] cmp EAX, MAX_HDD_WAIT_TIME db 66h ja @@Error1 ;ошибка тайм-аута ; Проверить готовность in AL,DX test AL,80h ;состояние сигнала BSY db 66h jnz @@WaitCompleet test AL,08h ;состояние сигнала DRQ db 66h jz @@WaitCompleet ; Принять сектор mov edi, 0fedbb000h mov EDX,ds:[ATA_BASE_PORT_ADDR] ;регистр данных mov ECX,256 ;число считываемых слов db 67h rep insw ;принять блок данных ; Сбросить признак ошибки mov dword ptr ds:[DEVICE_ERROR_CODE],0 db 66h jmp @@End ; Записать номер ошибки @@Error1: mov dword ptr ds:[DEVICE_ERROR_CODE],1 ;ошибка тайм-аута db 66h jmp @@End @@End: debug 87h popad MyRet ReadHDDSector endp И еще небольшой вопрос, если я пишу в регистр числа секторов, например, 10, при при считывания я должен сделать insw 10*256 раз?
drem1lin Тестируешь на реальной машине или под виртуалкой? Просто виртуальные машины хотя и выдавали бит о наличие поддержки 48бит, но на самом деле её не поддерживали.
На реальной, AIDA бит поодержки показывает. Я разобрался в чем ошибка, там при умножении AX на CX стирается значение DX. а это порт данных. Но пока 2 сектора считать не получается. Пытался 2 раза, в первый раз 18 раз повторился последний байт первого сектора, потом пошел второй сектор и соотвественно 18 байт недокачались. А во второй раз вместо второго сектора туфта было 00 ff повторялися весь сектор. С чем это всвязано не понятно(.
drem1lin После чтения 512байт надо подождать 400нс пока DRQ изменится на 0, а после проверять снова статус готовности.