Enhanced DVD-RW formatting
This commit is contained in:
parent
5fc55ec164
commit
e6cfff69eb
@ -475,6 +475,7 @@ void burn_disc_erase_sync(struct burn_drive *d, int fast)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
@param flag: bit0 = fill formatted size with zeros
|
@param flag: bit0 = fill formatted size with zeros
|
||||||
|
bit1, bit2 are for d->format_unit()
|
||||||
*/
|
*/
|
||||||
void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag)
|
void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag)
|
||||||
{
|
{
|
||||||
@ -489,12 +490,12 @@ void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag)
|
|||||||
#ifdef Libburn_format_ignore_sizE
|
#ifdef Libburn_format_ignore_sizE
|
||||||
size = 0;
|
size = 0;
|
||||||
#else
|
#else
|
||||||
stages = 1 + (flag & 1);
|
stages = 1 + ((flag & 1) && size > 1024 * 1024);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
d->cancel = 0;
|
d->cancel = 0;
|
||||||
d->busy = BURN_DRIVE_FORMATTING;
|
d->busy = BURN_DRIVE_FORMATTING;
|
||||||
ret = d->format_unit(d, size, 0);
|
ret = d->format_unit(d, size, flag & 6);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
d->cancel = 1;
|
d->cancel = 1;
|
||||||
/* reset the progress */
|
/* reset the progress */
|
||||||
@ -525,11 +526,11 @@ void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag)
|
|||||||
burn_drive_inquire_media(d);
|
burn_drive_inquire_media(d);
|
||||||
if (flag & 1) {
|
if (flag & 1) {
|
||||||
/* write size in zeros */;
|
/* write size in zeros */;
|
||||||
pbase = 0x8000;
|
pbase = 0x8000 + 0x7fff * (stages == 1);
|
||||||
pfill = 0xffff - pbase;
|
pfill = 0xffff - pbase;
|
||||||
buf_secs = 16; /* Must not be more than 16 */
|
buf_secs = 16; /* Must not be more than 16 */
|
||||||
num_bufs = size / buf_secs / 2048;
|
num_bufs = size / buf_secs / 2048;
|
||||||
if (num_bufs <= 0 || num_bufs > 0x7fffffff) {
|
if (num_bufs > 0x7fffffff) {
|
||||||
d->cancel = 1;
|
d->cancel = 1;
|
||||||
goto ex;
|
goto ex;
|
||||||
}
|
}
|
||||||
|
@ -853,6 +853,8 @@ void burn_disc_erase(struct burn_drive *drive, int fast);
|
|||||||
@param flag Bitfield for control purposes:
|
@param flag Bitfield for control purposes:
|
||||||
bit0= after formatting, write the given number of zero-bytes
|
bit0= after formatting, write the given number of zero-bytes
|
||||||
to the media and eventually perform preliminary closing.
|
to the media and eventually perform preliminary closing.
|
||||||
|
bit1= insist in size 0 even if there is a better default known
|
||||||
|
bit2= format to maximum available size
|
||||||
*/
|
*/
|
||||||
void burn_disc_format(struct burn_drive *drive, off_t size, int flag);
|
void burn_disc_format(struct burn_drive *drive, off_t size, int flag);
|
||||||
|
|
||||||
|
@ -347,6 +347,9 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
|
|||||||
0x00020127 (NOTE,HIGH) = Write start address is ...
|
0x00020127 (NOTE,HIGH) = Write start address is ...
|
||||||
0x00020128 (FATAL,HIGH) = Unsupported inquiry_type with mmc_get_performance
|
0x00020128 (FATAL,HIGH) = Unsupported inquiry_type with mmc_get_performance
|
||||||
0x00020129 (SORRY,HIGH) = Will not format media type
|
0x00020129 (SORRY,HIGH) = Will not format media type
|
||||||
|
0x00020130 (SORRY,HIGH) = Drive and media state unsuitable for blanking
|
||||||
|
0x00020131 (SORRY,HIGH) = No suitable formatting type offered by drive
|
||||||
|
|
||||||
|
|
||||||
libdax_audioxtr:
|
libdax_audioxtr:
|
||||||
0x00020200 (SORRY,HIGH) = Cannot open audio source file
|
0x00020200 (SORRY,HIGH) = Cannot open audio source file
|
||||||
|
185
libburn/mmc.c
185
libburn/mmc.c
@ -65,7 +65,6 @@ extern struct libdax_msgs *libdax_messenger;
|
|||||||
|
|
||||||
Todo:
|
Todo:
|
||||||
Determine first free lba for appending data.
|
Determine first free lba for appending data.
|
||||||
Determine start lba of most recent mkisofs session.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -110,6 +109,11 @@ static unsigned char MMC_SET_STREAMING[] =
|
|||||||
static unsigned char MMC_GET_PERFORMANCE[] =
|
static unsigned char MMC_GET_PERFORMANCE[] =
|
||||||
{ 0xAC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
{ 0xAC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
|
||||||
|
/* ts A70108 : To obtain info about drive and media formatting opportunities */
|
||||||
|
static unsigned char MMC_READ_FORMAT_CAPACITIES[] =
|
||||||
|
{ 0x23, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
|
||||||
|
|
||||||
static int mmc_function_spy_do_tell = 0;
|
static int mmc_function_spy_do_tell = 0;
|
||||||
|
|
||||||
int mmc_function_spy(char * text)
|
int mmc_function_spy(char * text)
|
||||||
@ -1104,6 +1108,104 @@ void mmc_get_configuration(struct burn_drive *d)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A70108 */
|
||||||
|
/* mmc5r03c.pdf 6.24 */
|
||||||
|
int mmc_read_format_capacities(struct burn_drive *d, int top_wanted)
|
||||||
|
{
|
||||||
|
struct buffer buf;
|
||||||
|
int len, type, score, num_descr, max_score = -1, i;
|
||||||
|
off_t size;
|
||||||
|
struct command c;
|
||||||
|
unsigned char *dpt;
|
||||||
|
char msg[160];
|
||||||
|
|
||||||
|
mmc_function_spy("mmc_read_format_capacities");
|
||||||
|
|
||||||
|
d->format_descr_type = 3;
|
||||||
|
d->format_curr_max_size = 0;
|
||||||
|
d->best_format_type = -1;
|
||||||
|
d->best_format_size = 0;
|
||||||
|
|
||||||
|
memcpy(c.opcode, MMC_READ_FORMAT_CAPACITIES,
|
||||||
|
sizeof(MMC_GET_CONFIGURATION));
|
||||||
|
c.retry = 1;
|
||||||
|
c.oplen = sizeof(MMC_READ_FORMAT_CAPACITIES);
|
||||||
|
c.opcode[7]= 0x02;
|
||||||
|
c.opcode[8]= 0x00; /* accept 512 bytes (not more than 260 possible) */
|
||||||
|
c.page = &buf;
|
||||||
|
c.page->sectors = 0;
|
||||||
|
c.page->bytes = 0;
|
||||||
|
c.dir = FROM_DRIVE;
|
||||||
|
|
||||||
|
d->issue_command(d, &c);
|
||||||
|
if (c.error)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
len = c.page->data[3];
|
||||||
|
if (len<8)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
dpt = c.page->data + 4;
|
||||||
|
/* decode 6.24.3.2 Current/Maximum Capacity Descriptor */
|
||||||
|
d->format_descr_type = dpt[4] & 3;
|
||||||
|
d->format_curr_max_size = (((off_t) dpt[0]) << 24)
|
||||||
|
+ (dpt[1] << 16) + (dpt[2] << 8) + dpt[3];
|
||||||
|
|
||||||
|
sprintf(msg,
|
||||||
|
"Current/Maximum Capacity Descriptor : type = %d : %.f",
|
||||||
|
d->format_descr_type, (double) d->format_curr_max_size);
|
||||||
|
libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002,
|
||||||
|
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
|
||||||
|
msg, 0, 0);
|
||||||
|
|
||||||
|
d->format_curr_max_size *= (off_t) 2048;
|
||||||
|
|
||||||
|
/* 6.24.3.3 Formattable Capacity Descriptors */
|
||||||
|
num_descr = (len - 8) / 8;
|
||||||
|
for (i = 0; i < num_descr; i++) {
|
||||||
|
dpt = c.page->data + 12 + 8 * i;
|
||||||
|
size = (((off_t) dpt[0]) << 24)
|
||||||
|
+ (dpt[1] << 16) + (dpt[2] << 8) + dpt[3];
|
||||||
|
size *= (off_t) 2048;
|
||||||
|
type = dpt[4] >> 2;
|
||||||
|
|
||||||
|
sprintf(msg, "Capacity Descriptor %2.2Xh %.fs = %.1f MB",type,
|
||||||
|
(double) size / 2048 , (double) size / 1024 / 1024);
|
||||||
|
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||||
|
0x00000002,
|
||||||
|
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
|
||||||
|
msg, 0, 0);
|
||||||
|
|
||||||
|
if (type == 0x10) { /* full format */
|
||||||
|
score = 1;
|
||||||
|
} else if(type == 0x13) {
|
||||||
|
score = 100;
|
||||||
|
} else if(type == 0x15) {
|
||||||
|
score = 50;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(type == top_wanted)
|
||||||
|
score+= 1000000000;
|
||||||
|
if (score > max_score) {
|
||||||
|
d->best_format_type = type;
|
||||||
|
d->best_format_size = size;
|
||||||
|
max_score = score;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(msg,
|
||||||
|
"best_format_type = %2.2Xh , best_format_size = %.f",
|
||||||
|
d->best_format_type, (double) d->best_format_size);
|
||||||
|
libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002,
|
||||||
|
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
|
||||||
|
msg, 0, 0);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void mmc_sync_cache(struct burn_drive *d)
|
void mmc_sync_cache(struct burn_drive *d)
|
||||||
{
|
{
|
||||||
struct command c;
|
struct command c;
|
||||||
@ -1168,14 +1270,16 @@ int mmc_read_buffer_capacity(struct burn_drive *d)
|
|||||||
>>> all-in-one automat.
|
>>> all-in-one automat.
|
||||||
|
|
||||||
@param size The size (in bytes) to be sent with the FORMAT comand
|
@param size The size (in bytes) to be sent with the FORMAT comand
|
||||||
@param flag unused yet, submit 0
|
@param flag bit1= insist in size 0 even if there is a better default known
|
||||||
|
bit2= format to maximum available size
|
||||||
|
bit3= expand format up to at least size
|
||||||
*/
|
*/
|
||||||
int mmc_format_unit(struct burn_drive *d, off_t size, int flag)
|
int mmc_format_unit(struct burn_drive *d, off_t size, int flag)
|
||||||
{
|
{
|
||||||
struct buffer buf;
|
struct buffer buf;
|
||||||
struct command c;
|
struct command c;
|
||||||
int ret, tolerate_failure = 0, return_immediately = 0, i;
|
int ret, tolerate_failure = 0, return_immediately = 0, i, format_type;
|
||||||
off_t num_of_blocks = 0;
|
off_t num_of_blocks = 0, diff;
|
||||||
char msg[160],descr[80];
|
char msg[160],descr[80];
|
||||||
|
|
||||||
mmc_function_spy("mmc_format_unit");
|
mmc_function_spy("mmc_format_unit");
|
||||||
@ -1198,10 +1302,11 @@ int mmc_format_unit(struct burn_drive *d, off_t size, int flag)
|
|||||||
/* >>> use case: background formatting during write */
|
/* >>> use case: background formatting during write */
|
||||||
|
|
||||||
/* mmc5r03c.pdf , 6.5.4.2.14, DVD+RW Basic Format */
|
/* mmc5r03c.pdf , 6.5.4.2.14, DVD+RW Basic Format */
|
||||||
c.page->data[8] = 0x26 << 2; /* Format type */
|
format_type = 0x26;
|
||||||
|
|
||||||
/* Note: parameter "size" is ignored here */
|
if ((size <= 0 && !(flag & 2)) || (flag & (4 | 8)))
|
||||||
memset(c.page->data + 4, 0xff, 4); /* maximum blocksize */
|
/* maximum capacity */
|
||||||
|
memset(c.page->data + 4, 0xff, 4);
|
||||||
|
|
||||||
if (d->bg_format_status == 1) /* is partly formatted */
|
if (d->bg_format_status == 1) /* is partly formatted */
|
||||||
c.page->data[11] = 1; /* Restart bit */
|
c.page->data[11] = 1; /* Restart bit */
|
||||||
@ -1217,22 +1322,67 @@ int mmc_format_unit(struct burn_drive *d, off_t size, int flag)
|
|||||||
} else if (d->current_profile == 0x13) {/*DVD-RW restricted overwrite*/
|
} else if (d->current_profile == 0x13) {/*DVD-RW restricted overwrite*/
|
||||||
/* >>> use case: quick grow formatting during write */
|
/* >>> use case: quick grow formatting during write */
|
||||||
|
|
||||||
/* >>> check wether READ FORMAT CAPACITIES does report
|
ret = mmc_read_format_capacities(d, 0x13);
|
||||||
0x13 formatting. If not, skip this. It seems to work
|
if (ret > 0) {
|
||||||
without formatting on e.g. freshly formatted media. */
|
if (d->best_format_type == 0x13) {
|
||||||
|
if (d->best_format_size <= 0)
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
/* formatted or intermediate state ? */
|
||||||
|
if (d->format_descr_type == 2 ||
|
||||||
|
d->format_descr_type == 3)
|
||||||
|
return 1;
|
||||||
|
/* does trying make sense at all ? */
|
||||||
tolerate_failure = 1;
|
tolerate_failure = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (d->best_format_type == 0x13 && (flag & (4 | 8))) {
|
||||||
|
num_of_blocks = d->best_format_size / 2048;
|
||||||
|
if (flag & 8) {
|
||||||
|
/* num_of_blocks needed to reach size */
|
||||||
|
diff = (size - d->format_curr_max_size) /32768;
|
||||||
|
if ((size - d->format_curr_max_size) % 32768)
|
||||||
|
diff++;
|
||||||
|
diff *= 16;
|
||||||
|
if (diff < num_of_blocks)
|
||||||
|
num_of_blocks = diff;
|
||||||
|
}
|
||||||
|
if (num_of_blocks > 0)
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
c.page->data[4 + i] =
|
||||||
|
(num_of_blocks >> (24 - 8 * i)) & 0xff;
|
||||||
|
}
|
||||||
/* 6.5.4.2.8 , DVD-RW Quick Grow Last Border */
|
/* 6.5.4.2.8 , DVD-RW Quick Grow Last Border */
|
||||||
c.page->data[8] = 0x13 << 2; /* Format type */
|
format_type = 0x13;
|
||||||
c.page->data[11] = 16; /* block size * 2k */
|
c.page->data[11] = 16; /* block size * 2k */
|
||||||
sprintf(descr, "DVD-RW, quick grow");
|
sprintf(descr, "DVD-RW, quick grow");
|
||||||
|
|
||||||
} else if (d->current_profile == 0x14) {/*DVD-RW sequential recording*/
|
} else if (d->current_profile == 0x14) {/*DVD-RW sequential recording*/
|
||||||
/* >>> use case : transition from Sequential to Overwrite */
|
/* >>> use case : transition from Sequential to Overwrite */
|
||||||
|
|
||||||
/* 6.5.4.2.10 , DVD-RW Quick (-> Restricted Overwrite) */
|
/* To Restricted Overwrite */
|
||||||
|
/* 6.5.4.2.10 , 15h DVD-RW Quick */
|
||||||
/* c.page->data[4-7]==0 : 0 blocks */
|
/* c.page->data[4-7]==0 : 0 blocks */
|
||||||
c.page->data[8] = 0x15 << 2; /* Format type */
|
/* or 6.5.4.2.5 Format Type = 10h (Full Format) */
|
||||||
|
mmc_read_format_capacities(d, (flag & 4) ? 0x10 : 0x15);
|
||||||
|
if (d->best_format_type == 0x15 ||
|
||||||
|
d->best_format_type == 0x10) {
|
||||||
|
if ((flag & 4) || d->best_format_type == 0x10) {
|
||||||
|
num_of_blocks = d->best_format_size / 2048;
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
c.page->data[4 + i] =
|
||||||
|
(num_of_blocks >> (24 - 8 * i)) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||||
|
0x00020131,
|
||||||
|
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"No suitable formatting type offered by drive",
|
||||||
|
0, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
format_type = d->best_format_type;
|
||||||
c.page->data[11] = 16; /* block size * 2k */
|
c.page->data[11] = 16; /* block size * 2k */
|
||||||
sprintf(descr, "DVD-RW, quick");
|
sprintf(descr, "DVD-RW, quick");
|
||||||
return_immediately = 1; /* caller must do the waiting */
|
return_immediately = 1; /* caller must do the waiting */
|
||||||
@ -1249,6 +1399,13 @@ int mmc_format_unit(struct burn_drive *d, off_t size, int flag)
|
|||||||
msg, 0, 0);
|
msg, 0, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
c.page->data[8] = format_type << 2;
|
||||||
|
|
||||||
|
sprintf(msg, "Format type %2.2Xh , blocks = %d\n",
|
||||||
|
format_type, (int) num_of_blocks);
|
||||||
|
libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002,
|
||||||
|
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
|
||||||
|
msg, 0, 0);
|
||||||
|
|
||||||
d->issue_command(d, &c);
|
d->issue_command(d, &c);
|
||||||
if (c.error && !tolerate_failure) {
|
if (c.error && !tolerate_failure) {
|
||||||
|
@ -141,6 +141,11 @@ struct burn_drive
|
|||||||
/* ts A61218 from 46h GET CONFIGURATION */
|
/* ts A61218 from 46h GET CONFIGURATION */
|
||||||
int bg_format_status; /* 0=needs format start, 1=needs format restart*/
|
int bg_format_status; /* 0=needs format start, 1=needs format restart*/
|
||||||
|
|
||||||
|
/* ts A70108 from 23h READ FORMAT CAPACITY mmc5r03c.pdf 6.24 */
|
||||||
|
int format_descr_type; /* 1=unformatted, 2=formatted, 3=unclear */
|
||||||
|
off_t format_curr_max_size; /* meaning depends on format_descr_type */
|
||||||
|
int best_format_type;
|
||||||
|
off_t best_format_size;
|
||||||
|
|
||||||
volatile int released;
|
volatile int released;
|
||||||
|
|
||||||
|
@ -975,6 +975,19 @@ int burn_disc_setup_dvd_minus_rw(struct burn_write_opts *o,
|
|||||||
char msg[160];
|
char msg[160];
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
d->nwa = 0;
|
||||||
|
if (o->start_byte >= 0) {
|
||||||
|
d->nwa = o->start_byte / 32768; /* align to 32 kB */
|
||||||
|
|
||||||
|
sprintf(msg, "Write start address is %d * 32768", d->nwa);
|
||||||
|
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||||
|
0x00020127,
|
||||||
|
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
msg, 0,0);
|
||||||
|
|
||||||
|
d->nwa *= 16; /* convert to 2048 block units */
|
||||||
|
}
|
||||||
|
|
||||||
if (d->current_profile == 0x13) { /* DVD-RW restricted overwrite */
|
if (d->current_profile == 0x13) { /* DVD-RW restricted overwrite */
|
||||||
|
|
||||||
/* ??? mmc5r03c.pdf 7.5.2 :
|
/* ??? mmc5r03c.pdf 7.5.2 :
|
||||||
@ -995,7 +1008,9 @@ int burn_disc_setup_dvd_minus_rw(struct burn_write_opts *o,
|
|||||||
|
|
||||||
d->busy = BURN_DRIVE_FORMATTING;
|
d->busy = BURN_DRIVE_FORMATTING;
|
||||||
|
|
||||||
ret = d->format_unit(d, (off_t) 0, 0); /* "quick grow" */
|
/* "quick grow" to at least byte equivalent of d->nwa */
|
||||||
|
ret = d->format_unit(d, (off_t) d->nwa * (off_t) 2048,
|
||||||
|
(d->nwa > 0) << 3);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
d->busy = BURN_DRIVE_WRITING;
|
d->busy = BURN_DRIVE_WRITING;
|
||||||
@ -1010,17 +1025,6 @@ int burn_disc_setup_dvd_minus_rw(struct burn_write_opts *o,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->nwa = 0;
|
|
||||||
if (o->start_byte >= 0) {
|
|
||||||
d->nwa = o->start_byte / 32768;
|
|
||||||
|
|
||||||
sprintf(msg, "Write start address is %d * 32768", d->nwa);
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
|
||||||
0x00020127,
|
|
||||||
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
msg, 0,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* >>> perform OPC if needed */;
|
/* >>> perform OPC if needed */;
|
||||||
|
|
||||||
/* >>> */;
|
/* >>> */;
|
||||||
|
Loading…
Reference in New Issue
Block a user