Interpreting feature 0x107 when deciding from where to get speed info

This commit is contained in:
Thomas Schmitt 2014-01-09 13:23:23 +00:00
parent d362438935
commit b2f94af25a
5 changed files with 215 additions and 126 deletions

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2014.01.07.115938" #define Cdrskin_timestamP "2014.01.09.132159"

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2013 Thomas Schmitt <scdbackup@gmx.net> Copyright (c) 2006 - 2014 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later. Provided under GPL version 2 or later.
This is the official API definition of libburn. This is the official API definition of libburn.
@ -713,7 +713,11 @@ struct burn_progress {
struct burn_speed_descriptor { struct burn_speed_descriptor {
/** Where this info comes from : /** Where this info comes from :
0 = misc , 1 = mode page 2Ah , 2 = ACh GET PERFORMANCE */ 0 = misc
1 = mode page 2Ah
2 = ACh GET PERFORMANCE Type 03h
3 = ACh GET PERFORMANCE Type 00h Data Type 10h (read speed)
*/
int source; int source;
/** The media type that was current at the time of report /** The media type that was current at the time of report

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2012 Thomas Schmitt <scdbackup@gmx.net> Copyright (c) 2006 - 2014 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later. Provided under GPL version 2 or later.
*/ */
@ -4210,41 +4210,182 @@ ex:;
} }
/* ts A61225 */ /* ts B40107 : Outsourced from mmc_get_performance_al()
/* @param flag bit0= register speed descriptors
*/ */
static int mmc_get_write_performance_al(struct burn_drive *d, static int new_burn_speed_descr(struct burn_drive *d, int sd_source,
int *alloc_len, int *max_descr, int flag) struct burn_speed_descriptor **sd, int flag)
{ {
struct buffer *buf = NULL; int ret;
int len, i, b, num_descr, ret, old_alloc_len;
int exact_bit, read_speed, write_speed;
/* >>> ts B10702: This rule seems questionable: ret = burn_speed_descriptor_new(&(d->mdata->speed_descriptors),
TSST SH-203 delivers here for CD only 7040k NULL, d->mdata->speed_descriptors, 0);
whereas mode page 2Ah gives 1412k to 7056k if (ret <= 0)
*/ return ret;
/* if this call delivers usable data then they should override
previously recorded min/max speed and not compete with them */ *sd = d->mdata->speed_descriptors;
(*sd)->source = sd_source;
if (d->current_profile > 0) {
(*sd)->profile_loaded = d->current_profile;
strcpy((*sd)->profile_name, d->current_profile_text);
}
return 1;
}
/* ts B40107 : Outsourced from mmc_get_performance_al()
and extended for descr_type 0x00
@param flag bit0= register speed descriptors
*/
static int interpret_performance(struct burn_drive *d, struct command *c,
int descr_type, int *alloc_len, int *max_descr,
int *num_descr, int flag)
{
int len, i, b, ret, old_alloc_len;
int exact_bit, read_speed, write_speed, start_speed;
int min_write_speed = 0x7fffffff, max_write_speed = 0; int min_write_speed = 0x7fffffff, max_write_speed = 0;
int min_read_speed = 0x7fffffff, max_read_speed = 0; int min_read_speed = 0x7fffffff, max_read_speed = 0;
struct command *c = NULL;
unsigned long end_lba; unsigned long end_lba;
unsigned char *pd; unsigned char *pd;
struct burn_speed_descriptor *sd; struct burn_speed_descriptor *sd;
/* A61225 : 1 = report about speed descriptors */ /* ts A61225 : 1 = report about speed descriptors */
static int speed_debug = 0; static int speed_debug = 0;
len = mmc_four_char_to_int(c->page->data);
old_alloc_len = *alloc_len;
*alloc_len = len + 4;
if (len + 4 > old_alloc_len)
len = old_alloc_len - 4;
*num_descr = ( *alloc_len - 8 ) / 16;
if (*max_descr == 0) {
*max_descr = *num_descr;
{ret = 1; goto ex;}
}
if (old_alloc_len < 16)
{ret = 1; goto ex;}
if (len < 12)
{ret = 0; goto ex;}
min_write_speed = d->mdata->min_write_speed;
max_write_speed = d->mdata->max_write_speed;
pd = c->page->data;
if (*num_descr > *max_descr)
*num_descr = *max_descr;
for (i = 0; i < *num_descr && (flag & 1); i++) {
end_lba = read_speed = write_speed = start_speed = 0;
if (descr_type == 0x03) {
exact_bit = !!(pd[8 + i*16] & 2);
for (b = 0; b < 4 ; b++) {
end_lba += pd[8 + i*16 + 4 + b]
<< (24 - 8 * b);
read_speed += pd[8 + i*16 + 8 + b]
<< (24 - 8 * b);
write_speed += pd[8 + i*16 + 12 + b]
<< (24 - 8 * b);
}
if (end_lba > 0x7ffffffe)
end_lba = 0x7ffffffe;
if (speed_debug)
fprintf(stderr,
"LIBBURN_DEBUG: kB/s: write=%d read=%d end=%lu exact=%d\n",
write_speed, read_speed,
end_lba, exact_bit);
ret = new_burn_speed_descr(d, 2, &sd, 0);
if (ret > 0) {
sd->wrc = (pd[8 + i*16] >> 3 ) & 3;
sd->exact = exact_bit;
sd->mrw = pd[8 + i*16] & 1;
sd->end_lba = end_lba;
sd->write_speed = write_speed;
sd->read_speed = read_speed;
}
} else { /* descr_type == 0 */
for (b = 0; b < 4 ; b++) {
start_speed += pd[8 + i*16 + 4 + b]
<< (24 - 8 * b);
end_lba += pd[8 + i*16 + 8 + b]
<< (24 - 8 * b);
read_speed += pd[8 + i*16 + 12 + b]
<< (24 - 8 * b);
}
if (speed_debug)
fprintf(stderr,
"LIBBURN_DEBUG: start=%d end=%d lba=%lu\n",
start_speed, read_speed, end_lba);
if (end_lba > 0x7ffffffe)
end_lba = 0x7ffffffe;
ret = new_burn_speed_descr(d, 3, &sd, 0);
if (ret > 0) {
sd->end_lba = end_lba;
sd->read_speed = start_speed;
}
if (start_speed > 0 && start_speed < min_read_speed)
min_read_speed = start_speed;
if (start_speed > max_read_speed)
max_read_speed = start_speed;
ret = new_burn_speed_descr(d, 3, &sd, 0);
if (ret > 0) {
sd->end_lba = end_lba;
sd->read_speed = read_speed;
}
}
if ((int) end_lba > d->mdata->max_end_lba)
d->mdata->max_end_lba = end_lba;
if ((int) end_lba < d->mdata->min_end_lba)
d->mdata->min_end_lba = end_lba;
if (write_speed > 0 && write_speed < min_write_speed)
min_write_speed = write_speed;
if (write_speed > max_write_speed)
max_write_speed = write_speed;
if (read_speed > 0 && read_speed < min_read_speed)
min_read_speed = read_speed;
if (read_speed > max_read_speed)
max_read_speed = read_speed;
}
if (min_write_speed < 0x7fffffff)
d->mdata->min_write_speed = min_write_speed;
if (max_write_speed > 0)
d->mdata->max_write_speed = max_write_speed;
/* there is no mdata->min_read_speed yet
if (min_read_speed < 0x7fffffff)
d->mdata->min_read_speed = min_read_speed;
*/
if (max_read_speed > 0)
d->mdata->max_read_speed = max_read_speed;
ret = 1;
ex:;
return ret;
}
/* ts A61225 */
/* @param flag bit0= register speed descriptors
*/
static int mmc_get_performance_al(struct burn_drive *d, int descr_type,
int *alloc_len, int *max_descr, int flag)
{
int num_descr, ret;
struct buffer *buf = NULL;
struct command *c = NULL;
BURN_ALLOC_MEM(buf, struct buffer, 1); BURN_ALLOC_MEM(buf, struct buffer, 1);
BURN_ALLOC_MEM(c, struct command, 1); BURN_ALLOC_MEM(c, struct command, 1);
if (d->current_profile <= 0) if (d->current_profile < 0)
mmc_get_configuration(d); mmc_get_configuration(d);
if (*alloc_len < 8) if (*alloc_len < 8)
{ret = 0; goto ex;} {ret = 0; goto ex;}
if (descr_type != 0x00 && descr_type != 0x03)
{ret = 0; goto ex;}
scsi_init_command(c, MMC_GET_PERFORMANCE, scsi_init_command(c, MMC_GET_PERFORMANCE,
sizeof(MMC_GET_PERFORMANCE)); sizeof(MMC_GET_PERFORMANCE));
@ -4255,9 +4396,11 @@ static int mmc_get_write_performance_al(struct burn_drive *d,
*/ */
c->dxfer_len = *alloc_len; c->dxfer_len = *alloc_len;
if (descr_type == 0x00)
c->opcode[1] = 0x10; /* Data Type: nominal read performance */
c->opcode[8] = ( *max_descr >> 8 ) & 0xff; c->opcode[8] = ( *max_descr >> 8 ) & 0xff;
c->opcode[9] = ( *max_descr >> 0 ) & 0xff; c->opcode[9] = ( *max_descr >> 0 ) & 0xff;
c->opcode[10] = 3; c->opcode[10] = descr_type;
c->retry = 1; c->retry = 1;
c->page = buf; c->page = buf;
c->page->sectors = 0; c->page->sectors = 0;
@ -4275,86 +4418,12 @@ static int mmc_get_write_performance_al(struct burn_drive *d,
if (c->error) if (c->error)
{ret = 0; goto ex;} {ret = 0; goto ex;}
len = mmc_four_char_to_int(c->page->data);
old_alloc_len = *alloc_len;
*alloc_len = len + 4;
if (len + 4 > old_alloc_len)
len = old_alloc_len - 4;
num_descr = ( *alloc_len - 8 ) / 16;
if (*max_descr == 0) {
*max_descr = num_descr;
{ret = 1; goto ex;}
}
if (old_alloc_len < 16)
{ret = 1; goto ex;}
if (len < 12)
{ret = 0; goto ex;}
/* ts B10702 : overriding the questionable override rule */ ret = interpret_performance(d, c, descr_type, alloc_len, max_descr,
min_write_speed = d->mdata->min_write_speed; &num_descr, flag);
max_write_speed = d->mdata->max_write_speed; if (ret <= 0)
goto ex;
pd = c->page->data;
if (num_descr > *max_descr)
num_descr = *max_descr;
for (i = 0; i < num_descr && (flag & 1); i++) {
exact_bit = !!(pd[8 + i*16] & 2);
end_lba = read_speed = write_speed = 0;
for (b = 0; b < 4 ; b++) {
end_lba += pd[8 + i*16 + 4 + b] << (24 - 8 * b);
read_speed += pd[8 + i*16 + 8 + b] << (24 - 8 * b);
write_speed += pd[8 + i*16 + 12 + b] << (24 - 8 * b);
}
if (end_lba > 0x7ffffffe)
end_lba = 0x7ffffffe;
if (speed_debug)
fprintf(stderr,
"LIBBURN_DEBUG: kB/s: write=%d read=%d end=%lu exact=%d\n",
write_speed, read_speed, end_lba, exact_bit);
/* ts A61226 */
ret = burn_speed_descriptor_new(&(d->mdata->speed_descriptors),
NULL, d->mdata->speed_descriptors, 0);
if (ret > 0) {
sd = d->mdata->speed_descriptors;
sd->source = 2;
if (d->current_profile > 0) {
sd->profile_loaded = d->current_profile;
strcpy(sd->profile_name,
d->current_profile_text);
}
sd->wrc = (pd[8 + i*16] >> 3 ) & 3;
sd->exact = exact_bit;
sd->mrw = pd[8 + i*16] & 1;
sd->end_lba = end_lba;
sd->write_speed = write_speed;
sd->read_speed = read_speed;
}
if ((int) end_lba > d->mdata->max_end_lba)
d->mdata->max_end_lba = end_lba;
if ((int) end_lba < d->mdata->min_end_lba)
d->mdata->min_end_lba = end_lba;
if (write_speed < min_write_speed)
min_write_speed = write_speed;
if (write_speed > max_write_speed)
max_write_speed = write_speed;
if (read_speed < min_read_speed)
min_read_speed = read_speed;
if (read_speed > max_read_speed)
max_read_speed = read_speed;
}
if (min_write_speed < 0x7fffffff)
d->mdata->min_write_speed = min_write_speed;
if (max_write_speed > 0)
d->mdata->max_write_speed = max_write_speed;
/* there is no mdata->min_read_speed yet
if (min_read_speed < 0x7fffffff)
d->mdata->min_read_speed = min_read_speed;
*/
if (max_read_speed > 0)
d->mdata->max_read_speed = max_read_speed;
ret = num_descr; ret = num_descr;
ex:; ex:;
BURN_FREE_MEM(buf); BURN_FREE_MEM(buf);
@ -4363,7 +4432,7 @@ ex:;
} }
int mmc_get_write_performance(struct burn_drive *d) int mmc_get_performance(struct burn_drive *d, int descr_type, int flag)
{ {
int alloc_len = 8, max_descr = 0, ret; int alloc_len = 8, max_descr = 0, ret;
@ -4374,23 +4443,33 @@ int mmc_get_write_performance(struct burn_drive *d)
/* first command execution to learn number of descriptors and /* first command execution to learn number of descriptors and
dxfer_len dxfer_len
*/ */
ret = mmc_get_write_performance_al(d, &alloc_len, &max_descr, 0); ret = mmc_get_performance_al(d, descr_type, &alloc_len, &max_descr, 0);
if (max_descr > 0 && ret > 0) { if (max_descr > 0 && ret > 0) {
/* Some drives announce only 1 descriptor if asked for 0. /* Some drives announce only 1 descriptor if asked for 0.
So ask twice for non-0 descriptors. So ask twice for non-0 descriptors.
*/ */
ret = mmc_get_write_performance_al(d, &alloc_len, &max_descr, ret = mmc_get_performance_al(d, descr_type,
0); &alloc_len, &max_descr, 0);
} }
/* /*
fprintf(stderr,"LIBBURN_DEBUG: ACh alloc_len = %d , ret = %d\n", fprintf(stderr,"LIBBURN_DEBUG: ACh alloc_len = %d , ret = %d\n",
alloc_len, ret); alloc_len, ret);
*/ */
if (max_descr > 0 && ret > 0) if (max_descr > 0 && ret > 0) {
/* final execution with announced length */ /* final execution with announced length */
max_descr = (alloc_len - 8) / 16; max_descr = (alloc_len - 8) / 16;
ret = mmc_get_write_performance_al(d, &alloc_len, &max_descr, ret = mmc_get_performance_al(d, descr_type,
1); &alloc_len, &max_descr, 1);
}
return ret;
}
int mmc_get_write_performance(struct burn_drive *d)
{
int ret;
ret = mmc_get_performance(d, 0x03, 0);
return ret; return ret;
} }
@ -5240,6 +5319,7 @@ int mmc_setup_drive(struct burn_drive *d)
d->wfb_timeout_sec = Libburn_wait_for_buffer_tio_seC; d->wfb_timeout_sec = Libburn_wait_for_buffer_tio_seC;
d->wfb_min_percent = Libburn_wait_for_buffer_min_perC; d->wfb_min_percent = Libburn_wait_for_buffer_min_perC;
d->wfb_max_percent = Libburn_wait_for_buffer_max_perC; d->wfb_max_percent = Libburn_wait_for_buffer_max_perC;
d->sent_default_page_05 = 0;
return 1; return 1;
} }

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net> Copyright (c) 2006 - 2014 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later. Provided under GPL version 2 or later.
*/ */
@ -127,6 +127,9 @@ int mmc_get_phys_format_info(struct burn_drive *d, int *disk_category,
int mmc_get_leadin_text(struct burn_drive *d, int mmc_get_leadin_text(struct burn_drive *d,
unsigned char **text_packs, int *num_packs, int flag); unsigned char **text_packs, int *num_packs, int flag);
/* ts B40107 */
int mmc_get_performance(struct burn_drive *d, int descr_type, int flag);
#ifdef Libburn_develop_quality_scaN #ifdef Libburn_develop_quality_scaN
/* B21108 ts */ /* B21108 ts */

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2013 Thomas Schmitt <scdbackup@gmx.net> Copyright (c) 2006 - 2014 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later. Provided under GPL version 2 or later.
*/ */
@ -416,6 +416,7 @@ static int spc_sense_caps_al(struct burn_drive *d, int *alloc_len, int flag)
struct command *c = NULL; struct command *c = NULL;
struct burn_speed_descriptor *sd; struct burn_speed_descriptor *sd;
char *msg = NULL; char *msg = NULL;
struct burn_feature_descr *feature_descr;
/* ts A61225 : 1 = report about post-MMC-1 speed descriptors */ /* ts A61225 : 1 = report about post-MMC-1 speed descriptors */
static int speed_debug = 0; static int speed_debug = 0;
@ -585,24 +586,25 @@ static int spc_sense_caps_al(struct burn_drive *d, int *alloc_len, int flag)
m->min_write_speed, m->max_write_speed); m->min_write_speed, m->max_write_speed);
try_mmc_get_performance:; try_mmc_get_performance:;
if (m->cdrw_write || page_length >= 32) { /* ts B40107 : Feature 0x107 announces availability of GET PERFORMANCE
/* ts A90823: Its WSPD bit announces Type 3.
One has to avoid U3 enhanced memory sticks here. On my Try this even if the feature is not current.
SuSE 10.2 a SanDisk Cruzer 4GB stalls at the second occasion
of ACh GET PERFORMANCE. (The first one is obviously called
by the OS at plug time.)
This pseudo drive returns no write capabilities and a page
length of 28. MMC-3 describes page length 32. Regrettably
MMC-2 prescribes a page length of 26. Here i have to trust
m->cdrw_write to reliably indicate any MMC-2 burner.
*/ */
ret = burn_drive_has_feature(d, 0x107, &feature_descr, 0);
if (ret > 0) {
if (feature_descr->data_lenght > 0) {
if (feature_descr->data[0] & 2) { /* WSPD */
ret = mmc_get_write_performance(d); ret = mmc_get_write_performance(d);
if (ret > 0 && speed_debug) if (ret > 0 && speed_debug)
fprintf(stderr, fprintf(stderr,
"LIBBURN_DEBUG: ACh min_write_speed = %d , max_write_speed = %d\n", "LIBBURN_DEBUG: ACh min_write_speed = %d , max_write_speed = %d\n",
m->min_write_speed, m->max_write_speed); m->min_write_speed,
m->max_write_speed);
}
/* Get read performance */
mmc_get_performance(d, 0x00, 0);
}
} }
ret = !was_error; ret = !was_error;
ex: ex:
BURN_FREE_MEM(msg); BURN_FREE_MEM(msg);