Browse Source

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

1.3.6
Thomas Schmitt 8 years ago
parent
commit
1c6f6c084f
  1. 2
      cdrskin/cdrskin_timestamp.h
  2. 8
      libburn/libburn.h
  3. 278
      libburn/mmc.c
  4. 5
      libburn/mmc.h
  5. 38
      libburn/spc.c

2
cdrskin/cdrskin_timestamp.h

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

8
libburn/libburn.h

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* 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.
This is the official API definition of libburn.
@ -713,7 +713,11 @@ struct burn_progress {
struct burn_speed_descriptor {
/** 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;
/** The media type that was current at the time of report

278
libburn/mmc.c

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* 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.
*/
@ -4210,79 +4210,55 @@ ex:;
}
/* ts A61225 */
/* @param flag bit0= register speed descriptors
/* ts B40107 : Outsourced from mmc_get_performance_al()
*/
static int mmc_get_write_performance_al(struct burn_drive *d,
int *alloc_len, int *max_descr, int flag)
static int new_burn_speed_descr(struct burn_drive *d, int sd_source,
struct burn_speed_descriptor **sd, int flag)
{
struct buffer *buf = NULL;
int len, i, b, num_descr, ret, old_alloc_len;
int exact_bit, read_speed, write_speed;
int ret;
/* >>> ts B10702: This rule seems questionable:
TSST SH-203 delivers here for CD only 7040k
whereas mode page 2Ah gives 1412k to 7056k
*/
/* if this call delivers usable data then they should override
previously recorded min/max speed and not compete with them */
ret = burn_speed_descriptor_new(&(d->mdata->speed_descriptors),
NULL, d->mdata->speed_descriptors, 0);
if (ret <= 0)
return ret;
*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_read_speed = 0x7fffffff, max_read_speed = 0;
struct command *c = NULL;
unsigned long end_lba;
unsigned char *pd;
struct burn_speed_descriptor *sd;
/* A61225 : 1 = report about speed descriptors */
/* ts A61225 : 1 = report about speed descriptors */
static int speed_debug = 0;
BURN_ALLOC_MEM(buf, struct buffer, 1);
BURN_ALLOC_MEM(c, struct command, 1);
if (d->current_profile <= 0)
mmc_get_configuration(d);
if (*alloc_len < 8)
{ret = 0; goto ex;}
scsi_init_command(c, MMC_GET_PERFORMANCE,
sizeof(MMC_GET_PERFORMANCE));
/* >>> future: maintain a list of write descriptors
if (max_descr > d->max_write_descr - d->num_write_descr)
max_descr = d->max_write_descr;
*/
c->dxfer_len = *alloc_len;
c->opcode[8] = ( *max_descr >> 8 ) & 0xff;
c->opcode[9] = ( *max_descr >> 0 ) & 0xff;
c->opcode[10] = 3;
c->retry = 1;
c->page = buf;
c->page->sectors = 0;
c->page->bytes = 0;
c->dir = FROM_DRIVE;
d->issue_command(d, c);
#ifdef Libisofs_simulate_old_mmc1_drivE
c->error = 1;
c->sense[0] = 0x70; /* Fixed format sense data */
c->sense[2] = 0x5;
c->sense[12] = 0x20;
c->sense[13] = 0x0;
#endif /* Libisofs_simulate_old_mmc1_drivE */
if (c->error)
{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;
*num_descr = ( *alloc_len - 8 ) / 16;
if (*max_descr == 0) {
*max_descr = num_descr;
*max_descr = *num_descr;
{ret = 1; goto ex;}
}
if (old_alloc_len < 16)
@ -4290,57 +4266,85 @@ static int mmc_get_write_performance_al(struct burn_drive *d,
if (len < 12)
{ret = 0; goto ex;}
/* ts B10702 : overriding the questionable override rule */
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++) {
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 (*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,
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);
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);
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;
}
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)
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 < min_read_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;
@ -4355,6 +4359,71 @@ static int mmc_get_write_performance_al(struct burn_drive *d,
*/
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(c, struct command, 1);
if (d->current_profile < 0)
mmc_get_configuration(d);
if (*alloc_len < 8)
{ret = 0; goto ex;}
if (descr_type != 0x00 && descr_type != 0x03)
{ret = 0; goto ex;}
scsi_init_command(c, MMC_GET_PERFORMANCE,
sizeof(MMC_GET_PERFORMANCE));
/* >>> future: maintain a list of write descriptors
if (max_descr > d->max_write_descr - d->num_write_descr)
max_descr = d->max_write_descr;
*/
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[9] = ( *max_descr >> 0 ) & 0xff;
c->opcode[10] = descr_type;
c->retry = 1;
c->page = buf;
c->page->sectors = 0;
c->page->bytes = 0;
c->dir = FROM_DRIVE;
d->issue_command(d, c);
#ifdef Libisofs_simulate_old_mmc1_drivE
c->error = 1;
c->sense[0] = 0x70; /* Fixed format sense data */
c->sense[2] = 0x5;
c->sense[12] = 0x20;
c->sense[13] = 0x0;
#endif /* Libisofs_simulate_old_mmc1_drivE */
if (c->error)
{ret = 0; goto ex;}
ret = interpret_performance(d, c, descr_type, alloc_len, max_descr,
&num_descr, flag);
if (ret <= 0)
goto ex;
ret = num_descr;
ex:;
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;
@ -4374,27 +4443,37 @@ int mmc_get_write_performance(struct burn_drive *d)
/* first command execution to learn number of descriptors and
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) {
/* Some drives announce only 1 descriptor if asked for 0.
So ask twice for non-0 descriptors.
*/
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);
}
/*
fprintf(stderr,"LIBBURN_DEBUG: ACh alloc_len = %d , ret = %d\n",
alloc_len, ret);
*/
if (max_descr > 0 && ret > 0)
if (max_descr > 0 && ret > 0) {
/* final execution with announced length */
max_descr = (alloc_len - 8) / 16;
ret = mmc_get_write_performance_al(d, &alloc_len, &max_descr,
1);
ret = mmc_get_performance_al(d, descr_type,
&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;
}
/* ts A61229 : outsourced from spc_select_write_params() */
/* Note: Page data is not zeroed here to allow preset defaults. Thus
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_min_percent = Libburn_wait_for_buffer_min_perC;
d->wfb_max_percent = Libburn_wait_for_buffer_max_perC;
d->sent_default_page_05 = 0;
return 1;
}

5
libburn/mmc.h

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* 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.
*/
@ -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,
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
/* B21108 ts */

38
libburn/spc.c

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* 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.
*/
@ -416,6 +416,7 @@ static int spc_sense_caps_al(struct burn_drive *d, int *alloc_len, int flag)
struct command *c = NULL;
struct burn_speed_descriptor *sd;
char *msg = NULL;
struct burn_feature_descr *feature_descr;
/* ts A61225 : 1 = report about post-MMC-1 speed descriptors */
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);
try_mmc_get_performance:;
if (m->cdrw_write || page_length >= 32) {
/* ts A90823:
One has to avoid U3 enhanced memory sticks here. On my
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 = mmc_get_write_performance(d);
if (ret > 0 && speed_debug)
fprintf(stderr,
"LIBBURN_DEBUG: ACh min_write_speed = %d , max_write_speed = %d\n",
m->min_write_speed, m->max_write_speed);
/* ts B40107 : Feature 0x107 announces availability of GET PERFORMANCE
Its WSPD bit announces Type 3.
Try this even if the feature is not current.
*/
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);
if (ret > 0 && speed_debug)
fprintf(stderr,
"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;
ex:
BURN_FREE_MEM(msg);

Loading…
Cancel
Save