Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

spindown by DeviceIoControl [Win2k, WinXP]


Страницы:   1 2

kernel ©   (2007-11-05 17:16:00) 

Доброго времени суток, уважаемые Delphi-кодеры :)
Необходимо остановить шпиндель жесткого диска с помощью DeviceIoControl. Прыгать в нулевое кольцо и посылать там в порт $0E6 не хочется, тем более вся программа построена на DeviceIoControl.

Думал, все обойдется посылкой $0E6 в регистр "command", дык не получается :: сложилось впечатление, что винту из-под DeviceIoControl можно посылать ограниченное число команд.

На десерт неработающий кусок кода:

SCIP_PM.cBufferSize:=0;
SCIP_PM.irDriveRegs.bFeaturesReg:=0;
SCIP_PM.irDriveRegs.bSectorCountReg:=0;
SCIP_PM.irDriveRegs.bSectorNumberReg:=0;
SCIP_PM.irDriveRegs.bCylLowReg:=0;
SCIP_PM.irDriveRegs.bCylHighReg:=0;
SCIP_PM.irDriveRegs.bDriveHeadReg:=$E0;//пробовал $A0 or ((DRVNUM and 1) shl 4);
SCIP_PM.irDriveRegs.bCommandReg:=$E6;
SCIP_PM.bDriveNumber:=DRVNUM;
if not DeviceIoControl(hSMARTIOCTL[DRVNUM], DFP_SEND_DRIVE_COMMAND,
@SCIP_PM, sizeof(TSENDCMDINPARAMS)-1, @SCOP_PM[DRVNUM],
 sizeof(TSENDCMDOUTPARAMS)-1 + SCIP_PM.cBufferSize, c, nil) then showmessage(PChar('Message: '+SysErrorMessage(GetLastError)+
   ' | Code: '+IntToStr(GetLastError)));


Всем заранее спасибо :)


kernel   (2007-11-07 10:25:00) [21]

теперь не знаю как его снова запустить :(


Dimaxx   (2007-11-06 21:13:00) [22]

Надо смотреть. Если стоит "Стандартный двухканальный PCI-IDE контроллер", то будет работать. А если стоит родной драйвер - фиг. У меня на JMicron'e ни каким образом нельзя было получить служебный сектор - ни через SCSI, ни через IDE. Откатил на стандартный драйвер - с полпинка заработало.


kernel   (2007-11-06 17:23:00) [23]

проверял на NVIDIA nForce 430B (6150)  -  все нормально :)


Andrey_rus   (2007-11-06 17:06:00) [24]


> IOCTL_IDE_PASS_THROUGH


Не будет работать с драверами отличными от стандартных. Например - NVIDIA (nForce). Хотя... Если у кого-нибудь есть возможность проверьте пожалуйста.


kernel   (2007-11-06 16:58:00) [25]

Завалялся винт у меня (SAMSUNG SP0802) - с трупнутой поверхностью. Думаю куда-нибудь двигатель его применить...


Dimaxx   (2007-11-06 16:18:00) [26]


> с командой я не ошибся ($E6)

Но ты так и не сказал для чего тебе это нужно было... :)


kernel   (2007-11-06 16:08:00) [27]

Dimaxx, с командой я не ошибся ($E6)

> Dimaxx ©   (05.11.07 20:56) [3]
>
> Вообще-то в примерах везде видел (получение СМАРТ, получение
> инфы о винте и т.п.)
>
> SCIP_PM.irDriveRegs.bSectorCountReg:=1;
> SCIP_PM.irDriveRegs.bSectorNumberReg:=1;
>
> почему ты пытался с 0 - не ясно.

