From 97fe85876092237bb27030313bc848ef099356a1 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Mon, 1 Jan 2007 17:10:54 +0000 Subject: [PATCH] Prepared formatting of DVD-RW --- cdrskin/cdrskin_timestamp.h | 2 +- libburn/async.c | 50 +++++++++++++++++++++++++++++++++++++ libburn/drive.c | 38 +++++++++++++++++++++++++++- libburn/drive.h | 4 +++ libburn/libburn.h | 19 +++++++++++--- libburn/libdax_msgs.h | 1 + libburn/mmc.c | 41 ++++++++++++++++++++++-------- libburn/mmc.h | 4 +++ libburn/spc.c | 3 ++- libburn/transport.h | 2 +- libburn/write.c | 26 +++++-------------- 11 files changed, 152 insertions(+), 38 deletions(-) diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index 8ebb2d1..2a10d51 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2006.12.30.001343" +#define Cdrskin_timestamP "2007.01.01.170824" diff --git a/libburn/async.c b/libburn/async.c index e48d719..4aae06e 100644 --- a/libburn/async.c +++ b/libburn/async.c @@ -35,6 +35,13 @@ struct erase_opts int fast; }; +/* ts A61230 */ +struct format_opts +{ + struct burn_drive *drive; + int flag; +}; + struct write_opts { struct burn_drive *drive; @@ -42,6 +49,7 @@ struct write_opts struct burn_disc *disc; }; + struct w_list { struct burn_drive *drive; @@ -53,6 +61,7 @@ struct w_list { struct scan_opts scan; struct erase_opts erase; + struct format_opts format; struct write_opts write; } u; }; @@ -223,6 +232,47 @@ void burn_disc_erase(struct burn_drive *drive, int fast) add_worker(drive, (WorkerFunc) erase_worker_func, &o); } + +/* ts A61230 */ +static void *format_worker_func(struct w_list *w) +{ + burn_disc_format_sync(w->u.format.drive, w->u.format.flag); + remove_worker(pthread_self()); + return NULL; +} + + +/* ts A61230 */ +void burn_disc_format(struct burn_drive *drive, int flag) +{ + struct format_opts o; + char msg[160]; + + if ((SCAN_GOING()) || find_worker(drive)) { + libdax_msgs_submit(libdax_messenger, drive->global_index, + 0x00020102, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, + "A drive operation is still going on (want to format)", + 0, 0); + return; + } + + if (drive->current_profile != 0x14) { /* no DVD-RW */ + sprintf(msg,"Will not format media type %4.4Xh", + drive->current_profile); + libdax_msgs_submit(libdax_messenger, drive->global_index, + 0x00020129, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, + msg, 0, 0); + drive->cancel = 1; + return; + } + o.drive = drive; + o.flag = flag; + add_worker(drive, (WorkerFunc) format_worker_func, &o); +} + + static void *write_disc_worker_func(struct w_list *w) { burn_disc_write_sync(w->u.write.opts, w->u.write.disc); diff --git a/libburn/drive.c b/libburn/drive.c index 847ef15..700fba2 100644 --- a/libburn/drive.c +++ b/libburn/drive.c @@ -447,8 +447,10 @@ void burn_disc_erase_sync(struct burn_drive *d, int fast) /* ts A60825 : allow on parole to blank appendable CDs */ if ( ! (d->status == BURN_DISC_FULL || (d->status == BURN_DISC_APPENDABLE && - ! libburn_back_hack_42) ) ) + ! libburn_back_hack_42) ) ) { + d->cancel = 1; return; + } d->cancel = 0; d->busy = BURN_DRIVE_ERASING; d->erase(d, fast); @@ -475,6 +477,40 @@ void burn_disc_erase_sync(struct burn_drive *d, int fast) burn_drive_inquire_media(d); } + +void burn_disc_format_sync(struct burn_drive *d, int flag) +{ + int ret; + + d->cancel = 0; + d->busy = BURN_DRIVE_FORMATTING; + ret = d->format_unit(d, 0); + if (ret <= 0) + d->cancel = 1; + /* reset the progress */ + d->progress.session = 0; + d->progress.sessions = 1; + d->progress.track = 0; + d->progress.tracks = 1; + d->progress.index = 0; + d->progress.indices = 1; + d->progress.start_sector = 0; + d->progress.sectors = 0x10000; + d->progress.sector = 0; + + while (!d->test_unit_ready(d) && d->get_erase_progress(d) == 0) + sleep(1); + while ((d->progress.sector = d->get_erase_progress(d)) > 0 || + !d->test_unit_ready(d)) + sleep(1); + + d->progress.sector = 0x10000; + + /* ts A61125 : update media state records */ + burn_drive_mark_unready(d); + burn_drive_inquire_media(d); +} + enum burn_disc_status burn_disc_get_status(struct burn_drive *d) { /* ts A61007 */ diff --git a/libburn/drive.h b/libburn/drive.h index 794e813..b835633 100644 --- a/libburn/drive.h +++ b/libburn/drive.h @@ -91,4 +91,8 @@ int burn_speed_descriptor_destroy(struct burn_speed_descriptor **s, int flag); /* ts A61226 : free dynamically allocated sub data of struct scsi_mode_data */ int burn_mdata_free_subs(struct scsi_mode_data *m); + +/* ts A61230 */ +void burn_disc_format_sync(struct burn_drive *d, int flag); + #endif /* __DRIVE */ diff --git a/libburn/libburn.h b/libburn/libburn.h index a4cb985..b20a899 100644 --- a/libburn/libburn.h +++ b/libburn/libburn.h @@ -784,8 +784,8 @@ int burn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *o, /* ts A61202 */ /** Tells the MMC Profile identifier of the loaded media. The drive must be grabbed in order to get a non-zero result. - libburn currently writes only to profiles 0x09 "CD-R", 0x0a "CD-RW" or - 0x1a "DVD+RW". + libburn currently writes only to profiles 0x09 "CD-R", 0x0a "CD-RW", + 0x13 "DVD-RW restricted overwrite" or 0x1a "DVD+RW". @param d The drive where the media is inserted. @param pno Profile Number as of mmc5r03c.pdf, table 89 @param name Profile Name (e.g "CD-RW", unknown profiles have empty name) @@ -841,7 +841,18 @@ void burn_read_opts_free(struct burn_read_opts *opts); */ void burn_disc_erase(struct burn_drive *drive, int fast); -/* ts A61109 : this is defunct */ + +/* ts A70101 */ +/** Format media for use with libburn. This currently applies only to DVD-RW + in state "Sequential Recording" (profile 0014h) which get formatted to + state "Restricted Overwrite" (profile 0013h). + @param drive The drive with the disc to format. + @param flag Unused yet. Submit 0. +*/ +void burn_disc_format(struct burn_drive *drive, int flag); + + +/* ts A61109 : this was and is defunct */ /** Read a disc from the drive and write it to an fd pair. The drive must be grabbed successfully BEFORE calling this function. Always ensure that the drive reports a status of BURN_DISC_FULL before calling this function. @@ -1136,7 +1147,7 @@ void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi); /* ts A61222 */ /** Sets a start address for writing to media and write modes which allow to - choose this address at all (DVD+RW only for now). The address is given in + choose this address at all (DVD+-RW only for now). The address is given in bytes. If it is not -1 then a write run will fail if choice of start address is not supported or if the block alignment of the address is not suitable for media and write mode. (Alignment to 32 kB blocks is advised diff --git a/libburn/libdax_msgs.h b/libburn/libdax_msgs.h index d67e15a..a5c0169 100644 --- a/libburn/libdax_msgs.h +++ b/libburn/libdax_msgs.h @@ -346,6 +346,7 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff 0x00020126 (SORRY,HIGH) = Write start address not properly aligned 0x00020127 (NOTE,HIGH) = Write start address is ... 0x00020128 (FATAL,HIGH) = Unsupported inquiry_type with mmc_get_performance + 0x00020129 (SORRY,HIGH) = Will not format media type libdax_audioxtr: 0x00020200 (SORRY,HIGH) = Cannot open audio source file diff --git a/libburn/mmc.c b/libburn/mmc.c index 3e025df..91dbdc9 100644 --- a/libburn/mmc.c +++ b/libburn/mmc.c @@ -55,9 +55,15 @@ extern struct libdax_msgs *libdax_messenger; functions in dvd+rw-tools are a bit intimidating to the reader. I hope it is possible to leave much of this to the drive. And if it fails ... well, it's only speed setting. :)) + ts A61229 : Burned to several DVD-RW formatted to mode Restricted Overwrite + by dvd+rw-format. Needs Libburn_support_dvd_minusrw_overW. + ts A61230 : Other than growisofs, libburn does not send a mode page 5 for + such DVD-RW (which the MMC-5 standard does deprecate) and it + really seems to work without such a page. + ts A70101 : Formatted DVD-RW media. Success is varying with media, but + dvd+rw-format does not do better with the same media. + Todo: - Determine media capacity. - Determine drive+media speed options. Determine first free lba for appending data. Determine start lba of most recent mkisofs session. */ @@ -173,8 +179,9 @@ int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa) + (data[10] << 8) + data[11]; *nwa = (data[12] << 24) + (data[13] << 16) + (data[14] << 8) + data[15]; - if (d->current_profile == 0x1a) { /* DVD+RW */ - *nwa = *nwa = 0; + if (d->current_profile == 0x1a || d->current_profile == 0x13) { + /* DVD+RW or DVD-RW restricted overwrite */ + *lba = *nwa = 0; } else if (!(data[7]&1)) { /* ts A61106 : MMC-1 Table 142 : NWA_V = NWA Valid Flag */ libdax_msgs_submit(libdax_messenger, -1, 0x00000002, @@ -1150,11 +1157,14 @@ int mmc_read_buffer_capacity(struct burn_drive *d) /* 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) +/* + @param flag unused yet, submit 0 +*/ +int mmc_format_unit(struct burn_drive *d, int flag) { struct buffer buf; struct command c; - int ret; + int ret, tolerate_failure = 0; char msg[160],descr[80]; mmc_function_spy("mmc_format_unit"); @@ -1183,13 +1193,24 @@ int mmc_format_unit(struct burn_drive *d) LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH, msg, 0,0); } - sprintf(descr, "DVD+RW, BGFS %d", - d->bg_format_status); + sprintf(descr, "DVD+RW, BGFS %d", d->bg_format_status); } else if (d->current_profile == 0x13) {/*DVD-RW restricted overwrite*/ + + /* >>> check wether READ FORMAT CAPACITIES does report + 0x13 formatting. If not, skip this. It seems to work + without formatting on e.g. freshly formatted media. */ + tolerate_failure = 1; + /* 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 */ + c.page->data[11] = 16; /* block size * 2k */ sprintf(descr, "DVD-RW, quick grow"); + } else if (d->current_profile == 0x14) {/*DVD-RW sequential recording*/ + /* 6.5.4.2.10 , DVD-RW Quick (-> Restricted Overwrite) */ + /* c.page->data[4-7]==0 : 0 blocks */ + c.page->data[8] = 0x15 << 2; /* Format type */ + c.page->data[11] = 16; /* block size * 2k */ + sprintf(descr, "DVD-RW, quick"); } else { /* >>> other formattable types to come */ @@ -1204,7 +1225,7 @@ int mmc_format_unit(struct burn_drive *d) } d->issue_command(d, &c); - if (c.error) { + if (c.error && !tolerate_failure) { if (c.sense[2]!=0) { sprintf(msg, "SCSI error on format_unit(%s): key=%X asc=%2.2Xh ascq=%2.2Xh", diff --git a/libburn/mmc.h b/libburn/mmc.h index ffc76f5..e79cb92 100644 --- a/libburn/mmc.h +++ b/libburn/mmc.h @@ -51,6 +51,10 @@ int mmc_read_buffer_capacity(struct burn_drive *d); */ int mmc_setup_drive(struct burn_drive *d); +/* 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 flag); + /* ts A61225 : obtain write speed descriptors via ACh GET PERFORMANCE */ int mmc_get_write_performance(struct burn_drive *d); diff --git a/libburn/spc.c b/libburn/spc.c index f764402..e1a3018 100644 --- a/libburn/spc.c +++ b/libburn/spc.c @@ -421,9 +421,10 @@ void spc_select_write_params(struct burn_drive *d, c.page->data[22] = 0; c.page->data[23] = 150; /* audio pause length */ +/*XXX need session format! */ + #endif /* ! Libburn_mmc_compose_mode_page_5 */ -/*XXX need session format! */ c.dir = TO_DRIVE; d->issue_command(d, &c); } diff --git a/libburn/transport.h b/libburn/transport.h index a703d0f..b8df4e7 100644 --- a/libburn/transport.h +++ b/libburn/transport.h @@ -224,7 +224,7 @@ struct burn_drive int (*read_buffer_capacity) (struct burn_drive *d); /* ts A61220 : format media (e.g. DVD+RW) */ - int (*format_unit) (struct burn_drive *d); + int (*format_unit) (struct burn_drive *d, int flag); }; diff --git a/libburn/write.c b/libburn/write.c index 4072f50..7dcf466 100644 --- a/libburn/write.c +++ b/libburn/write.c @@ -938,7 +938,7 @@ int burn_disc_setup_dvd_plus_rw(struct burn_write_opts *o, if (d->bg_format_status==0 || d->bg_format_status==1) { d->busy = BURN_DRIVE_FORMATTING; /* start or re-start dvd_plus_rw formatting */ - ret = d->format_unit(d); + ret = d->format_unit(d, 0); if (ret <= 0) return 0; d->busy = BURN_DRIVE_WRITING; @@ -972,31 +972,17 @@ int burn_disc_setup_dvd_minus_rw(struct burn_write_opts *o, 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 : + /* ??? 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" */ + + ret = d->format_unit(d, 0); /* "quick grow" */ if (ret <= 0) return 0; d->busy = BURN_DRIVE_WRITING;