Projekte > Optische Laufwerke > Medieninformationen

Formatkapazität

READ FORMAT CAPACITY Command - Operation Code $23

Mit dem READ FORMAT CAPACITY Command lässt sich ermitteln mit welcher Kapazität das eingelegte Medium formatiert bzw. bespielt werden kann. Dies wird in den Multi Media Commands 6 im Kapitel 6.23 beschrieben. Dieses Command setzt voraus, dass das Laufwerk das Feature FORMATABLE (siehe Feature List) unterstützt.

  7 6 5 4 3 2 1 0
0 Operation Code = $23
1 Reserviert
2
3
4
5
6
7 Allocation Length
8
9 Control

 

Zu setzende Werte:

Operation Code: $23 - READ FORMAT CAPACITY Command.

Allocation Length $0103 - Ist die maximale Anzahl Bytes, welche zurückgegeben werden kann/soll. Sie ist von der Länge der erwarteten Antwortstruktur abhängig. Man kann das Command zuerst mit der Länge 4 (Header) aufrufen und dann die Allocation Length gegebenenfalls beim zweiten Aufruf anpassen.

Control - ?

 

Antwortstruktur

Die Antwort beginnt mit dem Capacity List Header:

  7 6 5 4 3 2 1 0
0 Reserviert
1
2
3 Capacity List Length

 
Capacity List Length gibt die Länge der folgenden Liste in Bytes an. Ein Byte erlaubt eine Länge von $FF (255). Hinzu kommen vier Byte Header, sodass sich eine Allocation Length von $0103 (259) ergibt.

Auf den Header folgt der Current/Maximum Capacity Descriptor:

  7 6 5 4 3 2 1 0
0 Number of Blocks
1
2
3
4 Reserviert Descriptor Type
5 Block Length/Spare Area Size
6
7

 
Die Number of Blocks (Anzahl der Blöcke) und Block Length/Spare Area Size (Blocklänge/ Ersatzbereichgröße) ist vom Descriptor Type (Beschreibungstypen) abhängig. Die Beschreibungstypes sind:

Descriptor Type Description
00b Reserviert
01b Unformatiertes oder leeres Medium
10b Formatiertes Medium
11b Kein Medium eingelegt oder unbekannte Kapzität

 
Für ein unformatiertes oder leeres Medium ergibt sich:

Media Type Number of Blocks Block Length/
Spare Area Size
CD-R/RW, DVD-R/RW Die Anzahl der Sektoren in allen Datenzonen auf dem Medium. Block Length = 2048
DVD-RAM, DVD+RW Die maximal formatierbare Kapazität des eingelegten Mediums in Sektoren.
BD-R Die Anzahl der Sektoren in allen Datenzonen auf dem Medium. Die maximal zulässige Anzahl von Ersatzbereichs- clustern auf der eingelegten Disc
BD-RE Die Anzahl der Nutzdatenbereichsblöcke, wenn das Medium mit einem Minimum an Ersatzbereichen formatiert wird.

 
Für ein formatiertes Medium ergibt sich:

Media Type Number of Blocks Block Length/
Spare Area Size
ROM Wie beim READ CAPACITY Command die LBA des letzten lesbaren Blocks auf der Disc um eins erhöht. Block Length = 2048
CD-R/RW, DVD-R/RW, DVD+R Im Falle von sequentiell aufgezeichneten Medien oder Quick Grow/Quick Add formatierten eingeschränkt überschriebenen Medien mit mindestens einer geschlossenen Sitzung, ist der Wert die Gesamtkapazität der geschlossenen Sessions. Wenn das sequentiell aufgezeichnete Medium keine geschlossene Sitzung besitzt, wird der Wert als "Unbekannt" gemeldet.
DVD-RAM, DVD+RW Der Wert entspricht der gegenwärtig formatierten Kapazität des eingelegten Mediums.
BD-R SRM+POW oder PRM formatiert: Die Gesamtzahl der Blöcke im Nutzdatenbereich des eingelegten Mediums. Anzahl der Cluster für die Ersatzbereiche auf der eingelegten Disk.
SRM-POW-Disk mit mindestens einer kompletten Session: Die Gesamtkapazität der geschlossenen Sessions.
BD-RE Die Anzahl der Blöcke im Nutzdatenbereich.

 
Wenn kein oder ein unbekanntes Medium eingelegt ist ergibt sich:

Ist kein Medium eingelegt wird als Number of Blocks die maximnale Kapazität angegeben, welche das Laufwerk lesen kann. Ist ein sequentiell aufgezeichnetes Medium mit nicht geschlossenen Sessions eingelegt, ist es die Anzahl der Sektoren in allen Datenbereichen auf dem Medium. Schnell formatierte DVD-RW werden als unbekanntes Medium erkannt. In allen Fällen wird die Block Length/Sqare Area Size mit 2048 angegeben.

Nun schließt sich gegebenenfalls die Liste der Formattable Capacity Descriptors an:

  7 6 5 4 3 2 1 0
0 Number of Blocks
1
2
3
4 Format Type Reserviert
5 Type Dependent Parameter
6
7

 
Die Werte für Number of Blocks und Type Dependent Parameter sind vom Format Type abhängig. Auf eine Aufzählung wird hier verzichtet.

 

