📄 tcdbasic.pas
字号:
end;
{ READ TOC requests that the target transfers the table of contents.
NOTE: The maximum TOC data length possible on ISO-9660 CD-ROM media
is 804 bytes, or 100 TOC track descriptors. Track number 0 is CD lead-in
area, track number 0AAh is CD lead-out area, and they are not accessible
through SCSI.
MSFform=TRUE requests that MSF format be used for LBA fields, i.e. least
significant byte should be the Frame number (0..74d), next byte -
Second number (0..59d), next byte - Minute number (0..74bcd), and
the MSB of DWORD is reserved. In certain transition areas, the
relative MSF are decreasing positive values. The absolute MSF
addresses are always increasing positive values.
MSF=FALSE requests that the logical block address format be used
for the CD-ROM absolute address field or for the offset from the
beginning of the current track expressed as a number of LBs in a
CD-ROM track relative address field. This track relative logical
block address (TRLBA) value is reported as a negative value in
twos-complement notation for transition areas that have decreasing
MSF encoded relative addresses.
Start field specifies the starting track number for which the data
shall be returned. The data are returned in contiguous ascending
track number order. If the starting track field is not valid for
the currently installed medium, the command shall be terminated
with Err_SenseIllegalRequest status. Start=0 means entire table of
contents request and it's the only way we recommend to use this
function.
The returned data format shown below in SCSI_Toc record structure.
The TOC data block contains a 4-byte header followed by zero or more
TOC track descriptors. The first track number is not required to be one.
A disc may start at any valid track number. The track numbers between
the first and the last track number are required to be in contiguous
ascending order, except for the lead-out track (always numbered 0AAh).
NOTE: The starting logical block address value recovered from the TOC
has a tolerance of zero for data tracks and plus or minus 75 CD sectors
for audio tracks. }
function TCdRom.SCSIreadToc(MSFform : BOOLEAN; Start : BYTE;
var Toc: TCdRomToc) : BOOLEAN;
type
SCSI_TrackDescriptor = packed record
Reserved1 : byte;
ControlAndADR: byte; //bitset: D7..D4=ADR, D3..D0=Control
TrackNumber : byte;
Reserved2 : byte;
AbsAddress : DWORD; //byte-reversed!
end;
SCSI_Toc = packed record
Length : WORD; //byte-reversed!
FirstTrack: byte;
LastTrack : byte;
Tracks : array[0..99] of SCSI_TrackDescriptor;
end;
var
cd : SCSI_Toc;
cdt : SCSI_TrackDescriptor;
Arg1, B : byte;
i : integer;
begin
FillChar(cd, sizeof(cd), 0);
if MSFform then Arg1 := 2 else Arg1 := 0;
result := ASPIsend10($43, Arg1, 0, Start, sizeof(cd),
@cd, sizeof(cd), SRB_DIR_IN, ShortTimeout);
if NOT result then begin
Toc.FirstTrack := 0; Toc.LastTrack := 0;
Toc.TrackCount := 0; exit;
end;
Toc.FirstTrack := integer(cd.FirstTrack) AND $00FF;
Toc.LastTrack := integer(cd.LastTrack) AND $00FF;
Toc.TrackCount := (integer(BigEndianW(cd.Length))-2) DIV sizeof(cdt);
Toc.InMSF := MSFform;
for i := 0 to Toc.TrackCount-1 do begin
cdt := cd.Tracks[i];
with Toc.Track[i] do begin
Address := BigEndianD(cdt.AbsAddress);
TrackNumber := cdt.TrackNumber;
B := (cdt.ControlAndADR SHR 4) AND $0F;
if B >= 4 then ADR := ADRreserved
else ADR := TsubchannelADRinfo(B);
PreEmphasis := (cdt.ControlAndADR AND 1) <> 0;
CopyPermit := (cdt.ControlAndADR AND 2) <> 0;
DataTrack := (cdt.ControlAndADR AND 4) <> 0;
QuadAudio := (cdt.ControlAndADR AND 8) <> 0;
end; end; end;
{ READ HEADER requests the CD-ROM data block address header of the
requested logical block.
CDmode field specifies the CD-ROM data mode of the logical blocks:
+======================================+
|CD-ROM|User data field|Auxiliary field|
| mode | (2 048 bytes) | (288 bytes) |
|------+---------------+---------------|
| 00h | All zeroes | All zeroes |
| 01h | User data | L-EC symbols |
| 02h | User data | User data |
|03-FFh| Reserved | Reserved |
+======================================+
Address field gives the address of the first logical block in the
physical sector where the data for the requested GLBA is found. }
function TCdRom.SCSIreadHeaderLBA(GLBA : DWORD;
var CDmode : BYTE; var Address : DWORD) : BOOLEAN;
type SCSI_HeaderInfo = packed record
Mode : BYTE;
Resv1,Resv2,Resv3 : BYTE;
Addr : DWORD;
end;
var cd : SCSI_HeaderInfo;
begin
FillChar(cd, sizeof(cd), 0);
result := ASPIsend10($44, 0, GLBA, 0, sizeof(cd),
@cd, sizeof(cd), SRB_DIR_IN, MediumTimeout);
CDmode := cd.Mode;
Address := BigEndianD(cd.Addr);
end;
{ Second implementation of READ HEADER requests that MSF format be used
for Address field. }
function TCdRom.SCSIreadHeaderMSF(GLBA : DWORD;
var CDmode, AddressM, AddressS, AddressF : BYTE) : BOOLEAN;
var cd : array[0..7] of BYTE;
begin
FillChar(cd, sizeof(cd), 0);
result := ASPIsend10($44, 2, GLBA, 0, sizeof(cd),
@cd, sizeof(cd), SRB_DIR_IN, MediumTimeout);
CDmode := cd[0];
AddressM := cd[5];
AddressS := cd[6];
AddressF := cd[7];
end;
{ MODE SELECT(10) is a means to specify medium or device parameters to
the target. The target may provide for independent sets of parameters
for each attached logical unit.
PF (Page Form)=TRUE indicates that parameters following the header and
block descriptor(s) are structured as pages as specified in SCSI-2,
PF=FALSE means that all parameters after the block descriptors are
vendor-specific according to SCSI-1.
SP (Save Pages)=TRUE indicates that the target (after performing the
specified MODE SELECT operation) shall save to a non-volatile
vendor-specific location all the savable pages. The SP flag is
optional, even when mode pages are supported by the target.
If the target does not implement saved pages and the SP flag is
set to TRUE, the command shall be terminated with
Err_SenseIllegalRequest status.
BufLen is the length in bytes of the mode parameter list that shall be
transferred to the target. BufLen=0 indicates that no data shall be
transferred. This condition shall not be considered as an error.
Command shall be terminated with Err_SenseIllegalRequest status and all
mode parameters shall be remains unchanged if:
a) It sets any field that is reported by the target as not changeable
to a value other than its current value.
b) It sets any field in the mode parameter header, block descriptor(s)
or mode parameter to an unsupported value.
c) It sends a mode page with a length not equal to the page length
returned by the MODE SENSE command for that page.
d) It sets any reserved field in the parameter list to a non-zero value.
e) BufLen results in the truncation of any mode parameter header, mode
parameter block descriptor(s), or mode page.
A target may alter any mode parameter in any mode page (even reported
as non-changeable) as a result of changes to other mode parameters.
NOTE: MODE SENSE command should be issued prior to each MODE SELECT to
determine supported mode pages, page lengths, and other parameters.
NOTE: The initiator should issue a MODE SENSE command with the PCTL=1
and PAGE=3Fh to determine which mode pages are supported, which mode
parameters within the pages are changeable, and the supported length
of each mode page prior to issuing any MODE SELECT commands.
NOTE: MODE SELECT does not support page code of 3Fh (all pages). }
function TCdRom.SCSImodeSelectEX(PF, SP : BOOLEAN;
Buf : pointer; BufLen : DWORD) : BOOLEAN;
var Arg1 : byte;
begin
if PF then Arg1 := $10 else Arg1 := 0;
if SP then Arg1 := Arg1 OR 1;
result := ASPIsend10($55, Arg1, 0, 0, BufLen,
Buf, BufLen, SRB_DIR_OUT, ShortTimeout);
end;
function TCdRom.SCSImodeSelect(Buf : pointer; BufLen : DWORD) : BOOLEAN;
begin result := SCSImodeSelectEX(TRUE, FALSE, Buf, BufLen); end;
{ MODE SENSE(10) provides a means for a target to report parameters to
the initiator. It is a complementary command to the MODE SELECT(10).
DBD (Disable Block Descriptors) = TRUE specifies that the target shall
not return any block descriptors in the returned MODE SENSE data.
DBD=FALSE means that the target may return zero or more block
descriptors there, at the target's discretion.
PCTL (Page Control) field defines the type of mode parameter values to
be returned in the mode pages: 00b=Current Values, 01b=Changeable
Values, 10b=Default Values and 11b=Saved Values (see below).
NOTE: PCTL field only affects the mode parameters within the mode
pages, however the PS bit, page code and page length fields should
return current values since they have no meaning when used with
other types. The mode parameter header and mode parameter block
descriptor should return current values.
The current values (PCTL=0) are:
a) the values established by last successful MODE SELECT command;
b) the saved values if a MODE SELECT command has not successfully
completed since the last power-on, hard or soft RESET;
c) the default values, if saved values are not available or not
supported.
If the changeable values (PCTL=1) are selected, then all fields of
the mode parameters that are changeable shall be set to all one bits
and the fields of the mode parameters that are non-changeable (i.e.
defined by the target) shall be set to all zero bits.
NOTE: An attempt to change a non-changeable mode parameter (via MODE
SELECT) results in an error condition.
The default values (PCTL=2) are accessible even if the device is not
ready. Parameters not supported by the target shall be set to zero.
Implementation of saved (PCTL=3) page parameters is optional.
Mode parameters not supported by the target shall be set to zero.
If saved values are not implemented, the command shall return
Err_SenseIllegalRequest status.
PAGE specifies which mode page(s) to return. If requested page is not
implemented by the target, it shall return Err_SenseIllegalRequest
status.
A page code of 3Fh indicates that all pages implemented by the
target shall be returned. Pages should be returned in ascending
page code order except for mode page 00h. If implemented, it shall
be returned after all other mode pages.
NOTE: If the PCTL field and PAGE field are both set to zero, the
target should return a mode parameter header and block descriptor
(if applicable). This is for compatibility with SCSI-1 initiators.
+====================================================+
|Page code| Description |
|---------+------------------------------------------+
| 01h | Read error recovery page |
| 02h | Disconnect-reconnect page |
| 07h | Verify error recovery page |
| 08h | Caching page |
| 09h | Peripheral device page |
| 0Ah | Control mode page |
| 0Bh | Medium types supported page |
| 0Dh | CD-ROM page |
| 0Eh | CD-ROM audio control page |
| 20h-3Eh |Vendor-specific (page format required) |
| 00h |Vendor-specific (page format not required)|
+====================================================+ }
function TCdRom.SCSImodeSense(DBD : BOOLEAN; PCTL : TCdRomModePageType;
PAGE : BYTE; Buf : pointer; BufLen : DWORD) : BOOLEAN;
var
Arg1 : byte;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -