diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index 2fe4237..b2171aa 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2009.11.10.132154" +#define Cdrskin_timestamP "2009.11.10.203412" diff --git a/libburn/libburn.h b/libburn/libburn.h index 11f6888..3909f33 100644 --- a/libburn/libburn.h +++ b/libburn/libburn.h @@ -2750,38 +2750,33 @@ BURN_END_DECLS #endif -/* Temporary facility for exploring problems with Pioneer DVR-216D which - does not end writing of DVD-R. - This code does not hamper normal operations but causes some extra - messages to stderr and lots of text lines in File - /tmp/libburn_sg_command_log +/* This solves a problem with Pioneer DVR-216D. + Writing of sequential DVD-R[W] happens unnaturally fast and leaves no + impact on the media. The drive stalls at the end of the burn run. Only a + power cycle makes it usable again. - Move the next line outside this remark and remove all blanks up to "define". - # define Libburn_pioneer_dvr_216d_tesT 1 + Apparent reason: + One may not read the buffer capacity more than once before it is full + and physical burning begun. Strangely this happens only with libburn and + cdrecord-2.01.01a64 -v which both write DVD-R in 32 KB chunks. With + wodim's 62 KB chunks there is no endless drive business. */ +#define Libburn_pioneer_dvr_216d_read_buf_caP 1 -/* Experiment for problems with Pioneer DVR-216D: - SEND OPC INFORMATION command with DoOPC=1 after eventually reserving a - track on sequential DVD-R[W]. - wodim does this, growisofs sometimes, libburn only with this macro - Move the next line outside this remark and remove all blanks up to "define". +/* The following experiments did not solve the problem with Pioneer DVR-216D + but may nevertheless be interesting in future: + # define Libburn_pioneer_dvr_216d_with_opC 1 + # define Libburn_pioneer_dvr_216d_load_mode5 1 + # define Libburn_pioneer_dvr_216d_get_evenT 1 */ -/* Experiment for problems with Pioneer DVR-216D: - After starting unit asynchronously issue again a synchronous START UNIT. - Issue an extra START UNIT pair before reserving the track. +/* Probing of CD write modes hampers ejecting of the drive tray. + Needed is a more intelligent management of probing. + Note to myself: check whether feature interpretation can replace probing - Move the next line outside this remark and remove all blanks up to "define". - # define Libburn_pioneer_dvr_216d_double_starT 1 -*/ - -/* Experiment for problems with Pioneer DVR-216D: - Set speed not only via SET STREAMING but also via SET CD SPEED. - - Move the next line outside this remark and remove all blanks up to "define". - # define Libburn_pioneer_dvr_216d_set_cd_speeD 1 + # define Libburn_pioneer_dvr_216d_no_probe_wM 1 */ diff --git a/libburn/mmc.c b/libburn/mmc.c index 6539e3f..4c7f702 100644 --- a/libburn/mmc.c +++ b/libburn/mmc.c @@ -28,6 +28,8 @@ /* ts A70223 : in init.c */ extern int burn_support_untested_profiles; +static int mmc_get_configuration_al(struct burn_drive *d, int *alloc_len); + #ifdef Libburn_log_in_and_out_streaM /* <<< ts A61031 */ @@ -177,7 +179,7 @@ static unsigned char MMC_GET_CONFIGURATION[] = { 0x46, 0, 0, 0, 0, 0, 0, 16, 0, 0 }; static unsigned char MMC_SYNC_CACHE[] = { 0x35, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static unsigned char MMC_GET_EVENT[] = { 0x4A, 1, 0, 0, 16, 0, 0, 0, 8, 0 }; +static unsigned char MMC_GET_EVENT[] = { 0x4A, 1, 0, 0, 0x7e, 0, 0, 0, 8, 0 }; static unsigned char MMC_CLOSE[] = { 0x5B, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char MMC_TRACK_INFO[] = { 0x52, 0, 0, 0, 0, 0, 0, 16, 0, 0 }; @@ -410,6 +412,11 @@ int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa) *lba = mmc_four_char_to_int(data + 8); *nwa = mmc_four_char_to_int(data + 12); num = mmc_four_char_to_int(data + 16); + +#ifdef Libburn_pioneer_dvr_216d_load_mode5 + /* >>> memorize track mode : data[6] & 0xf */; +#endif + if (d->current_profile == 0x1a || d->current_profile == 0x13 || d->current_profile == 0x12 || d->current_profile == 0x43) { /* overwriteable */ @@ -520,17 +527,19 @@ void mmc_get_event(struct burn_drive *d) { struct buffer buf; struct command c; - int alloc_len= 8; + int alloc_len = 8, len, evt_code, loops = 0; + unsigned char *evt; if (mmc_function_spy(d, "mmc_get_event") <= 0) return; +again:; scsi_init_command(&c, MMC_GET_EVENT, sizeof(MMC_GET_EVENT)); -/* - c.oplen = sizeof(MMC_GET_EVENT); - memcpy(c.opcode, MMC_GET_EVENT, sizeof(MMC_GET_EVENT)); -*/ - c.dxfer_len = alloc_len; + c.dxfer_len = 8; + + /* >>> have a burn_drive element for Notification Class */; + c.opcode[4] = 0x7e; + c.opcode[7] = (c.dxfer_len >> 8) & 0xff; c.opcode[8] = c.dxfer_len & 0xff; c.retry = 1; @@ -539,11 +548,66 @@ void mmc_get_event(struct burn_drive *d) c.page->sectors = 0; c.dir = FROM_DRIVE; d->issue_command(d, &c); - burn_print(12, "0x%x:0x%x:0x%x:0x%x\n", - c.page->data[0], c.page->data[1], c.page->data[2], - c.page->data[3]); - burn_print(12, "event: %d:%d:%d:%d\n", c.page->data[4], - c.page->data[5], c.page->data[6], c.page->data[7]); + if (c.error) + return; + + evt = c.page->data; + len = ((evt[0] << 8) | evt[1]) + 2; + if (len < 8) + return; + + /* >>> memorize evt[3] in burn_drive element for Notification Class */; + if (evt[3] == 0) /* No event */ + return; + + evt_code = evt[4] & 0xf; + if (evt_code == 0) /* No change */ + return; + + switch (evt[2] & 7) { + case 0: /* no events supported */ + return; + case 1: /* Operational change */ + if (((evt[6] << 8) | evt[7])) { + alloc_len = 8; + mmc_get_configuration_al(d, &alloc_len); + } + break; + case 2: /* Power Management */ + if (evt[5] >= 2) + d->start_unit(d); + break; + case 3: /* External request */ + + /* >>> report about external request */; + + break; + case 4: /* Media */ + if (evt_code == 2) { + d->start_unit(d); + alloc_len = 8; + mmc_get_configuration_al(d, &alloc_len); + } + break; + case 5: /* Multiple Host Events */ + + /* >>> report about foreign host interference */; + + break; + + case 6: /* Device busy */ + if (evt_code == 1 && evt[5]) { + + /* >>> wait the time announced in evt[6],[7] + as 100ms units */; + } + break; + default: /* reserved */ + break; + } + loops++; + if (loops < 100) + goto again; } @@ -2167,10 +2231,6 @@ int mmc_set_streaming(struct burn_drive *d, return 0; scsi_init_command(&c, MMC_SET_STREAMING, sizeof(MMC_SET_STREAMING)); -/* - c.oplen = sizeof(MMC_SET_STREAMING); - memcpy(c.opcode, MMC_SET_STREAMING, sizeof(MMC_SET_STREAMING)); -*/ c.retry = 1; c.page = &buf; c.page->bytes = 28; @@ -2280,15 +2340,8 @@ void mmc_set_speed(struct burn_drive *d, int r, int w) /* ts A61221 : try to set DVD speed via command B6h */ if (strstr(d->current_profile_text, "DVD") == d->current_profile_text){ ret = mmc_set_streaming(d, r, w, end_lba); - -#ifdef Libburn_pioneer_dvr_216d_set_cd_speeD - if (ret < 0) - return; /* fatal failure */ -#else if (ret != 0) return; /* success or really fatal failure */ -#endif /* ! Libburn_pioneer_dvr_216d_set_cd_speeD */ - } /* ts A61112 : MMC standards prescribe FFFFh as max speed. @@ -2835,11 +2888,7 @@ void mmc_sync_cache(struct burn_drive *d) c.oplen = sizeof(MMC_SYNC_CACHE); */ c.retry = 1; - -#ifndef Libburn_pioneer_dvr_sync_not_immeD c.opcode[1] |= 2; /* ts A70918 : Immed */ -#endif - c.page = NULL; c.dir = NO_TRANSFER; @@ -2868,11 +2917,7 @@ void mmc_sync_cache(struct burn_drive *d) return; } -#ifdef Libburn_pioneer_dvr_216d_tesT - if (spc_wait_unit_attention(d, 300, "SYNCHRONIZE CACHE", 0) <= 0) -#else if (spc_wait_unit_attention(d, 3600, "SYNCHRONIZE CACHE", 0) <= 0) -#endif d->cancel = 1; else d->needs_sync_cache = 0; @@ -2894,11 +2939,6 @@ int mmc_read_buffer_capacity(struct burn_drive *d) scsi_init_command(&c, MMC_READ_BUFFER_CAPACITY, sizeof(MMC_READ_BUFFER_CAPACITY)); -/* - memcpy(c.opcode, MMC_READ_BUFFER_CAPACITY, - sizeof(MMC_READ_BUFFER_CAPACITY)); - c.oplen = sizeof(MMC_READ_BUFFER_CAPACITY); -*/ c.dxfer_len = alloc_len; c.opcode[7] = (c.dxfer_len >> 8) & 0xff; c.opcode[8] = c.dxfer_len & 0xff; @@ -3751,7 +3791,7 @@ int mmc_compose_mode_page_5(struct burn_drive *d, pd[5] = 0; } else if ((d->current_profile == 0x14 || d->current_profile == 0x11 || d->current_profile == 0x15) - && o->write_type == BURN_WRITE_SAO) { + && o->write_type == BURN_WRITE_SAO) { /* ts A70205 : DVD-R[W][/DL] : Disc-at-once, DAO */ /* Learned from dvd+rw-tools and mmc5r03c.pdf . See doc/cookbook.txt for more detailed references. */ @@ -3760,19 +3800,20 @@ int mmc_compose_mode_page_5(struct burn_drive *d, pd[2] = ((!!o->underrun_proof) << 6) | ((!!o->simulate) << 4) | 2; - /* No multi-session , FP = 0 , Track Mode = 5 */ + + /* No multi-session , FP = 0 , Copy = 0, Track Mode = 5 */ pd[3] = 5; + +#ifdef Libburn_pioneer_dvr_216d_load_mode5 + + /* >>> use track mode from mmc_get_nwa() */ + /* >>> pd[3] = (pd[3] & ~0xf) | (d->track_inf[5] & 0xf); */ + +#endif + /* Data Block Type = 8 */ pd[4] = 8; - -/* <<< did not help. A91104 */ -#ifdef Libburn_pioneer_dvr_216d_lsv_onE - pd[2] |= (1 << 5); /* LS_V = 1 */ - pd[5] = 16; /* Link Size = 16 */ - fprintf(stderr, "libburn_DEBUG: Libburn_pioneer_dvr_216d_lsv_onE , LS_V=1, Link Size=16\n"); -#endif - } else if (d->current_profile == 0x14 || d->current_profile == 0x11 || d->current_profile == 0x15) { /* ts A70128 : DVD-R[W][/DL] Incremental Streaming */ @@ -3807,10 +3848,6 @@ int mmc_compose_mode_page_5(struct burn_drive *d, /* Packet Size */ pd[13] = 16; -#ifdef Libburn_pioneer_dvr_216d_lsv_onE - fprintf(stderr, "libburn_DEBUG: Libburn_pioneer_dvr_216d_lsv_onE , LS_V= %d, Link Size= %d\n", !!(pd[2] & 32), (int) pd[5]); -#endif - } else if (d->current_profile == 0x1a || d->current_profile == 0x1b || d->current_profile == 0x2b || d->current_profile == 0x12 || d->current_profile == 0x41 || d->current_profile == 0x42 || diff --git a/libburn/sbc.c b/libburn/sbc.c index 94e42de..3e005dd 100644 --- a/libburn/sbc.c +++ b/libburn/sbc.c @@ -10,10 +10,6 @@ #include "spc.h" #include "options.h" -#ifdef Libburn_pioneer_dvr_216d_double_starT -#include -#endif - /* ts A70910 debug: for tracing calls which might use open drive fds @@ -99,18 +95,6 @@ int sbc_start_unit(struct burn_drive *d) /* ts A70918 : now asynchronous */ d->is_stopped = 0; ret = spc_wait_unit_attention(d, 1800, "START UNIT", 0); - -#ifdef Libburn_pioneer_dvr_216d_double_starT - fprintf(stderr, "libburn_DEBUG: Libburn_pioneer_dvr_216d_double_starT\n"); - scsi_init_command(&c, SBC_START_UNIT, sizeof(SBC_START_UNIT)); - c.retry = 1; - c.opcode[1] = 0; /* Not Immed */ - c.dir = NO_TRANSFER; - d->issue_command(d, &c); - if (c.error) - return 0; -#endif - return ret; } diff --git a/libburn/sg-linux.c b/libburn/sg-linux.c index 9fa7364..1ef7822 100644 --- a/libburn/sg-linux.c +++ b/libburn/sg-linux.c @@ -1655,11 +1655,6 @@ int sg_release(struct burn_drive *d) #define Libburn_log_sg_command_stderR 1 */ -#ifdef Libburn_pioneer_dvr_216d_tesT -#define Libburn_log_sg_commandS 1 -#define Libburn_fflush_log_sg_commandS 1 -#endif - #ifdef Libburn_log_sg_commandS diff --git a/libburn/spc.c b/libburn/spc.c index a6b63e8..ec8e1ba 100644 --- a/libburn/spc.c +++ b/libburn/spc.c @@ -98,7 +98,9 @@ int spc_test_unit_ready(struct burn_drive *d) /* ts A70315 */ -/** @param flag bit0=do not wait 0.1 seconds before first test unit ready */ +/** @param flag bit0=do not wait 0.1 seconds before first test unit ready + bit1=do not issue success message + */ /** Wait until the drive state becomes clear or until max_usec elapsed */ int spc_wait_unit_attention(struct burn_drive *d, int max_sec, char *cmd_text, int flag) @@ -112,15 +114,6 @@ int spc_wait_unit_attention(struct burn_drive *d, int max_sec, char *cmd_text, usleep(100000); for(i = !(flag & 1); i < max_sec * 10; i++) { ret = spc_test_unit_ready_r(d, &key, &asc, &ascq); - -#ifdef Libburn_pioneer_dvr_216d_tesT - if ((i % 100) == 1) - fprintf(stderr, -"libburn_EXPERIMENTAL: i= %d ret= %d key= %X asc= %2.2X ascq= %2.2X\n", - i, ret, (unsigned) key, - (unsigned) asc, (unsigned) ascq); -#endif /* Libburn_pioneer_dvr_216d_tesT */ - if (ret > 0) /* ready */ break; if (key!=0x2 || asc!=0x4) { @@ -160,11 +153,14 @@ int spc_wait_unit_attention(struct burn_drive *d, int max_sec, char *cmd_text, slumber:; usleep(100000); } - - sprintf(msg, "Async %s %s after %d.%d seconds", - cmd_text, (ret > 0 ? "succeeded" : "failed"), i / 10, i % 10); - libdax_msgs_submit(libdax_messenger, d->global_index, 0x00020150, - LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_LOW, msg, 0, 0); + if (ret <= 0 || !(flag & 2)) { + sprintf(msg, "Async %s %s after %d.%d seconds", + cmd_text, (ret > 0 ? "succeeded" : "failed"), + i / 10, i % 10); + libdax_msgs_submit(libdax_messenger, d->global_index, + 0x00020150, LIBDAX_MSGS_SEV_DEBUG, + LIBDAX_MSGS_PRIO_LOW, msg, 0, 0); + } if (i < max_sec * 10) return (ret > 0); @@ -254,14 +250,14 @@ void spc_prevent(struct burn_drive *d) return; scsi_init_command(&c, SPC_PREVENT, sizeof(SPC_PREVENT)); -/* - memcpy(c.opcode, SPC_PREVENT, sizeof(SPC_PREVENT)); - c.oplen = sizeof(SPC_PREVENT); - c.page = NULL; -*/ c.retry = 1; c.dir = NO_TRANSFER; d->issue_command(d, &c); + +#ifdef Libburn_pioneer_dvr_216d_get_evenT + mmc_get_event(d); +#endif + } void spc_allow(struct burn_drive *d) @@ -642,6 +638,7 @@ void spc_select_write_params(struct burn_drive *d, { struct buffer buf; struct command c; + int alloc_len; if (mmc_function_spy(d, "select_write_params") <= 0) return; @@ -656,13 +653,33 @@ void spc_select_write_params(struct burn_drive *d, o->block_type,spc_block_type(o->block_type)); */ - scsi_init_command(&c, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT)); -/* - memcpy(c.opcode, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT)); - c.oplen = sizeof(SPC_MODE_SELECT); -*/ + alloc_len = 8 + 2 + d->mdata->write_page_length; + memset(&(buf.data), 0, alloc_len); + +#ifdef Libburn_pioneer_dvr_216d_load_mode5 + + scsi_init_command(&c, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE)); + c.dxfer_len = alloc_len; + c.opcode[7] = (alloc_len >> 8) & 0xff; + c.opcode[8] = alloc_len & 0xff; c.retry = 1; - c.opcode[8] = 8 + 2 + d->mdata->write_page_length; + c.opcode[2] = 0x05; + c.page = &buf; + c.page->bytes = 0; + c.page->sectors = 0; + c.dir = FROM_DRIVE; + d->issue_command(d, &c); + + if (c.error) + memset(&(buf.data), 0, + 8 + 2 + d->mdata->write_page_length); + +#endif /* Libburn_pioneer_dvr_216d_load_mode5 */ + + scsi_init_command(&c, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT)); + c.retry = 1; + c.opcode[7] = (alloc_len >> 8) & 0xff; + c.opcode[8] = alloc_len & 0xff; c.page = &buf; c.page->bytes = 0; c.page->sectors = 0; @@ -670,8 +687,7 @@ void spc_select_write_params(struct burn_drive *d, /* ts A61007 : moved up to burn_disc_write() */ /* a ssert(d->mdata->valid); */ - 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 = alloc_len; burn_print(12, "using write page length %d (valid %d)\n", d->mdata->write_page_length, d->mdata->write_page_valid); diff --git a/libburn/write.c b/libburn/write.c index 573394f..a859917 100644 --- a/libburn/write.c +++ b/libburn/write.c @@ -43,6 +43,8 @@ #include "options.h" #include "structure.h" #include "source.h" +#include "mmc.h" +#include "spc.h" #include "libdax_msgs.h" extern struct libdax_msgs *libdax_messenger; @@ -1080,8 +1082,17 @@ int burn_disc_open_track_dvd_minus_r(struct burn_write_opts *o, /* ts A70214 : eventually adjust already expanded size of track */ burn_track_apply_fillup(s->track[tnum], d->media_capacity_remaining,1); -#ifdef Libburn_pioneer_dvr_216d_double_starT - d->start_unit(d); +#ifdef Libburn_pioneer_dvr_216d_with_opC + fprintf(stderr, "libburn_DEBUG: Libburn_pioneer_dvr_216d_with_opC : num_opc_tables = %d\n", d->num_opc_tables); + if (d->num_opc_tables <= 0 && !o->simulate) { + fprintf(stderr, "libburn_DEBUG: Libburn_pioneer_dvr_216d_with_opC : performing OPC\n"); + d->perform_opc(d); + fprintf(stderr, "libburn_DEBUG: Libburn_pioneer_dvr_216d_with_opC : done\n"); + } +#endif + +#ifdef Libburn_pioneer_dvr_216d_get_evenT + mmc_get_event(d); #endif if (o->write_type == BURN_WRITE_SAO) { /* DAO */ @@ -1100,16 +1111,6 @@ int burn_disc_open_track_dvd_minus_r(struct burn_write_opts *o, return 0; } } - -#ifdef Libburn_pioneer_dvr_216d_with_opC - fprintf(stderr, "libburn_DEBUG: Libburn_pioneer_dvr_216d_with_opC : num_opc_tables = %d\n", d->num_opc_tables); - if (d->num_opc_tables <= 0 && !o->simulate) { - fprintf(stderr, "libburn_DEBUG: Libburn_pioneer_dvr_216d_with_opC : performing OPC\n"); - d->perform_opc(d); - fprintf(stderr, "libburn_DEBUG: Libburn_pioneer_dvr_216d_with_opC : done\n"); - } -#endif - return 1; } @@ -1254,6 +1255,7 @@ int burn_dvd_write_track(struct burn_write_opts *o, struct buffer *out = d->buffer; int sectors; int i, open_ended = 0, ret= 0, is_flushed = 0; + int first_buf_cap = 0, further_cap = 0; /* ts A70213 : eventually expand size of track to max */ burn_track_apply_fillup(t, d->media_capacity_remaining, 0); @@ -1264,6 +1266,15 @@ int burn_dvd_write_track(struct burn_write_opts *o, ret = burn_disc_open_track_dvd_minus_r(o, s, tnum); if (ret <= 0) goto ex; + +#ifdef Libburn_pioneer_dvr_216d_read_buf_caP + /* Pioneer DVR-216D rev 1.09 hates multiple buffer inquiries + before the drive buffer is full. + */ + first_buf_cap = 0; + further_cap = -1; +#endif + } else if (d->current_profile == 0x1b || d->current_profile == 0x2b) { /* DVD+R , DVD+R/DL */ ret = burn_disc_open_track_dvd_plus_r(o, s, tnum); @@ -1299,8 +1310,16 @@ int burn_dvd_write_track(struct burn_write_opts *o, for (i = 0; open_ended || i < sectors; i++) { /* From time to time inquire drive buffer */ - if ((i%256)==0) + /* ts A91110: Eventually avoid to do this more than once + before the drive buffer is full. See above DVD- + */ + if (i == first_buf_cap || + ((i % 256) == 0 && (i >= further_cap || further_cap < 0))) { d->read_buffer_capacity(d); + if (further_cap < 0) + further_cap = + d->progress.buffer_capacity / 2048 + 128; + } /* transact a (CD sized) sector */ if (!sector_data(o, t, 0))