Deklarationen

 
  {
  *  Für die Auswertung.
  }
  type
    TCurrentMaximalCapacityDescriptor = record
      NumberOfBlocks : Cardinal;
      DescriptorType : Byte;
      BlockLength    : Cardinal;
    end;
 
    TFormattableCapacityDescriptor = record
      NumberOfBlocks : Cardinal;
      FormatType     : Byte;
      Params         : Cardinal;
    end;
 
    TFormatCapacity = record
      Valid                            : Boolean;
      CapacityListLength               : Byte;
      CurrentMaximalCapacityDescriptor : TCurrentMaximalCapacityDescriptor;
      FormatCapacityDescriptor         : Array of TFormattableCapacityDescriptor;
    end
 
  {
  *  Für den Befehl.
  }
  const
    SCSIOP_READ_FORMAT_CAPACITY = $23;
 
  type
    TREAD_FORMAT_CAPACITY_CDB = record
      OperationCode    : Byte;
      AllocationLength : Word;
      Control          : Byte;
    end;
 
    TREAD_FORMAT_CAPACITIES_DATA = Array[$0000..$0103] of Byte;
    PREAD_FORMAT_CAPACITIES_DATA = ^TREAD_FORMAT_CAPACITIES_DATA;
          

 

Ausführung und Auswertung

Nach dem Ausfüllen des Command Descriptors Blockes wird die Abfrage ausgeführt und die Antwort ausgewertet.

 
  function TOptDrives.ReadFormatCapacities(aDevice: THandle): Boolean;
  {**************c*****************************************************************
  *  READ FORMAT CAPACITY
  }
  var
    READ_FORMAT_CAPACITIES_CDB : TREAD_FORMAT_CAPACITIES_CDB;
    pReadFormatCapacities      : pREAD_FORMAT_CAPACITIES_DATA;
    aCDB                       : Array[0..9] of Byte;
    nList                      : Integer;
  begin
    {
    *  Format Capacity initialisieren.
    }
    FillChar(FDrive[FActive].FormatCapacities,
             SizeOf(FDrive[FActive].FormatCapacities), $00);
    {
    *  Den Command Descriptor Block füllen.
    }
    ZeroMemory(@READ_FORMAT_CAPACITIES_CDB, SizeOf(TREAD_FORMAT_CAPACITIES_CDB));
    with  READ_FORMAT_CAPACITIES_CDB
    do begin
      OperationCode    := SCSIOP_READ_FORMAT_CAPACITIES;
      AllocationLength := SizeOf(TREAD_FORMAT_CAPACITIES_DATA);
    end;
    {
    *  Den Command Descriptor Block übertragen.
    }
    ZeroMemory(@aCDB, SizeOf(aCDB));
    aCDB[0] := READ_FORMAT_CAPACITIES_CDB.OperationCode;
    aCDB[7] := HiByte(READ_FORMAT_CAPACITIES_CDB.AllocationLength);
    aCDB[8] := LoByte(READ_FORMAT_CAPACITIES_CDB.AllocationLength);
    {
    *  Befehl ausführen.
    }
    GetMem(pReadFormatCapacities, SizeOf(TREAD_FORMAT_CAPACITIES_DATA));
    Result := GET_SCSI_PASS_THROUGH_DIRECT(aDevice, aCDB, pReadFormatCapacities,
                                           SizeOf(TREAD_FORMAT_CAPACITIES_DATA));
    if Result then
    with FDrive[FActive].FormatCapacities
    do begin
      Valid := True;
      CapacityListLength := pReadFormatCapacities[3];
      {
      *  Prüfen, ob ein Current/Maximum Capacity Descriptor folgt.
      }
      if CapacityListLength >= 8 then
      with CurrentMaximalCapacityDescriptor
      do begin
        NumberOfBlocks := pReadFormatCapacities[4] shl 24 or
                          pReadFormatCapacities[5] shl 16 or
                          pReadFormatCapacities[6] shl 8 or
                          pReadFormatCapacities[7];
        DescriptorType := pReadFormatCapacities[8] and $03;
        BlockLength    := pReadFormatCapacities[9] shl 16 or
                          pReadFormatCapacities[10] shl 8 or
                          pReadFormatCapacities[11];
      end;
      {
      *  Prüfen, ob eine Formattable Capacity Descriptor Liste folgt.
      }
      if CapacityListLength > 8
      then begin
        nList := Length(FormatCapacityDescriptor);
        SetLength(FormatCapacityDescriptor, nList + 1);
        with FormatCapacityDescriptor[nList]
        do begin
          NumberOfBlocks := pReadFormatCapacities[(nList * 8) + 12] shl 24 or
                            pReadFormatCapacities[(nList * 8) + 13] shl 16 or
                            pReadFormatCapacities[(nList * 8) + 14] shl 8 or
                            pReadFormatCapacities[(nList * 8) + 15];
          FormatType     := pReadFormatCapacities[(nList * 8) + 16] and $FC shr 2;
          Params         := pReadFormatCapacities[(nList * 8) + 17] shl 16 or
                            pReadFormatCapacities[(nList * 8) + 18] shl 8 or
                            pReadFormatCapacities[(nList * 8) + 19];
        end;
      end;
    end;
  end;
          

 

Demo, welche diese Funktion nutzt:

Read Format Capacities (podReadFormatCapacities.7z - 306 kb) MD5 (1 kb). Stand: 9. Juli 2013

Änderungen an der Demo

Datum Beschreibung
09.07.2013Kleine Überarbeitung und neuer Name.
26.02.2012Aktualisiert: Groupbox "Optische Laufwerke".
18.02.2012Fehler: Profilbezeichnung für $001A DVD+R und $001B DVD+RW korrigiert.