📄 tcdbasic.pas
字号:
unit TCDBASIC;
// -----------------------------------------------------------------------------
// Project: CD-ROM and CD-audio Interface Components
// Component Names: TCdRom
// Module: TCdBasic
// Description: Implements ASPI/SCSI primitive interface
// to CD-ROM and CD-Audio devices.
// Version: 0.2 early beta
// Date: 25-MAY-1999
// Target: Win32, Delphi3
// Authors: Sergey "KSER" Kabikov, iamkser@hotmail.com
// Copyright (c) 1999 Sergey Kabikov
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// Acknowledgements:
// 1. Thanks to Jay A. Key (scsiprog@geocities.com) for his "akrip" program,
// which sources (http://www.geocities.com/SiliconValley/Byte/7125/)
// helps to solve many problems.
// -----------------------------------------------------------------------------
{ 1. Full list of mandatory SCSI-2 commands ('+' is release mark)
Comment line is brief description if released or reasons why don't.
+ 00h TEST UNIT READY ; checks if the LUN (logical unit) is ready.
+ 03h REQUEST SENSE ; requests info about results of last SCSI operation.
+ 12h INQUIRY ; requests some parameters of the target.
+ 16h RESERVE ; reserves the entire LUN for the exclusive use.
+ 17h RELEASE ; cancels RESERVE command effects.
+ 1Dh SelfTest ; requests the target to perform self-test.
+ 25h READ CAPACITY ; returns logical block address (LBA) and block length
; of the last valid block for seek operations.
+ 28h READ(10) ; requests data from the target.
2. Full list of optional SCSI-2 commands ('+' is release mark)
+ 01h REZERO UNIT ; positions the actuator at cylinder 0
- 08h READ(6) ; REPLACED BY READ(10)
- 0Bh SEEK(6) ; REPLACED BY SEEK(10)
- 15h MODE SELECT(6) ; REPLACED BY MODE SELECT(10)
- 18h COPY ; RARE NEED/RARE EXISTS
- 1Ah MODE SENSE(6) ; REPLACED BY MODE SENSE(10)
+ 1Bh START STOP UNIT ; controls for media access. May also eject CD.
- 1Ch RECEIVE DIAGNOSTIC RESULTS ; The only non-vendor-specific diagnostic
; page is a list-of-supported-pages.
- 1Dh SEND DIAGNOSTIC ; Partial release - see SelfTest above.
+ 1Eh PREVENT/ALLOW MEDIUM REMOVAL
- A8h READ(12) ; We don't need to read >128MB in one piece...
+ 2Bh SEEK(10) ; requests LUN seek to the specified LBA.
- 2Fh VERIFY(10) ; RARE NEED/RARE EXISTS
- Afh VERIFY(12) ; RARE NEED/RARE EXISTS
- 30h/31h/32h SEARCH DATA HIGH/EQUAL/LOW(10) ; RARE NEED/RARE EXISTS
- B0h/B1h/B2h SEARCH DATA HIGH/EQUAL/LOW(12) ; RARE NEED/RARE EXISTS
- 33h SET LIMITS(10) ; FOR LINKED COMMANDS ONLY
- B3h SET LIMITS(12) ; FOR LINKED COMMANDS ONLY
+ 34h PRE-FETCH ; target must transfer the LBs to the cache memory.
+ 35h SYNCHRONIZE CACHE ; forces all delayed writes from cache to medium.
+ 36h LOCK/UNLOCK CACHE ; target disallows/allows LBs within the specified
; range to be removed from the cache memory.
- 39h COMPARE ; RARE NEED/RARE EXISTS
- 3Ah COPY AND VERIFY ; RARE NEED/RARE EXISTS
- 3Bh WRITE BUFFER ;\ The device's buffer I/O without medium access.
- 3Ch READ BUFFER ;/ Not-so-useful ?
+ 3Eh READ LONG ; Reads full sector, including ECC bytes
- 40h CHANGE DEFINITION ; RARE NEED/RARE EXISTS
+ 42h READ SUB-CHANNEL ; Read special info from current sector [partial]
+ 43h READ TOC ; Reads CD's Table Of Content (tracks list)
+ 44h READ HEADER ; Reads LB's header: abs.address and CD-ROM mode
- 4Ch LOG SELECT ;\ Statistics request commands (not for audio)
- 4Dh LOG SENSE ;/ Not-so-useful ?
+ 55h MODE SELECT(10) ; Changes CD-ROM mode parameters.
+ 5Ah MODE SENSE(10) ; A means for a CD-ROM to report its parameters.
}
interface
uses Windows, TASPIdev;
type
{ =============== CD SUB-CHANNEL Q DATA DEFINITIONS =============== }
TAudioStatus = (AudioNone, AudioPlay, AudioPause, AudioComplete,
AudioError, AudioStop, AudioInvalid);
{Status| Description |
|------+------------------------------------------------|
| 0 | Audio status byte not supported or not valid |
| 1 | Audio play operation in progress |
| 2 | Audio play operation paused |
| 3 | Audio play operation successfully completed |
| 4 | Audio play operation stopped due to error |
| 5 | No current audio status to return }
{ Audio status values 3 and 4 return information on previous
audio operations; they are returned only once after the
condition has occurred. If another audio play operation is
not requested, the audio status returned for subsequent
READ SUB-CHANNEL commands is 5. }
var
TAudioStatusName : array[TAudioStatus] of string = ('None', 'Play',
'Pause', 'Complete', 'Error', 'Stop', 'Invalid');
type
TsubchannelADRinfo = (ADRnone, ADRposition, ADRcatalogue,
ADRISRC, ADRreserved);
{ADR code| Sub-channel Q encoded information |
|--------+---------------------------------------|
| 0h | Mode information not supplied |
| 1h | Current position data ( track, index, |
| | absolute and relative addresses) |
| 2h | Media catalogue number |
| 3h | ISRC |
| 4h-Fh | Reserved }
var
TsubchannelADRname : array[TsubchannelADRinfo] of string = ('None',
'Position', 'Catalogue', 'ISRC', 'Reserved');
type
TCdRomSubQinfo = packed record
AudioStatus : TAudioStatus;
ADR : TsubchannelADRinfo;
PreEmphasis : BOOLEAN; // TRUE=Audio track with pre-emphasis
CopyPermit : BOOLEAN; // TRUE=Digital copy permitted
// FALSE=Digital copy prohibited
DataTrack : BOOLEAN; // TRUE=Data track, FALSE=Audio track
QuadAudio : BOOLEAN; // TRUE=Four-channel audio
// FALSE=Two-channel audio
TrackNumber : byte; // Number (0..99d) of current track
IndexNumber : byte; // Index (0..99d) of part of the track
UPC : string[16]; // identifying number of this media
// according to the uniform product code
// values (UPC/EAN bar coding) in ASCII.
ISRC : string[16]; // identifying number of this media
// according to the ISRC standards
// (DIN-31-621) expressed in ASCII.
case BOOLEAN of // Address of current location: absolute
// and relative to current track beginning
TRUE : (AbsAddress, // in LBA format
RelAddress : DWORD);
FALSE: (AbsAddressF, // in MSF format : Frames (0..74d),
AbsAddressS, // Seconds (0..59d) and
AbsAddressM, // Minutes (0..74d)
AbsAddressR, // And reserved byte field in MSB
RelAddressF,
RelAddressS,
RelAddressM,
RelAddressR : BYTE);
end;
{ =============== CD TABLE-OF-CONTENT DEFINITION =============== }
TCdRomTrackDescriptor = packed record
TrackNumber : byte; // Track no 0AAh is lead-out area
ADR : TsubchannelADRinfo;
PreEmphasis : BOOLEAN; // TRUE=Audio track with pre-emphasis
CopyPermit : BOOLEAN; // TRUE=Digital copy permitted
// FALSE=Digital copy prohibited
DataTrack : BOOLEAN; // TRUE=Data track, FALSE=Audio track
QuadAudio : BOOLEAN; // TRUE=Four-channel audio
// FALSE=Two-channel audio
case BOOLEAN of // Absolute linear address of track
TRUE : (Address : DWORD); // in LBA format
FALSE: (AddressF, // in MSF format : Frames (0..74d),
AddressS, // Seconds (0..59d) and
AddressM, // Minutes (0..74d)
AddressR : BYTE); // And reserved byte field in MSB
end;
TCdRomToc = packed record
Track : array[0..99] of TCdRomTrackDescriptor;
FirstTrack : integer;
LastTrack : integer;
TrackCount : integer; // Total tracks amount
InMSF : BOOLEAN; // Track[i].Address format:
// TRUE=MSF, FALSE=LBA
end;
{ ========== CD-ROM MODE SELECT/SENSE DEFINITIONS =========== }
TCdRomModePageType = (MPTcurrent, MPTchangeable, MPTdefault, MPTsaved);
var
TCdRomModePageTypeName : array[TCdRomModePageType] of string =
('MPTcurrent', 'MPTchangeable', 'MPTdefault', 'MPTsaved');
type
TCdRomMediumType = (CDTdefault, CDTdata, CDTaudio, CDTmixed,
CDTreserved, CDTdata80, CDTaudio80, CDTmixed80, CDTnone);
{ 'CDTmixed' means that medium may contain data and audio tracks,
'CDTdefault' - that device supports only one medium type (??),
suffix '80' - that media is a 80 mm diameter disk instead the
default 120 mm. }
var
TCdRomMediumName : array[TCdRomMediumType] of string = ('Default',
'CD-ROM 5"', 'CD-Audio 5"', 'CD-XA 5"', 'Unknown',
'CD-ROM 3"', 'CD-Audio 3"', 'CD-XA 3"', 'None');
type
TCdRomBlockDescriptor = record
Density : BYTE; // type of physical sectors on CD (see below)
BlkCount : DWORD; // amount of sectors with declared size
BlkSize : DWORD; // physical sector size in bytes
end;
{ CD-ROM density codes:
00h = Default density code (the only density supported by target)
01h = CD-ROM mode 1 - User data only (2048 bytes per physical sector)
02h = CD-ROM mode 2 - User data plus auxiliary data field (2336 bytes)
03h = 4-byte tag field, user data plus auxiliary data (2340 bytes)
04h = CD-Audio mode - 1/75th of a second per logical block
values 05h-7Fh are reserved, 80h-FFh - vendor-specific. }
TCdRomModeHeader = record
Medium : TCdRomMediumType; // see descriptions above
DPOFUA : BOOLEAN; // DPO/FUA (see SCSIread10) valid if TRUE
BDlength : BYTE; // real number of records in BD field
BD : array[0..99] of TCdRomBlockDescriptor;
end;
TCdRomModePageAudio = record
PSAV, // TRUE means parameter saving capability
IMM, // TRUE enables background audio playback
SOTC, // TRUE enables multi-track audio playback
APRV : BOOLEAN; // LBAformat and LBSaudio are valid if TRUE
LBAformat : BYTE; // LBSaudio fractional coeff.index (1 or 1/256)
LBSaudio : WORD; // LBAs per second in audio mode
Volume, // volume for indexed target's audio output
// port. 00h is silence, FFh is maximum.
Channel : // set of disc's audio channels, connected to
array[0..3] of BYTE; // indexed output port (ORed bitset 00h..0Fh)
end;
{ ================ CD-ROM CLASS DEFINITION ================= }
TCdRom = class(TASPIDevice)
private
fLocked : BOOLEAN;
protected
procedure SetLockUnlock(Value : boolean);
procedure ChangeDevice(Value : TdeviceID); override;
public
constructor Create(AOwner : TObject);
destructor Destroy; override;
{============== MANDATORY SCSI-II COMMANDS ============}
function SCSItestReady : BOOLEAN; // True if READY
function SCSIrequestSense(Pbuf : pointer; BufLen : BYTE) : BOOLEAN;
function SCSIinquiry(Vital : BOOLEAN; CodePage : BYTE;
Pbuf : pointer; BufLen : BYTE) : BOOLEAN;
function SCSIreserve : BOOLEAN;
function SCSIrelease : BOOLEAN;
function SCSIreserve3rdParty(TrdPartyDeviceID: BYTE) : BOOLEAN;
function SCSIrelease3rdParty(TrdPartyDeviceID: BYTE) : BOOLEAN;
function SCSIselfTest(DOFF, UOFF : BOOLEAN) : BOOLEAN;
function SCSIreadCapacity(var BlkCount, BlkSize : DWORD) : BOOLEAN;
function SCSIreadCapacityPM(Partition : WORD; GLBA : DWORD;
var BlkCount, BlkSize : DWORD) : BOOLEAN;
function SCSIread10(DPO,FUA: boolean; GLBA: DWORD; Sectors: WORD;
Buf : pointer; BufLen : DWORD) : BOOLEAN;
{============== OPTIONAL SCSI-II COMMANDS =============}
function SCSIrezeroUnit : BOOLEAN;
function SCSIstartStopUnit(STRT, LOEJ, IMM : boolean) : BOOLEAN;
function SCSIseek10(GLBA : DWORD) : BOOLEAN;
function SCSIpreFetch(IMM : BOOLEAN;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -