Plextor commands for DVD scanning
Hi all,
I have discussed with Alexander Noe, who has done some reverse
engineering to find the plextor commands for DVD scanning. He gave me
some code, which he allowed me to disperse so that software developers
can add DVD scan support to their software.
It contains the proprietary commands for the Plextor drives, probably
for PX-[57]xx series.
I hope you will find useful things, and sorry if you already had these
information.
What we have:
-PIE
-PIF
-Jitter
-Beta
What is missing:
- TA. Alexander is working on TA on his new PX716A.
Eric
// plexstuff.cpp : Definiert den Einsprungpunkt für die Konsolenanwendung.
//
#include "stdafx.h"
#include "windows.h"
#include "memory.h"
#include "stdlib.h"
#include "wnaspi32.h"
#include "scsidefs.h"
#include "math.h"
#pragma pack(1)
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
int debug = 0;
const int DISC_DVDminusR = 0x01;
const int DISC_DVDminusRW = 0x02;
const int DISC_DVDplusR = 0x03;
const int DISC_DVDplusRW = 0x04;
const int DISC_DVDplusRDL = 0x05;
const int DISC_DVDROM = 0x06;
/*
typedef struct {
int data[8];
int position;
} RINGLIST;
*/
typedef struct
{
char vendor_ID[9];
char product_ID[17];
char product_revision[5];
BYTE haID;
BYTE Target;
BYTE Lun;
// DRIVE_CAPS caps;
} DRIVE_INFO;
/* Global Variables */
HINSTANCE hWNASPI32; // Handle to ASPI for Win32
/* Function Prototypes for WNASPI32.DLL */
DWORD (*GetASPI32SupportInfo)(void);
DWORD (*SendASPI32Command)(LPSRB);
BOOL (*GetASPI32Buffer)( void* );
BOOL (*FreeASPI32Buffer)( void* );
BOOL (*TranslateASPI32Address)( PDWORD, PDWORD );
// Then, inside your Main/WinMain function:
/* Load Real ASPI Layer, WNASPI32.DLL */
DWORD round(double x)
{
if ((x-(DWORD)x)>0.5)
{
return (DWORD)x+1;
}
else
{
return (DWORD)x;
}
}
const int COMMAND_FAILED = -0x01;
int ExecSCSICmd(DWORD dwFlag,DRIVE_INFO* drive,SRB_ExecSCSICmd* lpsrbExec,void* lpData,DWORD dwDataLen,
BYTE cmdlen,BYTE cmd0 = 0,BYTE cmd1 = 0,BYTE cmd2 = 0,
BYTE cmd3 = 0,BYTE cmd4 = 0,BYTE cmd5 = 0,BYTE cmd6 = 0,
BYTE cmd7 = 0,BYTE cmd8 = 0, BYTE cmd9 = 0,BYTE cmd10 = 0,
BYTE cmd11 = 0,BYTE cmd12 = 0)
{
HANDLE heventSRB;
DWORD dwASPIStatus;
memset(lpsrbExec, 0, sizeof(SRB_ExecSCSICmd) );
heventSRB = CreateEvent( NULL, TRUE, FALSE, NULL );
lpsrbExec->SRB_Cmd = SC_EXEC_SCSI_CMD;
lpsrbExec->SRB_Flags = (BYTE)(dwFlag | SRB_EVENT_NOTIFY);
lpsrbExec->SRB_Target = drive->Target;
lpsrbExec->SRB_Lun = drive->Lun;
lpsrbExec->SRB_HaId = drive->haID;
lpsrbExec->SRB_BufLen = dwDataLen;
lpsrbExec->SRB_BufPointer = (unsigned char*)lpData;
lpsrbExec->SRB_SenseLen = SENSE_LEN;
lpsrbExec->SRB_CDBLen = cmdlen;
lpsrbExec->SRB_PostProc = (LPVOID)heventSRB;
lpsrbExec->CDBByte[0] = cmd0;
lpsrbExec->CDBByte[1] = cmd1;
lpsrbExec->CDBByte[2] = cmd2;
lpsrbExec->CDBByte[3] = cmd3;
lpsrbExec->CDBByte[4] = cmd4;
lpsrbExec->CDBByte[5] = cmd5;
lpsrbExec->CDBByte[6] = cmd6;
lpsrbExec->CDBByte[7] = cmd7;
lpsrbExec->CDBByte[8] = cmd8;
lpsrbExec->CDBByte[9] = cmd9;
lpsrbExec->CDBByte[10] = cmd10;
lpsrbExec->CDBByte[11] = cmd11;
lpsrbExec->CDBByte[12] = cmd12;
ResetEvent( heventSRB );
dwASPIStatus = SendASPI32Command( lpsrbExec );
if( dwASPIStatus == SS_PENDING )
{
WaitForSingleObject( heventSRB, INFINITE );
}
// DispStat(lpsrbExec);
if (lpsrbExec->SRB_TargStat==STATUS_CHKCOND)
{
if (lpsrbExec->SenseArea[2]==KEY_UNITATT)
{
return ExecSCSICmd(dwFlag,drive,lpsrbExec,lpData,dwDataLen,cmdlen,cmd0,cmd1,cmd2,cmd3,cmd4,cmd5,
cmd6,cmd7,cmd8,cmd9,cmd10,cmd11,cmd12);
} else
/*if (lpsrbExec->SenseArea[2]==KEY_MEDIUMERR)
{
printf("medium error\n");
} else
*/
{
/* printf("error: sense code: %02X, ASC: %02X, ASCQ: %02X\n", (DWORD)lpsrbExec->SenseArea[2],
(DWORD)lpsrbExec->SenseArea[12],(DWORD)lpsrbExec->SenseArea[13]);*/
if (debug) {
printf(" command failed: (%d) %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
cmdlen,cmd0,cmd1,cmd2,cmd3,cmd4,cmd5,
cmd6,cmd7,cmd8,cmd9,cmd10,cmd11,cmd12);
} else {
printf(" command failed\n");
}
if (dwDataLen && debug && (dwDataLen < 8192)) {
if (dwFlag == SRB_DIR_IN) printf(" answer:\n ");
if (dwFlag == SRB_DIR_OUT) printf(" input :\n ");
for (int i=0;i<(int)dwDataLen;i++) {
printf("%02X ", ((unsigned char*)lpData)[i]);
if (((i+1) % 16) == 0) printf("\n ");
}
printf("\n");
}
return COMMAND_FAILED;
}
} else {
if (debug) {
printf(" command succeeded: (%d) %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
cmdlen,cmd0,cmd1,cmd2,cmd3,cmd4,cmd5,
cmd6,cmd7,cmd8,cmd9,cmd10,cmd11,cmd12);
if (dwDataLen && dwDataLen < 8192) {
if (dwFlag == SRB_DIR_IN) printf(" answer:\n ");
if (dwFlag == SRB_DIR_OUT) printf(" input :\n ");
for (int i=0;i<(int)dwDataLen;i++) {
printf("%02X ", ((unsigned char*)lpData)[i]);
if (((i+1) % 16) == 0) printf("\n ");
}
printf("\n");
}
}
}
return 0;
}
int TestUnitReady (DRIVE_INFO* drive)
{
SRB_ExecSCSICmd srbExec;
int j = ExecSCSICmd(0,drive,&srbExec,NULL,0,6,0);
if (j != COMMAND_FAILED) return 1;
return 0;
}
int swap4(char* c) {
char d[4];
d[0]=c[3];
d[1]=c[2];
d[2]=c[1];
d[3]=c[0];
return *(int*)d;
}
short int swap2(char* c) {
char d[2];
d[0]=c[1];
d[1]=c[0];
return *(short int*)d;
}
int swap4(int c_) {
char* c = (char*)&c_;
char d[4];
d[0]=c[3];
d[1]=c[2];
d[2]=c[1];
d[3]=c[0];
return *(int*)d;
}
void print_gigarec_value(int i)
{
switch (i & 0xFF) {
case 0x00: printf("gigarec off\n"); break;
case 0x01: printf("gigarec 1.2x\n"); break;
case 0x02: printf("gigarec 1.3x\n"); break;
case 0x03: printf("gigarec 1.4x\n"); break;
case 0x81: printf("gigarec 0.8x\n"); break;
case 0x82: printf("gigarec 0.7x\n"); break;
case 0x83: printf("gigarec 0.6x\n"); break;
}
}
int plextor_set_gigarec(DRIVE_INFO* drive, int i)
{
SRB_ExecSCSICmd srbExec;
memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );
printf(" applying gigarec setting : ");
print_gigarec_value(i);
char data[] = { 0x00, 0x00, 0x00, 0, 0,0,0,0 };
int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,data,8,12,0xE9,0x10,0x04,
0x00,i,0x00,0x00,0x00,0x00,0x00,0x08);
return 1;
}
int plextor_read_gigarec(DRIVE_INFO* drive, int* i)
{
SRB_ExecSCSICmd srbExec;
memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );
char data[] = { 0x00,0x00,0,0,0,0,0,0 };
int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,data,8,12,0xE9,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08);
printf(" reading current gigarec setting: ");
print_gigarec_value(data[3]);
return 1;
}
int plextor_start_pisum8(DRIVE_INFO* drive)
{
SRB_ExecSCSICmd srbExec;
memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );
int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,NULL,0,12,0xEA,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10);
if (j != COMMAND_FAILED) return 1;
return 0;
}
int plextor_start_pif(DRIVE_INFO* drive)
{
SRB_ExecSCSICmd srbExec;
memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );
int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,NULL,0,12,0xEA,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x12);
if (j != COMMAND_FAILED) return 1;
return 0;
}
int plextor_start_jitterbeta(DRIVE_INFO* drive)
{
SRB_ExecSCSICmd srbExec;
memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );
int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,NULL,0,10,0xEA,0x15,0x10,0x00,0x00,0x00,0x00,0x00,0x10,0x00);
if (j != COMMAND_FAILED) return 1;
return 0;
}
int plextor_end_pi(DRIVE_INFO* drive)
{
SRB_ExecSCSICmd srbExec;
memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );
int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,NULL,0,12,0xEA,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
if (j != COMMAND_FAILED) return 1;
return 0;
}
int read_one_ecc_block(DRIVE_INFO* drive, void* pBuffer, int lba)
{
SRB_ExecSCSICmd srbExec;
memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );
int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,pBuffer,32768,10,0x28,0x00,(lba>>24) & 0xFF,
(lba>>16) & 0xFF, (lba>>8) & 0xFF, lba & 0xFF, 0x00,0x00,0x10,0x00);
if (j != COMMAND_FAILED) return 1;
return 0;
}
int plextor_read_pi_info(DRIVE_INFO* drive, void* pBuffer)
{
SRB_ExecSCSICmd srbExec;
memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );
int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,pBuffer,0x34,12,0xEA,0x16,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0x00);
if (j != COMMAND_FAILED) return 1;
return 0;
}
int plextor_read_jb_info(DRIVE_INFO* drive, void* pBuffer)
{
SRB_ExecSCSICmd srbExec;
memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );
int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,pBuffer,0x10,12,0xEA,0x16,
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00);
if (j != COMMAND_FAILED) return 1;
return 0;
}
int plextor_pisum8_do_eight_ecc_blocks(DRIVE_INFO* drive, void* pBuffer, int lba, int* pError_count)
{
char data[0x34]; memset(data, 0, 0x34);
SRB_ExecSCSICmd srbExec;
memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );
for (int i=0;i<8;i++) {
read_one_ecc_block(drive, pBuffer, lba);
lba += 16;
}
plextor_read_pi_info(drive, data);
*pError_count = swap4(data+0x24);
return 1;
}
int plextor_jitterbeta_do_16_ecc_blocks(DRIVE_INFO* drive, void* pBuffer, int lba, int* jitter,
short int* beta)
{
char data[0x34]; memset(data, 0, 0x34);
short int* i16_beta;
char c;
SRB_ExecSCSICmd srbExec;
memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );
for (int i=0;i<16;i++) {
read_one_ecc_block(drive, pBuffer, lba);
lba += 16;
}
plextor_read_jb_info(drive, data);
c = data[10]; data[10] = data[11]; data[11] = c;
i16_beta = (short int*)(data+10);
*beta = *i16_beta;
*jitter = swap2(data+12);
return 1;
}
int plextor_pif_do_one_ecc_block(DRIVE_INFO* drive, void* pBuffer, int lba, int* pError_count)
{
char data[0x34]; memset(data, 0, 0x34);
SRB_ExecSCSICmd srbExec;
memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );
read_one_ecc_block(drive, pBuffer, lba);
lba += 16;
plextor_read_pi_info(drive, data);
*pError_count = swap4(data+0x24);
return 1;
}
int read_capacity(DRIVE_INFO* drive, int* pCapacity)
{
SRB_ExecSCSICmd srbExec;
memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );
char data[8]; memset(data, 0, 8);
int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,data,8,10,0x25);
*pCapacity = swap4(data);
if ((*pCapacity % 16) != 0) {
*pCapacity = ((*pCapacity) / 16 * 16) + 16;
}
return 1;
}
int eval_dvd_struct_0e(void* pData)
{
char* cData = (char*)pData;
cData[27]=0;
cData[35]=0;
cData[43]=0;
printf("manufacturer ID: ");
printf(cData+21);
printf(cData+29);
printf("\n");
return 1;
}
int eval_dvd_struct_11_dvdplus(void* pData)
{
char* cData = (char*)pData;
// cData[34]=0;
cData[0] = cData[31];
cData[31] = 0;
if (cData[23]) {
printf("manufacturer ID: ");
printf(cData+23);
printf("-");
cData[31] = cData[0];
cData[0] = cData[34];
cData[34] = 0;
printf(cData+31);
printf("-");
printf("%c%c", (unsigned int)(cData[0] >> 4)+48, (unsigned int)(cData[0] & 0x0F)+48);
printf("\n");
}
return 1;
}
/*
int get_read_speed(DRIVE_INFO* drive, int* speed)
{
unsigned char data[40]; memset(data, 0, 40);
char* perf_data_length = (char*)&data[0];
char* start_lba = (char*)&data[8];
char* start_perf = (char*)&data[12];
char* end_lba = (char*)&data[16];
char* end_perf = (char*)&data[20];
SRB_ExecSCSICmd srbExec;
memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );
int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,data,40,12,0xAC,0x00,0,0,0,0,0,0,0,2,0,0);
printf("get_read_speed:\n");
printf(" pd len= %d\n", swap4(perf_data_length));
printf(" start_lba = %06X\n", swap4(start_lba));
printf(" start_perf= %6d\n", swap4(start_perf));
printf(" end _lba = %06X\n", swap4(end_lba));
printf(" end _perf= %6d\n", swap4(end_perf));
return 1;
}
*/
int get_feature(DRIVE_INFO* drive, int feature_number, char* pDest, int pDest_len, int* current = NULL)
{
SRB_ExecSCSICmd srbExec;
memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );
if (current) *current = 0;
int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,pDest,32,10,0x46,0x02,(feature_number >> 8) & 0xFF,
feature_number & 0xFF,0,0,0,32);
if (j == COMMAND_FAILED) return 0;
char* data_length = (char*)&pDest[0];
char* current_profile = (char*)&pDest[6];
if (current) *current = pDest[10] & 0x01;
if (swap4(data_length) < 8) return 0;
return 1;
}
int read_dvd_structure(DRIVE_INFO* drive, int format, char* pDest)
{
SRB_ExecSCSICmd srbExec;
memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );
int j = ExecSCSICmd(SRB_DIR_IN,drive,&srbExec,pDest,2056,10,0xAD,0,0,0,0,0,0,format,
8,8,0);
return 1;
}
int determine_disc_type(DRIVE_INFO* drive, int* disc_type)
{
bool bDVDminus = false;
*disc_type = 0;
char* book_types[] = { "DVD-ROM", "DVD-RAM", "DVD-R", "DVD-RW", "<b0rked>",
"<b0rked>","<b0rked>","<b0rked>","<b0rked>","DVD+RW", "DVD+R",
"<b0rked>","<b0rked>","<b0rked>","DVD+R DL", "<b0rked>" };
char data[2056]; memset(data, 0, 2056); int current = 0;
if (get_feature(drive, 0x2F, data, 32, ¤t) && current) {
printf("disc type: DVD-R/W\n");
bDVDminus = true;
} else if (get_feature(drive, 0x2B, data, 32, ¤t) && current) {
printf("disc type: DVD+R\n"); *disc_type = DISC_DVDplusR;
}
else if (get_feature(drive, 0x2A, data, 32, ¤t) && current) {
printf("disc type: DVD+RW\n"); *disc_type = DISC_DVDplusRW;
}
else if (get_feature(drive, 0x3B, data, 32, ¤t) && current) {
printf("disc type: DVD+R DL\n"); *disc_type = DISC_DVDplusRDL;
}
else if (get_feature(drive, 0x1F, data, 32, ¤t) && current) {
printf("disc type: DVD-ROM\n"); *disc_type = DISC_DVDROM;
}
else {
printf("no DVD media found\n");
return 0;
}
read_dvd_structure(drive, 0, data);
int booktype = ((data[4] & 0xFF) >> 4);
printf("book type: %s\n", book_types[booktype]);
if (bDVDminus) {
if (booktype == 0x02) *disc_type = DISC_DVDminusR;
if (booktype == 0x03) *disc_type = DISC_DVDminusRW;
}
return 1;
}
int set_read_speed(DRIVE_INFO* drive, int speed)
{
unsigned char data[28]; memset(data, 0, 28);
int* start_lba = (int*)&data[4];
int* end_lba = (int*)&data[8];
int* read_size = (int*)&data[12];
int* read_time = (int*)&data[16];
int* write_size = (int*)&data[20];
int* write_time = (int*)&data[24];
int capacity; read_capacity(drive, &capacity);
*start_lba = swap4(0);
*end_lba = swap4(capacity);
*read_time = swap4(1000);
*read_size = swap4(speed);
*write_time = swap4(1000);
*write_size = swap4(22000);
SRB_ExecSCSICmd srbExec;
memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );
int j = ExecSCSICmd(SRB_DIR_OUT,drive,&srbExec,data,28,12,0xB6,0,0,0,0,0,0,0,0,0,28);
if (j == COMMAND_FAILED) return 0;
return 1;
}
int plextor_scan_pisum8(DRIVE_INFO* drive, int silent, int** result_map = NULL, int capacity = 0,
int* virtual_file = NULL, HANDLE hSemaphore = NULL)
{
void* pBuffer = malloc(32768);
__int64 capacity_in_bytes;
int scan_start_time;
int scan_end_time;
int last_update;
int produce_map = 0;
// int m;
const int last_pos_index_max = 8;
int k;
int last_pos[last_pos_index_max]; memset(last_pos, 0, sizeof(last_pos));
int last_pos_index = 0;
int last_time[last_pos_index_max];
if (!capacity) read_capacity(drive, &capacity);
capacity_in_bytes = (__int64)(capacity) * 2048;
printf("\n\nstarting PIsum8 test...\n");
if (!silent) printf("disc capacity: %d sectors = %d ECC blocks\n\n", capacity, capacity >> 4);
capacity >>= 7;
if (result_map) {
*result_map = (int*)calloc(sizeof(int), capacity+1);
(*result_map)[0] = capacity;
produce_map = 1;
}
if (virtual_file) {
*virtual_file++ = capacity;
ReleaseSemaphore(hSemaphore, 1, NULL);
}
int total_error_count = 0;
int current_error_count = 0;
int max_error_count = 0;
int broken_count = 0;
scan_start_time = GetTickCount();
last_update = GetTickCount();
plextor_start_pisum8(drive);
for (k=0;k<last_pos_index_max;last_time[k++]=scan_start_time-1);
for (k = 0;k<capacity;k++) {
plextor_pisum8_do_eight_ecc_blocks(drive, pBuffer, k*16*8, ¤t_error_count);
if (produce_map) (*result_map)[k+1] = current_error_count;
if (max_error_count < current_error_count) max_error_count = current_error_count;
if (current_error_count > 280) broken_count++;
if (virtual_file) {
*virtual_file++ = current_error_count;
ReleaseSemaphore(hSemaphore, 1, NULL);
}
if (GetTickCount() - last_update > 1000 || k==capacity-1) {
if (!debug) {
if (!silent) {
printf("\r");
printf("current speed: %5.2fx, %5.1f%% done, max: %d ",
(float)(k-last_pos[last_pos_index])*256/1.385/(GetTickCount()-last_time[last_pos_index]),
(float)k*100/capacity,max_error_count);
} else {
printf("\r");
printf("%5.1f%% done", (float)(k+1)*100/capacity);
}
}
last_update += 1000;
last_time[last_pos_index] = GetTickCount();
last_pos[last_pos_index++] = k;
last_pos_index%=last_pos_index_max;
}
}
for (k=0;k<capacity;total_error_count+=(*result_map)[k+++1]);
if (!silent) {
printf("\rtotal error count : %8d \n", total_error_count);
printf("average nbr of errors per sector : %8.2f\n", (float)total_error_count / k / 8);
printf("PIsum8 max : %8d\n", max_error_count);
printf("occurences of 8 consecutive blocks with PIsum8 > 280: %8d\n", broken_count);
} else printf("\n");
plextor_end_pi(drive);
scan_end_time = GetTickCount();
if (!silent) printf("duration : %d seconds\n", (scan_end_time - scan_start_time) / 1000);
delete pBuffer;
return 1;
}
int plextor_scan_pif(DRIVE_INFO* drive, int silent, int** result_map = NULL, int capacity = NULL,
int* virtual_file = NULL, HANDLE hSemaphore = NULL)
{
void* pBuffer = malloc(32768);
__int64 capacity_in_bytes;
int scan_start_time;
int scan_end_time;
int last_update;
int k;
int produce_map = 0;
const int last_pos_index_max = 8;
int last_pos[last_pos_index_max]; memset(last_pos, 0, sizeof(last_pos));
int last_pos_index = 0;
int last_time[last_pos_index_max];
if (!capacity) read_capacity(drive, &capacity);
capacity_in_bytes = (__int64)(capacity) * 2048;
printf("\n\nstarting PIF test...\n");
if (!silent) printf("disc capacity: %d sectors = %d ECC blocks\n\n", capacity, capacity >> 4);
capacity >>= 4;
if (virtual_file) {
*virtual_file++ = capacity;
ReleaseSemaphore(hSemaphore, 1, NULL);
}
if (result_map) {
*result_map = (int*)calloc(sizeof(int), capacity+1);
(*result_map)[0] = capacity;
produce_map = 1;
}
int total_error_count = 0;
int current_error_count = 0;
int max_error_count = 0;
int broken_count = 0;
scan_start_time = GetTickCount();
last_update = GetTickCount();
plextor_start_pif(drive);
for (k=0;k<last_pos_index_max;last_time[k++]=scan_start_time-1);
for (k = 0;k<capacity;k++) {
plextor_pif_do_one_ecc_block(drive, pBuffer, k*16, ¤t_error_count);
if (produce_map) (*result_map)[k+1] = current_error_count;
if (max_error_count < current_error_count) max_error_count = current_error_count;
if (current_error_count > 4) broken_count++;
if (virtual_file) {
*virtual_file++ = current_error_count;
ReleaseSemaphore(hSemaphore, 1, NULL);
}
if (GetTickCount() - last_update > 1000 || k==capacity - 1) {
if (!debug) {
if (!silent) {
printf("\r");
printf("current speed: %5.2fx, %5.1f%% done, max: %d",
(float)(k-last_pos[last_pos_index])*32/1.385/(GetTickCount()-last_time[last_pos_index]),
(float)k*100/capacity,
max_error_count);
} else {
printf("\r");
printf("%5.1f%% ", (float)(k+1)*100/capacity);
}
}
last_update += 1000;
last_time[last_pos_index] = GetTickCount();
last_pos[last_pos_index++] = k;
last_pos_index%=last_pos_index_max;
}
}
for (k=0;k<capacity;total_error_count+=(*result_map)[k+++1]);
if (!silent) {
printf("\rtotal error count : %8d \n", total_error_count);
printf("average nbr of errors per sector : %8.2f\n", (float)total_error_count / k / 8);
printf("PIF max : %8d\n", max_error_count);
printf("occurences of ECC blocks with PIF > 4 : %8d\n", broken_count);
} else printf("\n");
plextor_end_pi(drive);
scan_end_time = GetTickCount();
if (!silent) printf("duration : %d seconds\n", (scan_end_time - scan_start_time) / 1000);
delete pBuffer;
return 1;
}
int plextor_scan_jitterbeta(DRIVE_INFO* drive, int silent, int** result_map = NULL, int capacity = NULL,
int* virtual_file = NULL, HANDLE hSemaphore = NULL)
{
__int64 capacity_in_bytes;
short int beta;
int jitter, k;
unsigned int value;
int produce_map = 0;
void* pBuffer = malloc(32768);
if (!capacity) read_capacity(drive, &capacity);
capacity_in_bytes = (__int64)(capacity) * 2048;
printf("\n\nstarting J/B test...\n");
if (!silent) printf("disc capacity: %d sectors = %d ECC blocks\n\n", capacity, capacity >> 4);
capacity >>= 8;
plextor_start_jitterbeta(drive);
if (virtual_file) {
*virtual_file++ = capacity;
ReleaseSemaphore(hSemaphore, 1, NULL);
}
if (result_map) {
*result_map = (int*)calloc(sizeof(int), capacity+1);
(*result_map)[0] = capacity;
produce_map = 1;
}
for (k = 0;k<capacity;k++) {
plextor_jitterbeta_do_16_ecc_blocks(drive, pBuffer, k*16*16, &jitter, &beta);
value = (beta) << 16 | (jitter & 0xFFFF);
if (produce_map) (*result_map)[k+1] = value;
printf("\rLBA: %06X jitter: %4d, beta: %4d", k*16*16, jitter, (int)beta);
if (virtual_file) {
*virtual_file++ = value;
ReleaseSemaphore(hSemaphore, 1, NULL);
}
}
printf("\n");
plextor_end_pi(drive);
delete pBuffer;
return 1;
}
BOOL Init(int argc, char* argv[], int gigarec, int pisum8, int pif, int jb, void** results,
int silent, int speed = 2770, int immed_draw = 0)
{
char cBuffer[255];
char cBuffer2[255];
int i,j,k;
DRIVE_INFO* drive;
HANDLE hMemoryFile = 0;
HANDLE hSemaphore = NULL;
void* memory_file = NULL;
hMemoryFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, "pxstuff virtual file");
if (hMemoryFile) immed_draw = 1;
if (immed_draw) {
printf("sending data immediately to PxView...\n");
memory_file = MapViewOfFile(hMemoryFile, FILE_MAP_WRITE,0,0,0);
hSemaphore = OpenSemaphore(SEMAPHORE_ALL_ACCESS, 0, "pxstuff semaphore");
if (!hSemaphore) {
printf("Set PxView to capture mode before using draw_immed\n");
return 0;
}
}
// Symbol für dieses Dialogfeld festlegen. Wird automatisch erledigt
// wenn das Hauptfenster der Anwendung kein Dialogfeld ist
// ZU ERLEDIGEN: Hier zusätzliche Initialisierung einfügen
HINSTANCE hWNASPI32; // Handle to ASPI for Win32
hWNASPI32 = LoadLibrary("WNASPI32.DLL");
if(!hWNASPI32) /* If Load Failed */
{
printf(TEXT("LoadLibrary(\"WNASPI32.DLL\") Failed. Install ForceASPI 1.7.\n"));
return FALSE;
}
GetASPI32SupportInfo = (DWORD (*)(void))
GetProcAddress(hWNASPI32,"GetASPI32SupportInfo");
SendASPI32Command = (DWORD (*)(void *)) GetProcAddress(hWNASPI32,"SendASPI32Command");
GetASPI32Buffer = (BOOL (*)(void *)) GetProcAddress(hWNASPI32,"GetASPI32Buffer");
FreeASPI32Buffer = (BOOL (*)(void *)) GetProcAddress(hWNASPI32,"FreeASPI32Buffer");
TranslateASPI32Address = (BOOL (*)(DWORD*,DWORD*)) GetProcAddress(hWNASPI32,"TranslateASPI32Address");
if( !GetASPI32SupportInfo || !SendASPI32Command )
{
printf("Cannot find critical WNASPI32.DLL Functions!\n");
return FALSE;
}
BYTE HACount;
BYTE ASPIStatus;
DWORD SupportInfo;
SupportInfo = GetASPI32SupportInfo();
HACount = LOBYTE(LOWORD(SupportInfo));
ASPIStatus = HIBYTE(LOWORD(SupportInfo));
printf("\nLooking for drives...\n");
if (!HACount) {
printf("Broken result received by GetASPI32SupportInfo()\n");
HACount = 15;
}
for (i=0;i<HACount;i++)
{
SRB_HAInquiry HAInquiry; // Create a data struct for our command.
memset( &HAInquiry, 0, sizeof(SRB_HAInquiry) ); // Zero out the SRB
HAInquiry.SRB_Cmd = SC_HA_INQUIRY;
HAInquiry.SRB_HaId = i;
for (j=0;j<16;j++)
{
for (k=0;k<16;k++)
{
DWORD dwASPIStatus;
SRB_GDEVBlock GDEVBlock;
HANDLE heventSRB;
memset( &GDEVBlock, 0, sizeof( SRB_GDEVBlock ));
GDEVBlock.SRB_Cmd = SC_GET_DEV_TYPE;
GDEVBlock.SRB_HaId = i; // Host Adapter
GDEVBlock.SRB_Target = j; // SCSI ID
GDEVBlock.SRB_Lun = k;
heventSRB = CreateEvent( NULL, TRUE, FALSE, NULL );
if( !heventSRB ) {
// Couldn't get manual reset event, put error handling code here!
printf("failed to create event!\n");
}
GDEVBlock.SRB_Flags = SRB_EVENT_NOTIFY;
dwASPIStatus = SendASPI32Command( (LPSRB)&GDEVBlock );
if( dwASPIStatus == SS_PENDING ) {
WaitForSingleObject( heventSRB, INFINITE );
}
if (dwASPIStatus == SS_BAD_INSTALL) {
printf("ASPI error: 'Bad Installation'\n");
}
if( GDEVBlock.SRB_Status != SS_COMP )
{ // Handle Error Code
}
else // No error*/
{
if( GDEVBlock.SRB_DeviceType == DTYPE_CDROM )
{
SRB_ExecSCSICmd srbExec;
memset( &srbExec, 0, sizeof(SRB_ExecSCSICmd) );
ZeroMemory(cBuffer,sizeof(cBuffer));
srbExec.SRB_Cmd = SC_EXEC_SCSI_CMD;
srbExec.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
srbExec.SRB_Target = GDEVBlock.SRB_Target;
srbExec.SRB_Lun = GDEVBlock.SRB_Lun;
srbExec.SRB_HaId = GDEVBlock.SRB_HaId;
srbExec.SRB_BufLen = sizeof(cBuffer);
srbExec.SRB_BufPointer = (unsigned char*)cBuffer;
srbExec.SRB_SenseLen = SENSE_LEN;
srbExec.SRB_CDBLen = 6;
srbExec.SRB_PostProc = (LPVOID)heventSRB;
srbExec.CDBByte[0] = SCSI_INQUIRY;
srbExec.CDBByte[4] = sizeof(cBuffer);
ResetEvent( heventSRB );
dwASPIStatus = SendASPI32Command( (LPSRB)&srbExec );
if( dwASPIStatus == SS_PENDING )
{
WaitForSingleObject( heventSRB, INFINITE );
}
if( srbExec.SRB_Status != SS_COMP )
{
// Error processing the SRB, put error handling code here.
}
else
{
drive = (DRIVE_INFO*)calloc(1,sizeof(DRIVE_INFO));
lstrcpyn(drive->vendor_ID,&(cBuffer[8]),9);
lstrcpyn(drive->product_ID,&(cBuffer[16]),17);
lstrcpyn(drive->product_revision,&(cBuffer[32]),5);
drive->haID=GDEVBlock.SRB_HaId;
drive->Target=GDEVBlock.SRB_Target;
drive->Lun=GDEVBlock.SRB_Lun;
int plextor = 0;
int qchk = 0;
if (!strncmp(drive->vendor_ID, "PLEXTOR", 7)) {
if (!strncmp(drive->product_ID, "DVDR PX-716",13)) {
char* c = drive->product_revision + 2;
plextor=1;
qchk = 1;
} else
if (!strncmp(drive->product_ID, "DVDR PX-712",13)) {
char* c = drive->product_revision + 2;
plextor=1;
qchk = 1;
} else
if (!strncmp(drive->product_ID, "CD-R PREMIUM",14)) {
char* c = drive->product_revision + 2;
plextor=1;
}
}
sprintf(cBuffer2,"Drive %d:%d:%d: %s %s %s \n",GDEVBlock.SRB_HaId,
GDEVBlock.SRB_Target,GDEVBlock.SRB_Lun,drive->vendor_ID,drive->product_ID,
drive->product_revision);
if (plextor) printf(cBuffer2);
//printf("\n");
SRB_GetSetTimeouts srbGetSetTimeouts;
memset( &srbGetSetTimeouts, 0, sizeof(SRB_GetSetTimeouts) );
srbGetSetTimeouts.SRB_Cmd = SC_GETSET_TIMEOUTS;
srbGetSetTimeouts.SRB_Flags = SRB_DIR_OUT;
srbGetSetTimeouts.SRB_Target = drive->Target;
srbGetSetTimeouts.SRB_Lun = drive->Lun;
srbGetSetTimeouts.SRB_HaId = drive->haID;
srbGetSetTimeouts.SRB_Timeout = 10*2;
SendASPI32Command( (LPSRB)&srbGetSetTimeouts );
if( srbGetSetTimeouts.SRB_Status != SS_COMP )
{
// Error setting timeouts. Put error handling code here.
}
if (plextor) {
int i;
if (!silent) plextor_read_gigarec(drive, &i);
if (gigarec>-1) {
plextor_set_gigarec(drive, gigarec);
if (!silent) plextor_read_gigarec(drive, &i);
}
if (qchk && (pisum8 || pif || jb)) {
int disc_type = -1;
if (determine_disc_type(drive, &disc_type)) {
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
void* pData = malloc(2056);
if (disc_type == DISC_DVDminusR || disc_type == DISC_DVDminusRW) {
read_dvd_structure(drive, 0x0E, (char*)pData);
eval_dvd_struct_0e(pData);
} else if (disc_type == DISC_DVDplusR || disc_type == DISC_DVDplusRW
|| disc_type == DISC_DVDplusRDL) {
read_dvd_structure(drive, 0x11, (char*)pData);
eval_dvd_struct_11_dvdplus(pData);
} else {
read_dvd_structure(drive, 0x00, (char*)pData);
eval_dvd_struct_11_dvdplus(pData);
if (((char*)pData)[23]) {
printf("DVD-ROM and manufacturer ID detected. Disc might be DVD+R DL (\?\?\?)\n");
} else {
read_dvd_structure(drive, 0x0E, (char*)pData);
eval_dvd_struct_0e(pData);
if (((char*)pData)[23]) {
printf("DVD-ROM and manufacturer ID detected. Disc might be bitsetted DVD-R (\?\?\?)\n");
}
}
}
free(pData);
printf("trying to set speed to %dx\n", speed/1385);
set_read_speed(drive, speed);
int capacity = 0;
read_capacity(drive, &capacity);
if (!capacity) {
printf("reading capacity failed!");
return 0;
}
int scanval = 4*jb + 2*pif + pisum8;
int* vfile = (int*)memory_file;
if (vfile) *vfile++ = scanval;
if (pisum8) {
plextor_scan_pisum8(drive, silent, (int**)&results[0], capacity,
vfile, hSemaphore);
if (vfile) vfile+=1+(capacity>>7);
}
if (pif) {
plextor_scan_pif(drive, silent, (int**)&results[1], capacity,
vfile, hSemaphore);
if (vfile) vfile+=1+(capacity>>4);
}
if (jb) {
plextor_scan_jitterbeta(drive, silent, (int**)&results[2], capacity,
vfile, hSemaphore);
}
}
}
}
}
}
}
}
}
}
// TODO:
// If ASPIStatus != SS_COMP and != SS_NO_ADAPTERS, you must handle the error.
// Then, inside your Main/WinMain function:
/* Load Real ASPI Layer, WNASPI32.DLL */
return TRUE; // Geben Sie TRUE zurück, außer ein Steuerelement soll den Fokus erhalten
}
int main(int argc, char* argv[])
{
int gigarec = -1;
int pisum8 = 0;
int pif = 0;
int jb = 0;
int silent = 0;
int immed_draw=0;
int* results[3] = { NULL, NULL, NULL };
char destfile[1024]; destfile[0]=0;
int speed = 2770;
printf("\nPxScan v1.3, built %s %s\n", __DATE__, __TIME__);
for (int j=1;j<argc;j++) {
if (!strcmp(argv[j],"debug")) debug=1; else
if (!strnicmp(argv[j],"gigarec=",8)) {
if (!strnicmp(argv[j]+8, "1.2", 3)) {
gigarec = 0x01;
}
if (!strnicmp(argv[j]+8, "1.3", 3)) {
gigarec = 0x02;
}
if (!strnicmp(argv[j]+8, "1.4", 3)) {
gigarec = 0x03;
}
if (!strnicmp(argv[j]+8, "0.6", 3)) {
gigarec = 0x83;
}
if (!strnicmp(argv[j]+8, "0.7", 3)) {
gigarec = 0x82;
}
if (!strnicmp(argv[j]+8, "0.8", 3)) {
gigarec = 0x81;
}
} else
if (!stricmp(argv[j], "pisum8")) {
printf(" performing PIsum8 scan\n");
pisum8 = 1;
} else
if (!stricmp(argv[j], "pif")) {
printf(" performing PIF scan\n");
pif = 1;
} else
if (!stricmp(argv[j], "silent")) {
silent = 1;
} else
if (!stricmp(argv[j], "jitterbeta")) {
printf(" performing jitter/beta scan\n");
jb = 1;
} else
if (!strnicmp(argv[j], "destfile=", 9)) {
strcpy(destfile, argv[j]+9);
printf(" output file for results: %s\n", destfile);
} else
if (!strnicmp(argv[j], "speed=", 6)) {
speed=atoi(argv[j]+6)*1385;
} else {
printf(" unknown option: %s\n", argv[j]);
}
}
Init(argc, argv, gigarec, pisum8, pif, jb, (void**)results, silent, speed,
immed_draw);
printf("\n");
if (strlen(destfile) && (pisum8 || pif | jb) && (results[0] || results[1] || results[2])) {
FILE* f = fopen(destfile, "wb");
int present_mask = 0;
if (pisum8) present_mask |= 1;
if (pif) present_mask |= 2;
if (jb) present_mask |= (1<<16);
fwrite(&present_mask, 4, 1, f);
if (pisum8) {
printf("writing PIsum8 results (%d values) ...\n", results[0][0]);
fwrite(&(results[0][0]), 4, 1, f);
fwrite(&results[0][1], 4, results[0][0], f);
}
if (pif) {
printf("writing PIF results (%d values) ...\n", results[1][0]);
fwrite(&(results[1][0]), 4, 1, f);
fwrite(&results[1][1], 4, results[1][0], f);
}
if (jb) {
printf("writing J/B results (%d values) ...\n", results[2][0]);
fwrite(&(results[2][0]), 4, 1, f);
fwrite(&results[2][1], 4, results[2][0], f);
}
fclose(f);
}
if (results[0]) delete results[0];
if (results[1]) delete results[1];
printf("\n\n");
return 0;
}
Reply to: