Всем привет!
Разбираюсь с контроллером AHCI в реальном режиме для своей ОС.
Как оказалось, биос не утруждает себя инициализацией регистров AHCI, поэтому всё нужно проделывать с нуля.
Сейчас по классу
Разбираюсь с контроллером AHCI в реальном режиме для своей ОС.
Как оказалось, биос не утруждает себя инициализацией регистров AHCI, поэтому всё нужно проделывать с нуля.
Сейчас по классу
010601h нахожу его в пространстве PciCfg, беру BAR5 и попадаю в память MMIO. Дальше прописываю указатели в регистры "Command List" и "FIS base addr", заполняю остальные регистры и отправляю в хард ATA-команду IDENTIFY DEVICE = ECh. Проблема в том, что при первом запросе девайс исправно возвращает сектор с инфой, но после этого он остаётся занятым (led на морде непрерывно мигает), в результате чего не могу вогнать его в готовность для последующих запросов. Имеются все доки на AHCI + описание на wiki, однако уже третий день не могу разобраться. Может кто решал такого рода проблему? Вот фрагмент кода на ассемблере:
C-подобный:
;//*********************************************************************
;//*************** ИНИЦАЛИЗАЦИЯ КОНТРОЛЛЁРА AHCI ***********************
;//*********************************************************************
jmp @initAhci
;//----- Дождаться очистки бита Command.CtrlRunning(15)
StopAhciPort:
mov edi,[ahciPort]
mov eax,[fs:edi+18h] ;// Command Register
and al,not 10001b ;// сбросить биты Command.ST + FRE
mov [fs:edi+18h],eax
@@: mov eax,[fs:edi+18h] ;// Command Register
bt ax,15 ;// bitTest Command.CR
jc @b
bt ax,14 ;// bitTest Command.FR
jc @b
ret
StartAhciPort:
mov edi,[ahciPort]
@@: mov eax,[fs:edi+18h] ;// Command Register
bt ax,15 ;// bitTest Command.CR
jc @b
or al,10001b ;// взвести биты Command.ST + FRE
mov [fs:edi+18h],eax
ret
@initAhci:
;//----- 1. Ждать освобождения контроллера
call StopAhciPort
;//----- 2. Очистить выделенную 4Кб память
mov edi,0x8000
xor eax,eax
mov ecx,1024
rep stosd
;//----- 3. Настроить регистры Command и FIS
mov edi,[ahciPort]
mov dword[fs:edi+0x00],0x8000 ;// регистр "Command List Address"
mov dword[fs:edi+0x08],0x8400 ;// регистр "FIS Base Address"
;//----- 4. Настроить CmdHeader первого слота
mov dword[0x8000+0x00],0x00010045 ;// DW0.PRDTL = 1 запись
; mov byte[0x8000+0x00],0x45 ;// DW0.CFL = 5 двордов (размер FIS) + 4 (Write)
mov dword[0x8000+0x04],0 ;// DW1.PRDC = счётчик 512 байт
mov dword[0x8000+0x08],0x8400 ;// DW2.CTBA = адрес CmdTable
;//----- 5. Адрес и размер приёмного буфера
mov word[0x8400+0x80],0x9000 ;// Data Base Address
mov word[0x8400+0x8C],512 ;// Byte Counter
;//----- 6. Ждать освобождения контроллера
call StartAhciPort
;//*********************************************************************
;//******************* КОНЕЦ ИНИЦАЛИЗАЦИИ ******************************
;//*********************************************************************
mov edi,[ahciPort]
mov ecx,[fs:edi] ;// регистр "Command List"
mov [cursor],(160*5)+36
call PrintHex
mov edi,[ahciPort]
mov ecx,[fs:edi+0x08] ;// регистр "FIS Base Address"
mov [cursor],(160*6)+36
call PrintHex
;//----- Оформляем FIS "Identify Device" -----------------
mov edi,[ahciPort]
mov ebx,[fs:edi+0x24] ;// регистр "Signature"
mov eax,0x00EC8027 ;// EC=код, 80=Write, 27=H2D
cmp ebx,0x00000101 ;// это SATA диск ?
je @f
mov eax,0x00A18027 ;// значит SATAPI: A1=код, 80=Write, 27=H2D
@@: mov dword[0x8400],eax
;//----- Рег "Command Issue" - отправить запрос через слот(1) !!!
mov edi,[ahciPort]
mov dword[fs:edi+0x38],1
;//----- Ждать ответных данных от девайса..
@@: mov eax,[fs:edi+0x38]
or eax,eax
jnz @b