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 658851a497
commit 1c6f6c084f
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,27 +4443,37 @@ 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; return ret;
} }
int mmc_get_write_performance(struct burn_drive *d)
{
int ret;
ret = mmc_get_performance(d, 0x03, 0);
return ret;
}
/* ts A61229 : outsourced from spc_select_write_params() */ /* ts A61229 : outsourced from spc_select_write_params() */
/* Note: Page data is not zeroed here to allow preset defaults. Thus /* Note: Page data is not zeroed here to allow preset defaults. Thus
memset(pd, 0, 2 + d->mdata->write_page_length); memset(pd, 0, 2 + d->mdata->write_page_length);
@ -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 ret = burn_drive_has_feature(d, 0x107, &feature_descr, 0);
by the OS at plug time.) if (ret > 0) {
This pseudo drive returns no write capabilities and a page if (feature_descr->data_lenght > 0) {
length of 28. MMC-3 describes page length 32. Regrettably if (feature_descr->data[0] & 2) { /* WSPD */
MMC-2 prescribes a page length of 26. Here i have to trust ret = mmc_get_write_performance(d);
m->cdrw_write to reliably indicate any MMC-2 burner. if (ret > 0 && speed_debug)
*/ fprintf(stderr,
ret = mmc_get_write_performance(d); "LIBBURN_DEBUG: ACh min_write_speed = %d , max_write_speed = %d\n",
if (ret > 0 && speed_debug) m->min_write_speed,
fprintf(stderr, m->max_write_speed);
"LIBBURN_DEBUG: ACh min_write_speed = %d , max_write_speed = %d\n", }
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);