Prepared support for DVD-RW in mode Restricted Overwrite

This commit is contained in:
Thomas Schmitt 2006-12-30 00:15:07 +00:00
parent 6e9c399930
commit c05d6550cb
7 changed files with 236 additions and 17 deletions

View File

@ -3781,6 +3781,9 @@ int Cdrskin_atip(struct CdrskiN *skin, int flag)
} }
if(strstr(profile_name,"DVD")==profile_name) { if(strstr(profile_name,"DVD")==profile_name) {
printf("book type: %s (emulated booktype)\n", profile_name); printf("book type: %s (emulated booktype)\n", profile_name);
if(profile_number==0x13)
printf(
"cdrskin: for sdvdbackup: \"(growisofs mode Restricted Overwrite)\"\n");
} else { } else {
printf("ATIP info from disk:\n"); printf("ATIP info from disk:\n");
if(burn_disc_erasable(drive)) { if(burn_disc_erasable(drive)) {
@ -4293,13 +4296,14 @@ int Cdrskin_activate_write_mode(struct CdrskiN *skin, enum burn_disc_status s,
int flag) int flag)
{ {
int ok, was_still_default= 0, block_type_demand,track_type,sector_size, i; int ok, was_still_default= 0, block_type_demand,track_type,sector_size, i;
int profile_number= -1;
struct burn_drive_info *drive_info = NULL; struct burn_drive_info *drive_info = NULL;
char profile_name[80]; char profile_name[80];
profile_name[0]= 0; profile_name[0]= 0;
#ifdef Cdrskin_libburn_has_get_profilE #ifdef Cdrskin_libburn_has_get_profilE
if(skin->grabbed_drive) if(skin->grabbed_drive)
burn_disc_get_profile(skin->grabbed_drive,&i,profile_name); burn_disc_get_profile(skin->grabbed_drive,&profile_number,profile_name);
#endif #endif
if(strcmp(skin->preskin->write_mode_name,"DEFAULT")==0) { if(strcmp(skin->preskin->write_mode_name,"DEFAULT")==0) {
@ -4308,7 +4312,8 @@ int Cdrskin_activate_write_mode(struct CdrskiN *skin, enum burn_disc_status s,
if(s == BURN_DISC_APPENDABLE) { if(s == BURN_DISC_APPENDABLE) {
strcpy(skin->preskin->write_mode_name,"TAO"); strcpy(skin->preskin->write_mode_name,"TAO");
was_still_default= 2; /*<<< prevents trying of SAO if drive dislikes TAO*/ was_still_default= 2; /*<<< prevents trying of SAO if drive dislikes TAO*/
} else if(strstr(profile_name,"DVD+RW")==profile_name) { } else if(strstr(profile_name,"DVD+RW")==profile_name ||
profile_number == 0x13) { /* DVD-RW Restricted Overwrite */
strcpy(skin->preskin->write_mode_name,"TAO"); strcpy(skin->preskin->write_mode_name,"TAO");
} else { } else {
strcpy(skin->preskin->write_mode_name,"SAO"); strcpy(skin->preskin->write_mode_name,"SAO");

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2006.12.29.143734" #define Cdrskin_timestamP "2006.12.30.001343"

View File

@ -336,7 +336,7 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x0002011c (FATAL,HIGH) = Attempt to read track info from busy drive 0x0002011c (FATAL,HIGH) = Attempt to read track info from busy drive
0x0002011d (FATAL,HIGH) = SCSI error on write 0x0002011d (FATAL,HIGH) = SCSI error on write
0x0002011e (SORRY,HIGH) = Unsuitable media detected 0x0002011e (SORRY,HIGH) = Unsuitable media detected
0x0002011f (SORRY,HIGH) = Burning of DVD+RW is restricted to a single track 0x0002011f (SORRY,HIGH) = Burning is restricted to a single track
0x00020120 (NOTE,HIGH) = FORMAT UNIT ignored 0x00020120 (NOTE,HIGH) = FORMAT UNIT ignored
0x00020121 (FATAL,HIGH) = Write preparation setup failed 0x00020121 (FATAL,HIGH) = Write preparation setup failed
0x00020122 (FATAL,HIGH) = SCSI error on format_unit 0x00020122 (FATAL,HIGH) = SCSI error on format_unit

View File

@ -37,6 +37,11 @@ extern struct libdax_msgs *libdax_messenger;
/* ts A61219 : Based on knowlege from dvd+rw-tools-7.0 and mmc5r03c.pdf */ /* ts A61219 : Based on knowlege from dvd+rw-tools-7.0 and mmc5r03c.pdf */
#define Libburn_support_dvd_plus_rW 1 #define Libburn_support_dvd_plus_rW 1
/* ts A61229 */
/*
*/
#define Libburn_support_dvd_minusrw_overW 1
/* Progress report (with Libburn_support_dvd_plus_rW defined): /* Progress report (with Libburn_support_dvd_plus_rW defined):
ts A61219 : It seems to work with a used (i.e. thoroughly formatted) DVD+RW. ts A61219 : It seems to work with a used (i.e. thoroughly formatted) DVD+RW.
Error messages of class DEBUG appear because of inability to Error messages of class DEBUG appear because of inability to
@ -152,7 +157,8 @@ int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa)
memcpy(c.opcode, MMC_TRACK_INFO, sizeof(MMC_TRACK_INFO)); memcpy(c.opcode, MMC_TRACK_INFO, sizeof(MMC_TRACK_INFO));
c.opcode[1] = 1; c.opcode[1] = 1;
if(trackno<=0) { if(trackno<=0) {
if (d->current_profile == 0x1a) /* DVD+RW */ if (d->current_profile == 0x1a || d->current_profile == 0x13)
/* DVD+RW or DVD-RW restricted overwrite*/
c.opcode[5] = 1; c.opcode[5] = 1;
else /* mmc5r03c.pdf: valid only for CD, DVD+R, DVD+R DL */ else /* mmc5r03c.pdf: valid only for CD, DVD+R, DVD+R DL */
c.opcode[5] = 0xFF; c.opcode[5] = 0xFF;
@ -593,9 +599,10 @@ void mmc_read_disc_info(struct burn_drive *d)
*/ */
d->bg_format_status = data[7] & 3; d->bg_format_status = data[7] & 3;
/* <<< ts A61219 : preliminarily declare all DVD+RW blank, /* ts A61219 : preliminarily declare all DVD+RW blank,
(which is not the same as bg_format_status==0 "blank") */ (which is not the same as bg_format_status==0 "blank") */
if (d->current_profile == 0x1a) /* ts A61229 : same for DVD-RW Restricted overwrite */
if (d->current_profile == 0x1a || d->current_profile == 0x13)
d->status = BURN_DISC_BLANK; d->status = BURN_DISC_BLANK;
} }
@ -1079,6 +1086,10 @@ void mmc_get_configuration(struct burn_drive *d)
if (cp == 0x1a) if (cp == 0x1a)
d->current_is_supported_profile = 1; d->current_is_supported_profile = 1;
#endif #endif
#ifdef Libburn_support_dvd_minusrw_overW
if (cp == 0x13)
d->current_is_supported_profile = 1;
#endif
} }
@ -1137,7 +1148,8 @@ int mmc_read_buffer_capacity(struct burn_drive *d)
} }
/* ts A61219 : learned much from dvd+rw-tools-7.0: plus_rw_format() */ /* ts A61219 : learned much from dvd+rw-tools-7.0: plus_rw_format()
and mmc5r03c.pdf, 6.5 FORMAT UNIT */
int mmc_format_unit(struct burn_drive *d) int mmc_format_unit(struct burn_drive *d)
{ {
struct buffer buf; struct buffer buf;
@ -1156,10 +1168,10 @@ int mmc_format_unit(struct burn_drive *d)
memset(c.page->data, 0, c.page->bytes); memset(c.page->data, 0, c.page->bytes);
descr[0] = 0; descr[0] = 0;
c.page->data[1] = 0x02; /* Immed */
c.page->data[3] = 8; /* Format descriptor length */
if (d->current_profile == 0x1a) { /* DVD+RW */ if (d->current_profile == 0x1a) { /* DVD+RW */
c.page->data[1] = 0x02; /* Immed */ /* mmc5r03c.pdf , 6.5.4.2.14, DVD+RW Basic Format */
c.page->data[3] = 8; /* Format descriptor length */
/* mmc5r03c.pdf , 6.5.4.2.14 */
c.page->data[8] = 0x26 << 2; /* Format type */ c.page->data[8] = 0x26 << 2; /* Format type */
memset(c.page->data + 4, 0xff, 4); /* maximum blocksize */ memset(c.page->data + 4, 0xff, 4); /* maximum blocksize */
if (d->bg_format_status == 1) /* is partly formatted */ if (d->bg_format_status == 1) /* is partly formatted */
@ -1173,6 +1185,11 @@ int mmc_format_unit(struct burn_drive *d)
} }
sprintf(descr, "DVD+RW, BGFS %d", sprintf(descr, "DVD+RW, BGFS %d",
d->bg_format_status); d->bg_format_status);
} else if (d->current_profile == 0x13) {/*DVD-RW restricted overwrite*/
/* 6.5.4.2.8 , DVD-RW Quick Grow Last Border */
c.page->data[8] = 0x13 << 2; /* Format type */
c.page->data[11] = 16; /* Restart bit */
sprintf(descr, "DVD-RW, quick grow");
} else { } else {
/* >>> other formattable types to come */ /* >>> other formattable types to come */
@ -1359,3 +1376,55 @@ int mmc_setup_drive(struct burn_drive *d)
return 1; return 1;
} }
/* 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);
is the eventual duty of the caller.
*/
int mmc_compose_mode_page_5(struct burn_drive *d,
const struct burn_write_opts *o,
unsigned char *pd)
{
pd[0] = 5;
pd[1] = d->mdata->write_page_length;
/* ts A61229 */
if (d->current_profile == 0x13) { /* DVD-RW restricted overwrite */
/* learned from transport.hxx : page05_setup()
and mmc3r10g.pdf table 347 */
/* BUFE (burnproof), no LS_V (i.e. default Link Size, i hope),
no simulate, write type 0 = packet */
pd[2] = (1 << 6);
/* no multi, fixed packet, track mode 5 */
pd[3] = (1 << 5) | 5;
/* Data Block Type */
pd[4] = 8;
/* Link size dummy */
pd[5] = 0;
} else {
/* Traditional setup for CD */
pd[2] = ((!!o->underrun_proof) << 6)
| ((!!o->simulate) << 4)
| (o->write_type & 0x0f);
/* ts A61106 : MMC-1 table 110 : multi==0 or multi==3 */
pd[3] = ((3 * !!o->multi) << 6) | (o->control & 0x0f);
pd[4] = spc_block_type(o->block_type);
/* ts A61104 */
if(!(o->control&4)) /* audio (MMC-1 table 61) */
if(o->write_type == BURN_WRITE_TAO)
pd[4] = 0; /* Data Block Type: Raw Data */
pd[14] = 0; /* audio pause length MSB */
pd[15] = 150; /* audio pause length LSB */
/*XXX need session format! */
/* ts A61229 : but session format (pd[8]) = 0 seems ok */
}
return 1;
}

View File

@ -54,4 +54,15 @@ int mmc_setup_drive(struct burn_drive *d);
/* ts A61225 : obtain write speed descriptors via ACh GET PERFORMANCE */ /* ts A61225 : obtain write speed descriptors via ACh GET PERFORMANCE */
int mmc_get_write_performance(struct burn_drive *d); int mmc_get_write_performance(struct burn_drive *d);
/* 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);
is the eventual duty of the caller.
*/
int mmc_compose_mode_page_5(struct burn_drive *d,
const struct burn_write_opts *o,
unsigned char *pd);
#endif /*__MMC*/ #endif /*__MMC*/

View File

@ -345,6 +345,11 @@ void spc_sense_write_params(struct burn_drive *d)
mmc_read_disc_info(d); mmc_read_disc_info(d);
} }
/* ts A61229 */
#define Libburn_mmc_compose_mode_page_5 1
/* remark ts A61104 : /* remark ts A61104 :
Although command MODE SELECT is SPC, the content of the Although command MODE SELECT is SPC, the content of the
Write Parameters Mode Page (05h) is MMC (Table 108 in MMC-1). Write Parameters Mode Page (05h) is MMC (Table 108 in MMC-1).
@ -355,7 +360,9 @@ void spc_select_write_params(struct burn_drive *d,
{ {
struct buffer buf; struct buffer buf;
struct command c; struct command c;
#ifndef Libburn_mmc_compose_mode_page_5
int bufe, sim; int bufe, sim;
#endif
/* ts A61007 : All current callers are safe. */ /* ts A61007 : All current callers are safe. */
/* a ssert(o->drive == d); */ /* a ssert(o->drive == d); */
@ -380,11 +387,21 @@ void spc_select_write_params(struct burn_drive *d,
memset(c.page->data, 0, 8 + 2 + d->mdata->write_page_length); memset(c.page->data, 0, 8 + 2 + d->mdata->write_page_length);
c.page->bytes = 8 + 2 + d->mdata->write_page_length; c.page->bytes = 8 + 2 + d->mdata->write_page_length;
c.page->data[8] = 5;
c.page->data[9] = d->mdata->write_page_length;
burn_print(12, "using write page length %d (valid %d)\n", burn_print(12, "using write page length %d (valid %d)\n",
d->mdata->write_page_length, d->mdata->write_page_valid); d->mdata->write_page_length, d->mdata->write_page_valid);
#ifdef Libburn_mmc_compose_mode_page_5
/* ts A61229 */
if (mmc_compose_mode_page_5(d, o, c.page->data + 8) <= 0)
return;
#else
c.page->data[8] = 5;
c.page->data[9] = d->mdata->write_page_length;
bufe = o->underrun_proof; bufe = o->underrun_proof;
sim = o->simulate; sim = o->simulate;
c.page->data[10] = (bufe << 6) c.page->data[10] = (bufe << 6)
@ -403,6 +420,9 @@ void spc_select_write_params(struct burn_drive *d,
c.page->data[22] = 0; c.page->data[22] = 0;
c.page->data[23] = 150; /* audio pause length */ c.page->data[23] = 150; /* audio pause length */
#endif /* ! Libburn_mmc_compose_mode_page_5 */
/*XXX need session format! */ /*XXX need session format! */
c.dir = TO_DRIVE; c.dir = TO_DRIVE;
d->issue_command(d, &c); d->issue_command(d, &c);
@ -500,6 +520,8 @@ void spc_probe_write_modes(struct burn_drive *d)
} }
} }
/* ( ts A61229 : shouldn't this go to mmc.c too ?) */
/** @return -1 = error */ /** @return -1 = error */
int spc_block_type(enum burn_block_types b) int spc_block_type(enum burn_block_types b)
{ {

View File

@ -887,6 +887,20 @@ int burn_disc_close_session_dvd_plus_rw(struct burn_write_opts *o,
} }
/* ts A61228 */
int burn_disc_close_session_dvd_minus_rw(struct burn_write_opts *o,
struct burn_session *s)
{
struct burn_drive *d = o->drive;
d->busy = BURN_DRIVE_CLOSING_SESSION;
if (d->current_profile == 0x13)
d->close_track_session(d, 1, 0); /* CLOSE SESSION */
d->busy = BURN_DRIVE_WRITING;
return 1;
}
/* ts A61218 */ /* ts A61218 */
int burn_dvd_write_session(struct burn_write_opts *o, int burn_dvd_write_session(struct burn_write_opts *o,
struct burn_session *s) struct burn_session *s)
@ -903,6 +917,11 @@ int burn_dvd_write_session(struct burn_write_opts *o,
ret = burn_disc_close_session_dvd_plus_rw(o, s); ret = burn_disc_close_session_dvd_plus_rw(o, s);
if (ret <= 0) if (ret <= 0)
return 0; return 0;
} else if (d->current_profile == 0x13) {
/* DVD-RW restricted overwrite */
ret = burn_disc_close_session_dvd_minus_rw(o, s);
if (ret <= 0)
return 0;
} }
return 1; return 1;
} }
@ -943,6 +962,74 @@ int burn_disc_setup_dvd_plus_rw(struct burn_write_opts *o,
} }
/* ts A61228 : learned much from dvd+rw-tools-7.0/growisofs_mmc.cpp */
int burn_disc_setup_dvd_minus_rw(struct burn_write_opts *o,
struct burn_disc *disc)
{
struct burn_drive *d = o->drive;
char msg[160];
int ret;
if (d->current_profile == 0x13) { /* DVD-RW restricted overwrite */
#ifdef NIX
/* >>> compose mode page 5 -> spc_select_write_params() */
/* learned from transport.hxx : page05_setup()
and mmc3r10g.pdf table 347 */
o->underrun_proof = 1;
o->write_type = 0; /* packet */
o->multi = 0;
o->control = (1<<5) | 5; /* Fixed packet, Track mode 5 */
>>> make controllable in spc_select_write_params() :
>>> c.page->data[10] &= ~(1<<5); /* LS_V = 0 */
>>> c.page->data[12] = 8; /* Data Block Type */
>>> .page->data[13] = 0; /* Link size */
#endif /* NIX */
/* ??? urm ... mmc5r03c.pdf 7.5.2 :
"For DVD-RW media ... If a medium is in Restricted overwrite
mode, this mode page shall not be used."
But growisofs composes a page 5 and sends it.
*/
d->send_write_parameters(d, o);
d->busy = BURN_DRIVE_FORMATTING;
ret = d->format_unit(d); /* "quick grow" */
if (ret <= 0)
return 0;
d->busy = BURN_DRIVE_WRITING;
} else {
sprintf(msg, "Unsuitable media detected. Profile %4.4Xh %s",
d->current_profile, d->current_profile_text);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002011e,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0,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 */;
/* >>> */;
return 1;
}
/* ts A61218 */ /* ts A61218 */
int burn_dvd_write_sync(struct burn_write_opts *o, int burn_dvd_write_sync(struct burn_write_opts *o,
struct burn_disc *disc) struct burn_disc *disc)
@ -966,12 +1053,12 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
goto early_failure; goto early_failure;
} }
if (strcmp(d->current_profile_text,"DVD+RW")==0) { if (d->current_profile == 0x1a || d->current_profile == 0x13) {
/* DVD+RW or DVD-RW Restricted Overwrite */
if (disc->sessions!=1 || disc->session[0]->tracks>1 if (disc->sessions!=1 || disc->session[0]->tracks>1
|| o->multi ) { || o->multi ) {
sprintf(msg, sprintf(msg,
"Burning of DVD+RW is restricted to a single track and session" "Burning is restricted to a single track and no multi-session"
); );
libdax_msgs_submit(libdax_messenger, d->global_index, libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002011f, 0x0002011f,
@ -979,6 +1066,8 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
msg, 0,0); msg, 0,0);
goto early_failure; goto early_failure;
} }
}
if (d->current_profile == 0x1a) { /* DVD+RW */
if (o->start_byte >= 0 && (o->start_byte % 2048)) { if (o->start_byte >= 0 && (o->start_byte % 2048)) {
sprintf(msg, sprintf(msg,
"Write start address not properly aligned to 2048"); "Write start address not properly aligned to 2048");
@ -988,7 +1077,6 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
msg, 0,0); msg, 0,0);
goto early_failure; goto early_failure;
} }
ret = burn_disc_setup_dvd_plus_rw(o, disc); ret = burn_disc_setup_dvd_plus_rw(o, disc);
if (ret <= 0) { if (ret <= 0) {
sprintf(msg, sprintf(msg,
@ -1001,6 +1089,30 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
} }
o->obs_pad = 0; /* no filling-up of track's last 32k buffer */ o->obs_pad = 0; /* no filling-up of track's last 32k buffer */
} else if (d->current_profile == 0x13) { /* DVD-RW Rest. Overwrite */
if (o->start_byte >= 0 && (o->start_byte % 32768)) {
sprintf(msg,
"Write start address not properly aligned to 32K");
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020125,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0,0);
goto early_failure;
}
ret = burn_disc_setup_dvd_minus_rw(o, disc);
if (ret <= 0) {
sprintf(msg,
"Write preparation setup failed for DVD-RW");
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020121,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
msg, 0,0);
goto early_failure;
}
/* ??? is this necessary ? */
o->obs_pad = 1; /* fill-up track's last 32k buffer */
} else { } else {
sprintf(msg, "Unsuitable media detected. Profile %4.4Xh %s", sprintf(msg, "Unsuitable media detected. Profile %4.4Xh %s",
d->current_profile, d->current_profile_text); d->current_profile, d->current_profile_text);