From f505c56896157ccb6151a596aef6859c4cbf9df7 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 --- libburn/trunk/cdrskin/cdrskin_timestamp.h | 2 +- libburn/trunk/libburn/async.c | 50 +++++++++++++++++++++++ libburn/trunk/libburn/drive.c | 38 ++++++++++++++++- libburn/trunk/libburn/drive.h | 4 ++ libburn/trunk/libburn/libburn.h | 19 +++++++-- libburn/trunk/libburn/libdax_msgs.h | 1 + libburn/trunk/libburn/mmc.c | 41 ++++++++++++++----- libburn/trunk/libburn/mmc.h | 4 ++ libburn/trunk/libburn/spc.c | 3 +- libburn/trunk/libburn/transport.h | 2 +- libburn/trunk/libburn/write.c | 26 +++--------- 11 files changed, 152 insertions(+), 38 deletions(-) diff --git a/libburn/trunk/cdrskin/cdrskin_timestamp.h b/libburn/trunk/cdrskin/cdrskin_timestamp.h index 8ebb2d18..2a10d51f 100644 --- a/libburn/trunk/cdrskin/cdrskin_timestamp.h +++ b/libburn/trunk/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2006.12.30.001343" +#define Cdrskin_timestamP "2007.01.01.170824" diff --git a/libburn/trunk/libburn/async.c b/libburn/trunk/libburn/async.c index e48d7197..4aae06ee 100644 --- a/libburn/trunk/libburn/async.c +++ b/libburn/trunk/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/trunk/libburn/drive.c b/libburn/trunk/libburn/drive.c index 847ef156..700fba29 100644 --- a/libburn/trunk/libburn/drive.c +++ b/libburn/trunk/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/trunk/libburn/drive.h b/libburn/trunk/libburn/drive.h index 794e8139..b8356330 100644 --- a/libburn/trunk/libburn/drive.h +++ b/libburn/trunk/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/trunk/libburn/libburn.h b/libburn/trunk/libburn/libburn.h index a4cb9853..b20a899d 100644 --- a/libburn/trunk/libburn/libburn.h +++ b/libburn/trunk/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/trunk/libburn/libdax_msgs.h b/libburn/trunk/libburn/libdax_msgs.h index d67e15a3..a5c01695 100644 --- a/libburn/trunk/libburn/libdax_msgs.h +++ b/libburn/trunk/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/trunk/libburn/mmc.c b/libburn/trunk/libburn/mmc.c index 3e025df3..91dbdc99 100644 --- a/libburn/trunk/libburn/mmc.c +++ b/libburn/trunk/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/trunk/libburn/mmc.h b/libburn/trunk/libburn/mmc.h index ffc76f50..e79cb922 100644 --- a/libburn/trunk/libburn/mmc.h +++ b/libburn/trunk/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/trunk/libburn/spc.c b/libburn/trunk/libburn/spc.c index f7644026..e1a30183 100644 --- a/libburn/trunk/libburn/spc.c +++ b/libburn/trunk/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/trunk/libburn/transport.h b/libburn/trunk/libburn/transport.h index a703d0f0..b8df4e7f 100644 --- a/libburn/trunk/libburn/transport.h +++ b/libburn/trunk/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/trunk/libburn/write.c b/libburn/trunk/libburn/write.c index 4072f508..7dcf466a 100644 --- a/libburn/trunk/libburn/write.c +++ b/libburn/trunk/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;