Dafür kann man auf die Capabilities zurückgreifen und das MODE SENSE (10) Command verwenden. Der MODE SENSE (10) Command Descriptor Block:
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
| 0 | Operation Code ($5A) | |||||||
| 1 | Reserviert | LLBAA | DBD | Reserviert | ||||
| 2 | PC | PAGE CODE | ||||||
| 3 | SUBPAGE CODE | |||||||
| 4 | Reserviert | |||||||
| 5 | ||||||||
| 6 | ||||||||
| 7 | Allocation Length | |||||||
| 8 | ||||||||
| 9 | Control | |||||||
Byte 0: Operation Code - $5A
Byte 1: $00.
Byte 2: 00b - Current values
Byte 2 und 3: $2A00 - Page Code und Subpage Code
Byte 7 und 8: $FF - Länge der Antwortstruktur, der vom Gerätetyp, dem unterstützten Multi Media Command Standard und dem eingelegten Medium abhängigen Mode Parameter Liste. Diese beginnt mit dem Mode Parameter (10) Header:
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
| 0 | Mode Data Length | |||||||
| 1 | ||||||||
| 2 | Reserviert | |||||||
| 3 | ||||||||
| 4 | ||||||||
| 5 | ||||||||
| 6 | Block Descriptor Length = 0 | |||||||
| 7 | ||||||||
Mode Data Length
Gibt in Bytes an, wie lang die folgende Datenstruktur ist.
Block Descriptor Length
Die Länge ist 0, da Multimediageräte keine Block Descriptors unterstützen. Für ältere SCSI logical Units sind es 8.
CD/DVD Capabilities and Mechanical Status Page (Page Code 2Ah)
Die Beschreibung der CD/DVD Capabiblities and Mechanical Status Page (Page Code $2A) findet sich in den
SCSI Multimedia Commands – 3 (MMC-3) in Kapitel 6.3.11. Hier auf die interessierenden Felder reduziert:
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
| 0 | PS | Reserviert | Page Code ($2A) | |||||
| 1 | Page Length (28 + 4 * (maximum number of n)) | |||||||
| 2..7 | Verschiedene Felder siehe Capabilities | |||||||
| 8 | Maximum Read Speed Supported (Veraltet) | |||||||
| 9 | ||||||||
| 10..17 | Verschiedene Felder siehe Capabilities | |||||||
| 18 | Maximum Write Speed (Veraltet) | |||||||
| 19 | ||||||||
| 20 | Current Write Speed Selected (Veraltet) | |||||||
| 21 | ||||||||
| 22..26 | Verschiedene Felder siehe Capabilities | |||||||
| 27 | Reserved | Rotation Control Selected | ||||||
| 28 | Current Write Speed Selected | |||||||
| 29 | ||||||||
| 30 | Number of Logical Unit Write Speed Performance Descriptor Tables (n) | |||||||
| 31 | ||||||||
| 32 | Logical Unit Write Speed Performance Descriptor Block #1 | |||||||
| 33 | ||||||||
| 34 | ||||||||
| 35 | ||||||||
| 36 | Logical Unit Write Speed Performance Descriptor Block #2 | |||||||
| 37 | ||||||||
| 38 | ||||||||
| 39 | ||||||||
| . . |
||||||||
| n * 4 + 28 | Logical Unit Write Speed Performance Descriptor Block #n | |||||||
| n * 4 + 29 | ||||||||
| n * 4 + 30 | ||||||||
| n * 4 + 31 | ||||||||
| Padding | ||||||||
Page Code: Code der zurückgegebenenen Seite.
Page Length: Gibt die noch folgenden Bytes an.
Maximum Read Speed Supported: Die höchste unterstützte Lesegeshwindigkeit. Sie ist vom eingelegten Medium abhängig. Obwohl als veraltet bezeichnet, wird sie meist noch angegeben.
Maximum Write Speed: Die höchste unterstützte Schreibgeschwindigkeit. Sie ist vom eingelegten Medium abhängig. Obwohl als veraltet bezeichnet, wird sie meist noch angegeben.
Rotation Control Selected: Gibt an, wie die Rotation controlliert wird:
| Wert | Beschreibung |
| 00b | Media default rotation control |
| 01b | CAV |
| Andere | Reserviert |
Current Write Speed Selected: Die gegenwärtig eingelegte Schreibgeschwindigkeit. Sie ist vom eingelegten
Medium abhängig. In der alten Version der Code Page belegt das Feld die Bytes 20 und 21. In der neuen Version wird
es als veraltet bezeichnet, wird jedoch meist angegeben. In der neuen Version belegt das Feld die Bytes 28 und 29.
Hinzu ist das Feld Rotation Control Selected in Byte 27 gekommen.
Number of Logical Unit Write Speed Performance Descriptor Tables (n): Gibt die Anzahl der folgenden Logical Unit Write Speed Performance Descriptor Blocks an.
Logical Unit Write Speed Performance Descriptor Block - Struktur:
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
| 0 | Reserved | |||||||
| 1 | Reserved | Rotation Control | ||||||
| 2 | Write Speed Supported (kbytes/sec) | |||||||
| 3 | ||||||||
Hier bedeutet die Rotation Control:
| Wert | Beschreibung |
| 00b | CLV |
| 01b | CAV |
| 10b | Reserviert |
| 11b |
{
* Für die Auswertung.
}
type
TModeParameterHeader = record
ModeDataLength : Word;
BlockDescLength : Word;
end;
type
TLogUnitWriteSpeedPerfDescBlock = record
Rotation : Byte;
WriteSpeed : Word;
end;
type
TCapabilities = record
PageCode : Byte;
PageLength : Byte;
RotCtrlSel : Byte;
CurWriSpeSel : Word;
NumLUWSPDT : Word;
LUWSPDBlock : array of TLogUnitWriteSpeedPerfDescBlock;
SpeedReadMax : Word;
SpeedReadCur : Word;
SpeedWriteMax : Word;
SpeedWriteCur : Word;
end;
TCapabilitiesMechStatus = record
ModeParameterHeader : TModeParameterHeader;
Capabilities : TCapabilities;
end;
...
{
* Für den Befehl.
}
const
SCSIOP_MODE_SENSE10 = $5A;
SCSIPC_CAPABILITIES = $2A;
type
TMODE_SENSE10_CDB = record
OperationCode : Byte;
PC_PageCode : Byte;
SubpageCode : Byte;
AllocationLength : Word;
end;
type
TCAPABILITIES_MECHSTATUS = record
ModeParameterHeader : array[0..7] of Byte;
Data : array[0..$FF] of Byte;
end;
Nach dem Ausfüllen des Command Descriptors Blockes wird die Abfrage ausgeführt und die Antwort ausgewertet. Es werden auch die als veraltet bezeichneten Felder ausgewertet.
...
begin
...
{
* Den Command Descriptor Block füllen.
}
ZeroMemory(@MODE_SENSE10_CDB, SizeOf(MODE_SENSE10_CDB));
MODE_SENSE10_CDB.OperationCode := SCSIOP_MODE_SENSE10;
MODE_SENSE10_CDB.PC_PageCode := SCSIPC_CAPABILITIES;
MODE_SENSE10_CDB.AllocationLength := SizeOf(TMODE_SENSE10_DATA);
{
* Den Command Descriptor Block übertragen.
}
SetLength(aCDB, 10);
aCDB[0] := MODE_SENSE10_CDB.OperationCode;
aCDB[2] := MODE_SENSE10_CDB.PC_PageCode;
aCDB[3] := MODE_SENSE10_CDB.SubpageCode;
aCDB[7] := HiByte(MODE_SENSE10_CDB.AllocationLength);
aCDB[8] := LoByte(MODE_SENSE10_CDB.AllocationLength);
{
* Befehl ausführen
}
ZeroMemory(@CAPABILITIES_MECHSTATUS, SizeOf(CAPABILITIES_MECHSTATUS));
if GET_SCSI_PASS_THROUGH_DIRECT(aDrive, aCDB, @CAPABILITIES_MECHSTATUS,
SizeOf(TCAPABILITIES_MECHSTATUS))
then begin
with Capabilities.ModeParameterHeader
do begin
ModeDataLength := CAPABILITIES_MECHSTATUS.ModeParameterHeader[0] shl 8 or
CAPABILITIES_MECHSTATUS.ModeParameterHeader[1];
BlockDescLength := CAPABILITIES_MECHSTATUS.ModeParameterHeader[6] shl 8 or
CAPABILITIES_MECHSTATUS.ModeParameterHeader[7];
end;
with Capabilities.Capabilities
do begin
PageCode := CAPABILITIES_MECHSTATUS.Data[0] and $3F;
PageLength := CAPABILITIES_MECHSTATUS.Data[1];
SpeedReadMax := CAPABILITIES_MECHSTATUS.Data[8] shl 8 or
CAPABILITIES_MECHSTATUS.Data[9];
SpeedReadCur := CAPABILITIES_MECHSTATUS.Data[14] shl 8 or
CAPABILITIES_MECHSTATUS.Data[15];
SpeedWriteMax := CAPABILITIES_MECHSTATUS.Data[18] shl 8 or
CAPABILITIES_MECHSTATUS.Data[19];
SpeedWriteCur := CAPABILITIES_MECHSTATUS.Data[20] shl 8 or
CAPABILITIES_MECHSTATUS.Data[21];
RotCtrlSel := CAPABILITIES_MECHSTATUS.Data[27] and $03;
CurWriSpeSel := CAPABILITIES_MECHSTATUS.Data[28] shl 8 or
CAPABILITIES_MECHSTATUS.Data[29];
NumLUWSPDT := CAPABILITIES_MECHSTATUS.Data[30] shl 8 or
CAPABILITIES_MECHSTATUS.Data[31];
{
* Blöcke
}
if NumLUWSPDT > 0
then begin
SetLength(LUWSPDBlock, NumLUWSPDT);
for n := 1 to NumLUWSPDT
do begin
LUWSPDBlock[n - 1].Rotation
:= CAPABILITIES_MECHSTATUS.Data[n * 4 + 29] and $07;
LUWSPDBlock[n - 1].WriteSpeed
:= CAPABILITIES_MECHSTATUS.Data[n * 4 + 30] shl 8 or
CAPABILITIES_MECHSTATUS.Data[n * 4 + 31];
end;
end;
end;
end;
...
end;
Hier könnte man noch einige Plausibilitätsprüfungen einbauen. Zum Beispiel kann man die Werte für die Mode Data
Length, den Page Code und die Page Length überprüfen.
Demo, welche diese Funktion nutzt:

Medien Disc Speed (podDiscSpeed.7z - 267 kb) MD5 (1 kb). Stand: 26. Februar 2012
Fr_An - Erstellt: 30. Januar 2012 - Letzte Änderung: 26. Februar 2012
seit 28. Juli 2010