SMART_RCV_DRIVE_DATA & SMART_SEND_DRIVE_COMMAND

Ce qui se trouve sur cette page n'engage que moi, n'ayant trouvé de documentation précise ce contenu découle directement de mes expériences, c'est donc peut etre totalement faux.
Je compte sur vous pour améliorer la qualité des informations contenue sur cette page…

DeviceIOControl

SMART_RCV_DRIVE_DATA et SMART_SEND_DRIVE_COMMAND sont des un codes de contrôle (dwIoControlCode) utilisé dans l'appel a l'API DeviceIoControl

Déclaration

BOOL DeviceIoControl(
  HANDLE       hDevice,
  DWORD        dwIoControlCode,
  LPVOID       lpInBuffer,
  DWORD        nInBufferSize,
  LPVOID       lpOutBuffer,
  DWORD        nOutBufferSize,
  LPDWORD      lpBytesReturned,
  LPOVERLAPPED lpOverlapped
);

Exemple d'appel

Exemple d'appel en Pascal (parce que moi j'aime bien le Pascal)

var
   vSCIP: TSendCmdInParams;
   vSCOP: TSendCmdOutParams;
   vOutSize: dword;
begin
   ...
  DeviceIoControl(AHandle, SMART_RCV_DRIVE_DATA, @vSCIP, sizeof(TSendCmdInParams), @vSCOP, sizeof(TSendCmdOutParams)+BufferSize, vOutSize, nil);
  // Ou...
  DeviceIoControl(AHandle, SMART_SEND_DRIVE_COMMAND, @vSCIP, sizeof(TSendCmdInParams), @vSCOP, sizeof(TSendCmdOutParams), vOutSize, nil);

Structures

SENDCMDOUTPARAMS

Source : SENDCMDOUTPARAMS chez Microsoft

La Structure SENDCMDOUTPARAMS contient la réponse fournie par l'API.
Cette structure est remplie par l'API pas besoin de la pré-remplir.

typedef struct _SENDCMDOUTPARAMS {
  ULONG        cBufferSize;
  DRIVERSTATUS DriverStatus;
  UCHAR        bBuffer[1];
} SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;

Structure SENDCMDINPARAMS

Source : SENDCMDINPARAMS chez Microsoft

typedef struct _SENDCMDINPARAMS {
  ULONG   cBufferSize; // Taille du buffer de sortie BufferSize dans le tableau ci-dessous
  IDEREGS irDriveRegs; // Strucutre IDEREGS contenant les paramètres d'appel (voir ci-dessous)
  UCHAR   bDriveNumber; // Numero du disk (exemple: avec \\.\PhysicalDrive5, le numéro du disque est 5)
  UCHAR   bReserved[3];
  ULONG   dwReserved[4];
  UCHAR   bBuffer[1]; 
} SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;

Structure IDEREGS

Source : IDEREGS chez Microsoft

La Structure IDEREGS est une sous structure de SENDCMDINPARAMS (voir ci-dessus) contenant les paramètres utiles a l'appel de l'API.

typedef struct _IDEREGS {
  UCHAR bFeaturesReg; // La fonction qu'on appel, Features dans le tableau ci-dessous
  UCHAR bSectorCountReg; // SectorCount dans tableau : Nombre de secteur (je pense...)
  UCHAR bSectorNumberReg; // Sectornumber dans tableau : Numéro du premier secteur (je pense...)
  UCHAR bCylLowReg; // CylLow dans tableau : Cylindre Bas ???
  UCHAR bCylHighReg; // CylHigh dans tableau : Cylindre Haut ???
  UCHAR bDriveHeadReg; //  $A0 or ((DriveNumber and 1) shl 4); en Pascal. Pourquoi ??? je ne sais pas..
  UCHAR bCommandReg; // toujours SMART_CMD  ( $B0) avec SMART_RVC_DRIVE_DATA 
  UCHAR bReserved;
} IDEREGS, *PIDEREGS, *LPIDEREGS;

Features

SMART_RCV_DRIVE_DATA
IDEREGS Features Rôle SENDCMDINPARAMS BufferSize IDEREGS SectorCount IDEREGS SectorNumber IDEREGS CylLow IDEREGS CylHigh
READ_ATTRIBUTES $D0 Récupérer les attributs SMART READ_ATTRIBUTE_BUFFER_SIZE (512) 1 1 SMART_CYL_LOW ($4F) SMART_CYL_HI ($C2)
READ_THRESHOLDS $D1 Récupérer les valeurs de seuil qui indiquent quand un disque est sur le point de tomber en panne.READ_THRESHOLD_BUFFER_SIZE (512) 1 1 SMART_CYL_LOW ($4F) SMART_CYL_HI ($C2)
ENABLE_DISABLE_AUTOSAVE $D2 Active l'attribut optionnel autosave du périphérique lorsqu'il est défini à 1. Désactive cette fonction lorsqu'elle est définie à 0…
SAVE_ATTRIBUTE_VALUES $D3 Demande à l'appareil de sauvegarder ses valeurs d'attribut dans la mémoire non volatile de l'appareil.
EXECUTE_OFFLINE_DIAGS $D4 Permet à l'appareil de commencer à collecter des données SMART en mode hors ligne ou d'exécuter une routine de test d'autodiagnostic en mode captif ou hors ligne.
SMART_READ_LOG $D5 Récupère les Logs.
SMART_WRITE_LOG $D6 Écrit le nombre indiqué de secteurs de données de 512 octets dans les logs
RETURN_SMART_STATUS $DA Récupère l'état de fiabilité de l'appareil.
ENABLE_DISABLE_AUTO_OFFLINE $DB Active ou Désactive le mode hors ligne
SMART_SEND_DRIVE_COMMAND
IDEREGS Features Rôle SENDCMDINPARAMS BufferSize IDEREGS SectorCount IDEREGS SectorNumber IDEREGS CylLow IDEREGS CylHigh
ENABLE_SMART $D8 Active SMART 0 1 1 SMART_CYL_LOW ($4F) SMART_CYL_HI ($C2)
DISABLE_SMART $D9 Désactive SMART

Types communs pour les Features

TicSendCmdOutParams

Le type TicSendCmdOutParams est une variante du type TSendCmdOutParams présent dans l'unité jwaWinIoCtl.pas (Ici on parle Pascal et Lazarus plus précisément) auquel j'ai enlevé le dernier membre (bBuffer: array [0..0] of BYTE) pour qu'il puisse être inclus dans un type TSCOP_XXXXXXX.
Bon, je ne sais pas si c'est une bonne idée, mais c'est la mienne a l'instant T.
Et ça fonctionne en plus !

   TTicSendCmdOutParams = packed record
      cBufferSize:  DWORD;            // Size of bBuffer in bytes
      DriverStatus: TDriverStatus;    // Driver status structure.
   end;

READ_ATTRIBUTES

le SCOP (SendCmdOutParams) est suivi de deux Byte A et B dont je ne connais pas l'utilité.
Puis un tableau de 30 attributs SMART (TSmartAttrs)
Et de quelques byte, ici pour combler l'espace.

   TSCOP_SmartAttrs = packed record
      SCOP:     TTicSendCmdOutParams; (voir ci-dessus)
      A, B:     byte; // ???
      Results:  TSmartAttrs; //array[0..29] of TSmartAttr; 
      Reserved: array[1..150] of byte; // pour arriver a 512
   end;

Avec les types suivants

   TSmartAttr = packed record
      ID:    byte;
      Flags: word;
      Current, Worst: byte;
      Raw:   array[0..5] of byte; //[01 23 45 67 89 AB] correspond a $AB8967452301
      Reserved: byte;
   end;
 
   TSmartAttrs = array[0..29] of TSmartAttr; // max of 30 attributes

Les Membre d'un Attribut

D’après ce que je constate il peut y avoir au maximum 30 attributs

ID
Flag
Current
Worst
Raw

READ_THRESHOLDS

le SCOP (SendCmdOutParams)
suivi d'un Word (2oct) indiquant la numéro de révision.
Puis un tableau de 30 Thresholds SMART (TSmartThresholds)
Et de quelques byte, ici pour combler l'espace.

   TSCOP_SmartThresholds = packed record
      SCOP : TTicSendCmdOutParams;
      RevNumber : word; // 2 oct
      Results : TSmartThresholds; // 360 oct
      Reserved : array[0..148] of byte; // 149 oct
      Chksum: byte; // 1 oct
      // total 512 = READ_THRESHOLD_BUFFER_SIZE
   end;

Avec les types suivants

   TSmartThreshold = packed record
      ID: byte; //1 oct
      Threshold : byte; //1 oct
      Reserved : array[0..9] of byte; //10 oct
      // Total = 12 oct
   end;
 
   TSmartThresholds = array[0..C_SMART_MAX_ATTRS] of TSmartThreshold; //12x30 = 360 oct

Les Membres de Threshold

30 max comme le nombre d'attributs

ID

ID de l'attribut auquel correspond ce Threshold

Threshold

Valeur sur 1 octet, seuil indiquant quand un disque est sur le point de tomber en panne.

Interpretation du Threshold

Pour l'instant, je ne sais pas trop.

Dés que j'ai plus d'infos je les mettrai ici !

ENABLE_DISABLE_AUTOSAVE

SAVE_ATTRIBUTE_VALUES

EXECUTE_OFFLINE_DIAGS

SMART_READ_LOG

SMART_WRITE_LOG

ENABLE_SMART

On peut estimer que si la commande DeviceIOControl renvoi True alors le SMART est activé.

DISABLE_SMART

RETURN_SMART_STATUS

ENABLE_DISABLE_AUTO_OFFLINE

Sources

Vous pourriez laisser un commentaire si vous étiez connecté.