Einzelnen Beitrag anzeigen

c.wuensch

Registriert seit: 19. Dez 2004
Ort: Münster
96 Beiträge
 
#1

Hilfe bei Übersetzung von C nach Delphi

  Alt 14. Jul 2008, 22:11
Hi an alle,

Ich hab die Frage hier schonmal gestellt, aber mach jetzt nochmal einen neuen Thread damit der Titel besser passt.

Ich möchte den Power-Status (aktiv / Standby) einer Festplatte auslesen.

Folgender Delphi-Code bewirkt, dass die Platte in Standby versetzt wird (Dank an hathor):
Delphi-Quellcode:
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;
 
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'));

Folgender C-Code stammt aus dem Linux-Tool hdparm und bewirkt das Auslesen des Status:
Code:
  __u8 args[4] = {ATA_OP_CHECKPOWERMODE1,0,0,0};
  const char *state;
  if (do_drive_cmd(fd, args)
    && (args[0] = ATA_OP_CHECKPOWERMODE2) /* (single =) try again with 0x98 */ 
    && do_drive_cmd(fd, args)) { 
      err = errno;
      state = "unknown";
    } else { 
      state = (args[2] == 255) ? "active/idle" : "standby";
    } 
  printf(" drive state is: %s\n", state);
Hier sind die Flags dazu:
Code:
ATA_OP_CHECKPOWERMODE1   = 0xe5,
ATA_OP_CHECKPOWERMODE2   = 0x98,
ATA_OP_STANDBYNOW1      = 0xe0,
ATA_OP_SLEEPNOW1      = 0xe6, // das hier wird im Delphi-Code schonmal benutzt
ATA_OP_SLEEPNOW2      = 0x99,
ATA_OP_SETIDLE1      = 0xe3,
Und hier ist die Funktion do_drive_cmd, die dadurch aufgerufen wird:
Code:
int do_drive_cmd (int fd, unsigned char *args)
{
#ifdef SG_IO

   struct ata_tf tf;
   void *data = NULL;
   unsigned int data_bytes = 0;
   int rc;

   if (args == NULL)
      goto use_legacy_ioctl;
   /*
    * Reformat and try to issue via SG_IO:
    */
   if (args[3]) {
      data_bytes = args[3] * 512;
      data      = args + 4;
   }
   tf_init(&tf, args[0], 0, args[1]);
   tf.lob.feat = args[2];
   if (tf.command == ATA_OP_SMART) {
      tf.lob.nsect = args[3];
      tf.lob.lbal = args[1];
      tf.lob.lbam = 0x4f;
      tf.lob.lbah = 0xc2;
   }

   rc = sg16(fd, SG_READ, &tf, data, data_bytes, 0);
   if (rc) {
      if (rc == -1)
         goto use_legacy_ioctl;
      errno = rc;
      rc = -1;
   } else if (tf.status & (ATA_STAT_ERR | ATA_STAT_DRQ)) {
      if (verbose)
         fprintf(stderr, "I/O error, ata_op=0x%02x ata_status=0x%02x ata_error=0x%02x\n",
            tf.command, tf.status, tf.error);
      errno = EIO;
      rc = -1;
   }

   args[0] = tf.status;
   args[1] = tf.error;
   args[2] = tf.lob.nsect;
   return rc;

use_legacy_ioctl:
#endif /* SG_IO */
   if (verbose)
      fprintf(stderr, "Trying legacy HDIO_DRIVE_CMD\n");
   return ioctl(fd, HDIO_DRIVE_CMD, args); // das ist wohl die entscheidende Zeile!
}
So, und jetzt die Frage:
Wie kann man obigen Delphi-Code entsprechend abwandeln, so dass er den Status abfragt?

Freue mich über jede Antwort!
Cu, Chris
  Mit Zitat antworten Zitat