Отключается режим DMA для IDE контроллера (драйвер фильтр)
От: Srv  
Дата: 24.04.06 16:04
Оценка:
Всем привет!
Буду рад если кто-нибудь сможет мне помочь.
Дело в том, что написал простой драйвер фильтр для IDE контроллера, ставлю его в систему, создаю в драйвере именованный DeviceObject, создаю символическую ссылку и общаюсь с ним через ioctl, драйвер шлет smart команды по портам в IDE контроллер. После не продолжительной посылки, канал контроллера начинает работать в PIO режиме (все жутко тормозит), не пойму почему DMA отрубается. Если не слать ioctl, а просто установить дравйвер и все, то все работает в DMA нормально. Подскажите куда копать, может я не правильно написал фильтр.
Re: Отключается режим DMA для IDE контроллера (драйвер фильт
От: Alter_ Украина http://alter.org.ua
Дата: 24.04.06 21:16
Оценка: 1 (1)
Здравствуйте, Srv, Вы писали:

1. как именно вы шлете команды ?
2. не возникает ли ситуация, когда ваши команды отправляются в активный канал (какое-то устройство что-то делает, а драйвер ожидает прерывания). В этом случае нарушится исполнение текущей команды, далее таймаут (и тормоза), сброс шины, и после нескольких таких штук — автоматический переход в ПИО для повышения стабильности.
3. на некоторых контроллерах и/или с некоторыми драйверами нельзя трогать один канал, пока занят другой.

Попробуйте взять исходники atapi из DDK NT4, сборать версию с логами, да посмотреть, что происходит. ДМА там правде нет. Хотя, если найдете исходники NT4, там ДМА для Интела присутствует.
Или экстремальный вариант — попробовать debug версию http://alter.org.ua/sofw/win/uniata для того же разбирательства с происходящим.
--
Alter, http://alter.org.ua
Re: Отключается режим DMA для IDE контроллера (драйвер фильт
От: Maxim S. Shatskih Россия  
Дата: 25.04.06 09:05
Оценка: 1 (1) +1
>общаюсь с ним через ioctl, драйвер шлет smart команды по портам в IDE контроллер.

Такой драйвер вообще не может нормально работать. Ничего удивительного в том, что отрубается DMA, нету.

Лезть в порты железки может только драйвер этой железки, т.е. atapi.sys и минидрайвер. Когда сбоку появляется еще какой-то код, который тоже лезет в порты, то порты от этого сходят с ума дело в том, что нет никакой возможности синхронизировать эти 2 кода.

Я почти уверен, что пропадание DMA связано с полным крахом контроллера, который был вылечен resetом из штатного atapi.sys/pciidex.sys, причем после ресета DMA было на всякий случай выключено.

Нужен SMART? Дык есть IOCTLs для SMART. Есть еще IOCTL_IDE_PASS_THROUGH/IOCTL_ATA_PASS_THROUGH, но они по-разному работают в разных версиях виндов и имеют ограничения.

Ничего кроме этого нету, если не хочется иметь вот подобные глюки.
Занимайтесь LoveCraftом, а не WarCraftом!
Re[2]: Отключается режим DMA для IDE контроллера (драйвер фи
От: Srv  
Дата: 27.04.06 07:13
Оценка:
MSS>Нужен SMART? Дык есть IOCTLs для SMART. Есть еще IOCTL_IDE_PASS_THROUGH/IOCTL_ATA_PASS_THROUGH, но они по-разному работают в разных версиях виндов и имеют ограничения.

Да нужен SMART, но драйвер IDE не хочет работать нормально с

//
// Feature register defines for SMART "sub commands"
//

#define READ_ATTRIBUTES         0xD0
#define READ_THRESHOLDS         0xD1


и кроме того нужен SMART для RAID. Ну напрмер как в проге activesmart-scsi.
Re[2]: Отключается режим DMA для IDE контроллера (драйвер фи
От: Srv  
Дата: 27.04.06 07:15
Оценка:
Здравствуйте, Alter_, Вы писали:

A_>1. как именно вы шлете команды ?


вот так шлю


BOOL CheckHDDState(ULONG StateReg, ULONG TimeOut, UCHAR SetFlags, UCHAR ClearFlags, ULONG msFreq)
{
    UINT64    Ticks = QueryTickCount(msFreq);
    UCHAR    Value, V, IsFirst = TRUE;
    UCHAR    Flags = SetFlags | ClearFlags;

    do
    {
        Value = _INP(StateReg);
        if ((Value & Flags) == SetFlags)
            return TRUE;
    }
    while ((QueryTickCount(msFreq) - Ticks) <= TimeOut);

    return FALSE;
}

BOOL WaitForDeviceReady(ULONG BasePort, ULONG Disk, ULONG msFreq)
{
    if (!CheckHDDState(BasePort + 7, 3 * 1000, 0, BSY, msFreq))
        return FALSE;
    _OUTP(BasePort + 6, CB_DH_SELECT | (Disk << 4));
    if (CheckHDDState(BasePort + 7, 3, DRDY, BSY|DF, msFreq))
        return TRUE; 
    return FALSE;
}


VOID DELAY400NS(ULONG CtrlPort)
{
    _INP(CtrlPort);
    _INP(CtrlPort);
    _INP(CtrlPort);
    _INP(CtrlPort);
}

VOID ReadDataFromDevice(ULONG BasePort, VOID* DeviceData, ULONG Len)
{
    _asm
    {
        push edi
        mov  edi, DeviceData
        mov  ecx, Len
        mov  edx, BasePort
        cld
        rep  insw
        pop  edi
    }
}

BOOL DO_SMART_RCV_DRIVE_DATA(PDEVICE_EXTENSION pDevExt, PSENDCMDINPARAMS SCIP, PSENDCMDOUTPARAMS SCOP)
{
    PIDEREGS    IDERegs;
    ULONG        BasePort = 0, CtrlPort = 0;
    ULONG        BasePort_ = 0;
    BOOL        Result;
    ULONG        i;

    BasePort = pDevExt->portconf.BasePort;
    CtrlPort = pDevExt->portconf.CtrlPort;

    if ((BasePort == 0) || (CtrlPort == 0))
        return FALSE;

    if (SCIP->bDriveNumber >= pDevExt->DisksCount)// Проверить номер переданного диска
        return FALSE;

    if (!WaitForDeviceReady(BasePort, SCIP->bDriveNumber, pDevExt->msFreq))// Ждать пока контроллер не освободится
        return FALSE;

    _OUTP(CtrlPort, CB_DC_NIEN);// Запретить прерывания

    IDERegs = &SCIP->irDriveRegs;// Записать параметры переданной команды
    BasePort_ = BasePort;
    _OUTP(++BasePort_, IDERegs->bFeaturesReg);
    _OUTP(++BasePort_, IDERegs->bSectorCountReg);
    _OUTP(++BasePort_, IDERegs->bSectorNumberReg);
    _OUTP(++BasePort_, IDERegs->bCylLowReg);
    _OUTP(++BasePort_, IDERegs->bCylHighReg);
    _OUTP(++BasePort_, IDERegs->bDriveHeadReg);
    _OUTP(++BasePort_, IDERegs->bCommandReg);// Послать переданную команду

    Result = CheckHDDState(BasePort_, CMD_TIMEOUT, DRDY|DRQ, BSY|DF|ERR, pDevExt->msFreq);// Ждать готовности команды
    if (Result)
        ReadDataFromDevice(BasePort, &SCOP->bBuffer, SECTOR_SIZE/2);// Считать результат выполнения команды
    _OUTP(CtrlPort, 0);// Разрешить прерывания

    return Result;
}


Думаю из исходника понятно как это происходит вызываю DO_SMART_RCV_DRIVE_DATA...
Re[3]: Отключается режим DMA для IDE контроллера (драйвер фи
От: Alter_ Украина http://alter.org.ua
Дата: 27.04.06 10:23
Оценка:
Здравствуйте, Srv, Вы писали:

A_>>1. как именно вы шлете команды ?

Srv>вот так шлю

понял.

На самом деле я тут подумал, можно сделать так, чтобы работало.

1. Для начала заблокировать поступление новых команд в контроллер — сложить в свою очередь.
2. Подождать, пока стихнет активность на канале. (AltStatus рулит).
3. Узнать, разрешены ли в контроллере прерывания от устройств, если да, запомнить и запретить
4. Делаете то, что вам нужно.
5. Вычитываете Status, чтобы стбросить прерывание, обязательно проверяете Busmaster DMA статус на предмет прерывания, и если установлено — сбрасываете (DMA STOP)
6. восстанавливаете разрешение прерываний (если нужно, см. п.3)
7. посылаете в драйвер задержаные в п.1 запросы.
--
Alter, http://alter.org.ua
Re[4]: Отключается режим DMA для IDE контроллера (драйвер фи
От: Srv  
Дата: 27.04.06 13:52
Оценка:
Здравствуйте, Alter_, Вы писали:

A_>На самом деле я тут подумал, можно сделать так, чтобы работало.


Ну на счет очереди я и сам знаю, только что то мне в драйвер фильтр (верхнеуровневый для класса устройств hdc) ни каких запросов не приходит, как то даже странновато. А если очередь не делать, ну то есть сделать критическую секцию, когда приходит запрос заходим в к.с. затем делаем что нужно и выходим из к.с.
А вот как сделать DMA STOP и т.д. не знаю, посмотреть в спецификации нужно да? можно ли на нее ссылочку.
Re[5]: Отключается режим DMA для IDE контроллера (драйвер фи
От: Alter_ Украина http://alter.org.ua
Дата: 27.04.06 15:56
Оценка:
Здравствуйте, Srv, Вы писали:

Srv>Здравствуйте, Alter_, Вы писали:


A_>>На самом деле я тут подумал, можно сделать так, чтобы работало.


Srv>Ну на счет очереди я и сам знаю, только что то мне в драйвер фильтр (верхнеуровневый для класса устройств hdc) ни каких запросов не приходит, как то даже странновато. А если очередь не делать, ну то есть сделать критическую секцию, когда приходит запрос заходим в к.с. затем делаем что нужно и выходим из к.с.

Srv>А вот как сделать DMA STOP и т.д. не знаю, посмотреть в спецификации нужно да? можно ли на нее ссылочку.

Можете в сорцах вот здесь
http://alter.org.ua/soft/win/uni_ata/index.php
посмотреть, а можете погуглить. У меня она есть, но где взял не помню.
--
Alter, http://alter.org.ua
Re[3]: Отключается режим DMA для IDE контроллера (драйвер фи
От: Maxim S. Shatskih Россия  
Дата: 28.04.06 22:26
Оценка:
Одно из решений.

Ставишь PnP бас-фильтры над всеми объектами, что растут из IDE контроллеров.

В них есть операция "закрыть/открыть". Если фильтр закрыт, то все ирпы уводятся в очередь в фильтре и висят там, пока фильтр не открою. Открытие фильтра шлет все ирпы из очереди вниз. Закрытие фильтра ждет, пока не завершатся все ирпы, уже прошедшие вниз в ИДЕ контроллер.

Вот из-под такого фильтра, закрыв его, еще можно попробовать лазить в железку ИДЕ. Но не иначе.
Занимайтесь LoveCraftом, а не WarCraftом!
Re[3]: Отключается режим DMA для IDE контроллера (драйвер фи
От: Maxim S. Shatskih Россия  
Дата: 28.04.06 22:28
Оценка:
Ассемблер-то хоть можно убрать? READ_PORT_BUFFER_USHORT у нас есть вместо rep insw.
Занимайтесь LoveCraftом, а не WarCraftом!
Re[4]: Отключается режим DMA для IDE контроллера (драйвер фи
От: Srv  
Дата: 29.04.06 16:19
Оценка:
Здравствуйте, Maxim S. Shatskih, Вы писали:

MSS>Одно из решений.

А тогда вопрос, когда ОС шлет IRP IDE контроллеру? А то у меня что счетчик IRP увеличивается только тогда когда приходят мои IRP.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.