Ставил 0, т.к. это то состояние регистров ч\з которое мне удавалось вырубить винт (через hddl21)
А дело было было в том, что я не мог найти IOCTL_ код, для этой команды (в DeviceIoControl(hDevice, IOCTL_... )
В общем всем огроооооооомное спасибо, вот работающий код (случайно наткнулся на http://www.delphi-forum.de/printview.php?t=75438&start=0&sid=cd1c3a8937a3e6a42aff7df3fcee434d):

Type  
TIDERegs = packed record  
   bFeaturesReg     : Byte; // Used for specifying SMART "commands".  
   bSectorCountReg  : Byte; // IDE sector count register  
   bSectorNumberReg : Byte; // IDE sector number register  
   bCylLowReg       : Byte; // IDE low order cylinder value  
   bCylHighReg      : Byte; // IDE high order cylinder value  
   bDriveHeadReg    : Byte; // IDE drive/head register  
   bCommandReg      : Byte; // Actual IDE command.  
   bReserved        : Byte; // reserved for future use.  Must be zero.  
 end;  
 IDEREGS   = TIDERegs;  
 PIDERegs  = ^TIDERegs;  

TIdSector = packed record  
   wGenConfig                 : Word; //00  
   wNumCyls                   : Word;  
   wReserved                  : Word;  
   wNumHeads                  : Word;  
   wBytesPerTrack             : Word;  
   wBytesPerSector            : Word;  
   wSectorsPerTrack           : Word;  
   wVendorUnique              : Array[0..2] of Word;  
   sSerialNumber              : Array[0..19] of Char; //10-19  
   wBufferType                : Word;  
   wBufferSize                : Word;  
   wECCSize                   : Word;  
   sFirmwareRev               : Array[0..7] of Char;  //23-26  
   sModelNumber               : Array[0..39] of Char; //27-46  
   wMoreVendorUnique          : Word;  
   wDoubleWordIO              : Word;  
   wCapabilities              : Word;  
   wReserved1                 : Word;  
   wPIOTiming                 : Word;  
   wDMATiming                 : Word;  
   wBS                        : Word;  
   wNumCurrentCyls            : Word;  
   wNumCurrentHeads           : Word;  
   wNumCurrentSectorsPerTrack : Word;  
   ulCurrentSectorCapacity    : ULONG; //57-58  
   wMultSectorStuff           : Word;  
   ulTotalAddressableSectors  : ULONG; //60-61  
   wSingleWordDMA             : Word;  
   wMultiWordDMA              : Word;  //63  
   wFlowControlPIOSupported   : Word;  //64  
   wMinimumMultiWordDMA       : Word;  //65  
   wRecommendedMultiWordDMA   : Word;  //66  
   wMinimumPIOCycleWOFlow     : Word;  //67  
   wMinimumPIOCycleIORDYFlow  : Word;  //68  
   bReserved1                 : Array[0..21] of Byte; //69-79  
   wMajorVersionNumber        : Word;  //80  
   wMinorVersionNumber        : Word;  //81  
   wCommandSetSupported       : Word;  //82  
   wCommandSetSupported2      : Word;  //83  
   wCommandSetExtension       : Word;  //84  
   wCommandSetFeatureEnabled1 : Word;  //85  
   wCommandSetFeatureEnabled2 : Word;  //86  
   wCommandSetFeatureEnabled3 : Word;  //87  
   wUltraDMAMode              : Word;  //88  
   wTimeRequiredErase         : Word;  //89  
   wTimeRequiredEnhancedErase : Word;  //90  
   wAbleMode                  : Word;  //91  
   bReserved2                 : Array[0..71] of Byte; //92-127  
   wSecurityModeFeature       : Word;  //128  
   wCurrentFeatureOption      : Word;  //129  
   wReserved2                 : Word;  //130  
   wInitialPowerMode          : Word;  //131  
   bReserved3                 : Array[0..247] of Byte; //132-255  
 end;  
 PIdSector = ^TIdSector;

const  
 BufferSize = SizeOf(TIDERegs)+4;  
 IOCTL_IDE_PASS_THROUGH        = $0004d028;

implementation

{$R *.dfm}

Function IdeRegPassThrough(Device: String; var ideregs: TIDERegs ): Boolean;  
var  
 ret:BOOL;  
 hDevice : THandle;  
 cbBytesReturned : DWORD;  
 pInData : PIDERegs;  
 pOutData : Pointer;  
 Buffer : Array[0..BufferSize-1] of Byte;  
begin  
 Result := False;  
 FillChar(Buffer,BufferSize,#0);  

 hDevice := CreateFile( PChar(Device), GENERIC_READ or GENERIC_WRITE,  
   FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0 );  
 if hDevice=INVALID_HANDLE_VALUE then Exit;  
 try  
   pInData := @Buffer;  
    pOutData := pInData;  
   pInData^ := ideregs;  
   ret := DeviceIoControl( hDevice, IOCTL_IDE_PASS_THROUGH, @Buffer, BufferSize, @Buffer, BufferSize, cbBytesReturned, nil );  
   if not ret then begin  
     Exit;  
   end;  
   ideregs := PIDERegs(pOutData)^;  
 finally  
   CloseHandle(hDevice);  
 end;  
 Result := True;  
end;  

function SendToSleep(Device: String): Boolean;
var  
 ideregs : TIDERegs;  
begin  
 Result := False;  
 with ideregs do  
 begin  
   bFeaturesReg     := 0;  
   bSectorCountReg  := 0;  
   bSectorNumberReg := 0;  
   bCylLowReg       := 0;  
   bCylHighReg      := 0;  
   bDriveHeadReg    := $A0;  
   bCommandReg      := $E6;  
   bReserved        := 0;  
 end;  
 if not IdeRegPassThrough(Device, ideregs ) then Exit else Result := True;  
end;

//Label1.caption:= BoolToStr(SendToSleep('\\.\PhysicalDrive0'));


Dib@zol   (2007-11-06 15:48:00) [28]

Любопытно... А может это вовсе и не запрещение на посыл команды? Попробуй сделать цикл вызовов с размером этой самой области данных от 1 скажем до high(DWORD). И анализируй возвращённый результат. Если он не 122, то ура - нужный размер найден.
ЗЫ Такой способ однажды помог мне экспериментально выяснить размер структуры под системный диалог открытия файла. И только потом я дотумкал посмотреть как это реализовано в VCL :)


kernel   (2007-11-06 15:40:00) [29]

при подаче команды в винт, пишется:
Message: Область данных, переданная по системному вызову, слишком мала
Code: 122


Dimaxx   (2007-11-06 15:00:00) [30]

По крайней мере инфа со служебного сектора винта по команде $EC (вроде такая) нормально получается. Значит, что-то можно, а что-то нельзя.


Dimaxx   (2007-11-06 14:58:00) [31]

А зачем вырубать накопитель в винде, да еще так, что его можно включить только по сбросу?? Пиши драйвер свой, чтобы был полный доступ.


kernel   (2007-11-06 14:01:00) [32]


> Е6 тебе не даст выполнить драйвер HDD. Да и остальные команды
> управления движком тоже.

Зачем же тогда придумали структуру IDERegs? Чтобы половину команд в регистры нельзя было заслать что-ли? :)


Dimaxx   (2007-11-05 21:19:00) [33]

Даже если тебе удасться нормально заставлять винт выключать движок и включать его - не советую этим пользоваться. Может я и ошибаюсь, но ты хочешь выключать винт на время его "неиспользования". Спешу тебя огорчить - частые включения/выключения сильно снижают срок службы накопителя. Пусть уж лучше он работает круглые сутки.


Dimaxx   (2007-11-05 21:13:00) [34]

Ты не перепутал с командами?

E0 (Standby Mode)

Выключает двигатель шпинделя, при доступе снова автоматически включается.

E1 (Idle Mode)

Выключает двигатель шпинделя.

E2 (Auto Power Down)

Выключает двигатель шпинделя, после доступа снова автоматически выключается, время устанавливается шагами по 5 секунд (1F2h).

E3 (Auto Power Down)

Включает двигатель шпинделя и далее как команда E2h.

E5 (Read Power Mode)

Читает в 1F2h состояние двигателя шпинделя.

E6 (Sleep Mode)

Выключает накопитель, включение только через сброс (программный или аппаратный).


Е6 тебе не даст выполнить драйвер HDD. Да и остальные команды управления движком тоже.


Dimaxx   (2007-11-05 20:56:00) [35]

Вообще-то в примерах везде видел (получение СМАРТ, получение инфы о винте и т.п.)

SCIP_PM.irDriveRegs.bSectorCountReg:=1;
SCIP_PM.irDriveRegs.bSectorNumberReg:=1;

почему ты пытался с 0 - не ясно.


kernel   (2007-11-05 19:52:00) [36]

Вырубить ч\з DevIOCtl, вроде, должно быть можно. Насколько мне известно, ограничений на команды управления винтом быть не должно (ч\з регистры). А гугль ничего мне не дал :(


Dib@zol   (2007-11-05 19:45:00) [37]

Up.
Немного сомневаюсь, что винда вообще даст это сделать из-под ДивайсИоКонтрола, так как функция замедления/остановки шпинделя в большинстве случаев нужна только дровам ХДД. Тут только разве что вручную собрать реостат с управлением от ЮСБ и подключить его к шнуру питания винта :)

Впрочем, я где-то в Инете натыкался на любопытную прогу уменьшения скорости сидюшного дисковода, вроде даже опенсорсную... А CD привод он вроде как тоже SCSI. Вощем, гугль в руки и бегом ;)


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо