Enhanced DVD-RW formatting

This commit is contained in:
Thomas Schmitt 2007-01-09 21:06:55 +00:00
parent 5fc55ec164
commit e6cfff69eb
6 changed files with 204 additions and 32 deletions

View File

@ -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;
} }

View File

@ -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);

View File

@ -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

View File

@ -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) {

View File

@ -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;

View File

@ -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 */;
/* >>> */; /* >>> */;