• XSS.stack #1 – первый литературный журнал от юзеров форума

SATA в режиме AHCI

Roller

RAID-массив
Пользователь
Регистрация
26.05.2020
Сообщения
71
Решения
1
Реакции
54
Всем привет!
Разбираюсь с контроллером 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

VirtualBox_Codeby_31_05_2025_01_56_06.png
 
Может поможет,
бит на запись убираем:
mov dword [0x8000+0x00], 0x00010005h

сброс и установка:
and ax, 0xFFEE
or ax, 0x0011
Просмотри получше al и тд

И вроде так:
mov word [0x8400+0x8C], 511

Без теста тяжело сказать
 
бит на запись убираем
Там столько битовых масок, что совсем запутался.
Я грешил на кривое оформление FIS, а оказывается и правда только бит(W) нужно было сбросить.
Теперь и SATA(ECh) и SATAPI(A1h) один и тот-же код исправно отрабатывает. Спасибо больше за наводку - буду знать.
PS: а с and/or нормально всё , т.к. для and я установил там инверсию and al, not 10001b
 
Может поможет,
бит на запись убираем:
mov dword [0x8000+0x00], 0x00010005h

сброс и установка:
and ax, 0xFFEE
or ax, 0x0011
Просмотри получше al и тд

И вроде так:
mov word [0x8400+0x8C], 511

Без теста тяжело сказать
It seems like AHCI is 99% legwork + 1% bitmask.)
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх