Projekte > Optische Laufwerke > Hardware

Mechanismus

MECHANISM STATUS Command - Operation Code $BD

Multi-Media Commands - 6 Kapitel 6.10. Das MECHANISM STATUS Command ruft den gegenwärtigen Status des Mechanismus, einschließlich der Wechslermechanismen, welche den Standard unterstützen, ab. Der Befehl wurde bereits im Kapitel Mechanik - Status der Schublade benutzt.

Der MECHANISM STATUS Command Descriptor Block:

  7 6 5 4 3 2 1 0
0 Operation Code ($BD)
1 Reserviert
2
3
4
5
6
7
8 Allocation Length
9
10 Reserviert
11 Control

 

Die Werte:

Byte 0: Operation Code = $BD

Byte 8 und 9: Länge der Antwortstruktur = SizeOf(TMechanismStatusHeader) = $20

Byte 11: Control - ?

 

Die Antwortstruktur:

Auf acht Byte Mechanism Status Header folgen die Slot tables. Hier der Techanism Status Header:

  7 6 5 4 3 2 1 0
0 Fault Changer State Current Slot (Low order))
1 Mechanism State Door Open Reserviert Current Slot (High order)
2 Current LBA (Legacy)
3
4
5 Number of Slots Available
6 Length of Slot Tables
7

 

Fault
Gibt an, ob die Ausführung der Aktion, welche im Changer State angegeben ist, scheiterte.

Changer State

Changer State Definition
$0 Ready
$1 Load in Progress
$2 Unload in Progress
$3 Initialisierung

 
Current Slot
Gibt den aktuell ausgewählten Slot an. Bei Geräten, welche bootfähig sind, sollte dies nach der Initialisierung der Slot 0 sein. Wenn das Gerät kein Wechsler ist, ist das Feld reserviert.

Mechanism State

Mechanism State Definition
$0 Idle
$1 Legacy definition - Playing (Audio or Data)
$2 Legacy definition - Scanning
$3 Legacy definition - Active with Host, Composite or Other Ports in use (zB READ)
$4 - $6 Reserviert
$7 No State Information Available

 
Door open
Wenn das Bit gesetzt ist, ist die Tür/Schublade offen oder das Magazin nicht eingesetzt.

Current LBA
LBA (Logical Block Addressing) gibt den Sektor an, von welchem zuletzt gelesen wurde.

Number of Slots
Anzahl der verfügbaren Slots. Wenn das Gerät kein Wechsler ist, ist der Wert 0.

Length of Slot Tables
Gibt die Anzahl der Bytes an, welche mit Slot Informationen belegt sind. Sie berägt ein Vielfaches von vier.
 

Eine Slot Table:

  7 6 5 4 3 2 1 0
0 Disc Present Reserved Change
1 Reserved CWP_V CWP
2 Reserved
3

 
Disc Present Gibt an, ob eine Disc eingelegt ist.

Change
Gibt an, ob die Disc seit den letzten Laden geändert wurde. Das Flag ist obligatorisch.

CWP_V
Gibt an, das die Media Cartridge Write Protection in diesem Slot geprüft wurde und das Flag CWP gültig ist.

CWP
Gibt an, ob die Media Cartridge Write Protection für den Slot aktiv ist.

 

Deklaratioen

Für die Ausführung:

 
  const
    SCSIOP_MECHANISM_STATUS = $BD;
 
  type
    TMECHANISM_STATUS_CDB = record
      OperationCode    : Byte;
      AllocationLength : Word;
      Control          : Byte;
    end;
 
  type
    TMECHANISM_STATUS_PARAMETER_LIST = record
      MechanismStatusHeader : Array[0..7] of Byte;
      SlotTable             : Array[0..39] of Byte;
    end;
    PMECHANISM_STATUS_PARAMETER_LIST = ^TMECHANISM_STATUS_PARAMETER_LIST;
          

 

Für die Auswertung:

 
  type
    TMechanismStatusHeader = record
      Fault                  : Boolean;
      ChangerState           : Byte;
      CurrentSlot            : Byte;
      MechanismState         : Byte;
      DoorOpen               : Boolean;
      CurrentLBA             : Array[0..2] of Byte;
      NumberOfSlotsAvailable : Byte;
      LengthOfSlotTables     : Word;
    end;
 
  type
    TSlotTable = record
      DiscPresent : Boolean;
      Change      : Boolean;
      CWP_V       : Boolean;
      CWP         : Boolean;
    end;
 
  type
    TMechanismStatusParameterList = record
      MechanismStatusHeader : TMechanismStatusHeader;
      SlotTables            : Array of TSlotTable;
    end;
        

 

Ausführung und Auswertung

Der Command Descriptor Comman wird ausgefüllt, der Befehl ausgeführt und anschließend die Antwortstruktur ausgewertet.

 
  function TOptDrives.ReadMechanismStatus(aDevice: THandle): Boolean;
  {*******************************************************************************
  *  Den Status des Mechanismus ermitteln.
  }
  var
    MECHANISM_STATUS_CDB : TMECHANISM_STATUS_CDB;
    pMechanismStatus     : PMECHANISM_STATUS_PARAMETER_LIST;
    aCDB                 : Array of Byte;
    i                    : Integer;
  begin
    Result := False;
    {
    *  Mechanismus Status initialisieren.
    }
    FillChar(FDrive[FActive].MechanismStatus,
             SizeOf(FDrive[FActive].MechanismStatus), $00);
    {
    *  Den Command Descriptor Block füllen.
    }
    ZeroMemory(@MECHANISM_STATUS_CDB, SizeOf(MECHANISM_STATUS_CDB));
    MECHANISM_STATUS_CDB.OperationCode    := SCSIOP_MECHANISM_STATUS;
    MECHANISM_STATUS_CDB.AllocationLength := SizeOf(TMECHANISM_STATUS_PARAMETER_LIST);
    {
    *  Den Command Descriptor Block übertragen.
    }
    SetLength(aCDB, 12);
    aCDB[0]  := MECHANISM_STATUS_CDB.OperationCode;
    aCDB[8]  := HiByte(MECHANISM_STATUS_CDB.AllocationLength);
    aCDB[9]  := LoByte(MECHANISM_STATUS_CDB.AllocationLength);
    {
    *  Befehl ausführen
    }
    GetMem(pMechanismStatus, SizeOf(TMECHANISM_STATUS_PARAMETER_LIST));
    if GET_SCSI_PASS_THROUGH_DIRECT(aDevice, aCDB, pMechanismStatus,
                                    SizeOf(TMECHANISM_STATUS_PARAMETER_LIST)) then
    with FDrive[FActive].MechanismStatus.MechanismStatusHeader
    do begin
      {
      *  Header lesen
      }
      Fault                  := pMechanismStatus.Header[0] and $80 > 0;
      ChangerState           := pMechanismStatus.Header[0] and $60 shr 5;
      CurrentSlot            := pMechanismStatus.Header[0] and $15 or
                                pMechanismStatus.Header[1] and $07 shl 5;
      MechanismState         := pMechanismStatus.Header[1] shr 6;
      DoorOpen               := pMechanismStatus.Header[1] and $10 > 0;
      CurrentLBA[0]          := pMechanismStatus.Header[2];
      CurrentLBA[1]          := pMechanismStatus.Header[3];
      CurrentLBA[2]          := pMechanismStatus.Header[4];
      NumberOfSlotsAvailable := pMechanismStatus.Header[5];
      LengthOfSlotTables     := pMechanismStatus.Header[6] shl 8 or
                                pMechanismStatus.Header[7];
      {
      *  Wenn es ein Wechsler ist und es Slots gibt.
      }
      if NumberOfSlotsAvailable > 0
      then begin
        SetLength(FDrive[FActive].MechanismStatus.SlotTables, NumberOfSlotsAvailable);
        for i := 0 to NumberOfSlotsAvailable - 1 do
        with FDrive[FActive].MechanismStatus.SlotTables[i]
        do begin
          DiscPresent := pMechanismStatus.SlotTable[i * 4 + 0] and $80 > 0;
          Change      := pMechanismStatus.SlotTable[i * 4 + 0] and $01 > 0;
          CWP_V       := pMechanismStatus.SlotTable[i * 4 + 1] and $02 > 0;
          CWP         := pMechanismStatus.SlotTable[i * 4 + 1] and $01 > 0;
        end;
      end;
      {
      *  Ergebnis
      }
      Result := True;
    end;
  end;
          

 
CD-Wechsler dürften in PCs selten sein. Somit dürften eigentlich nur die Informationen Door_Open und eventuell CurrentLBA, welcher sich bei jedem Dateizugriff ändert, interessant sein.

 

Demo, welche diese Funktion nutzt:

MechanismscStatus (podMechanism.7z - 305 kb) MD5 (1 kb). Stand: 30. Juni 2013