diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index 5276f4f..ec55482 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2007.09.18.130344" +#define Cdrskin_timestamP "2007.09.18.200343" diff --git a/libburn/libdax_msgs.h b/libburn/libdax_msgs.h index bcfdd19..5d7205a 100644 --- a/libburn/libdax_msgs.h +++ b/libburn/libdax_msgs.h @@ -430,6 +430,9 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff 0x0002014a (SORRY,HIGH) = Cannot read desired amount of data 0x0002014b (SORRY,HIGH) = Drive is already registered resp. scanned 0x0002014c (FATAL,HIGH) = Emulated drive caught in SCSI function + 0x0002014d (SORRY,HIGH) = Asynchromous SCSI error + 0x0002014f (SORRY,HIGH) = Timeout with asynchromous SCSI command + 0x00020150 (DEBUG,LOW) = Reporting asynchronous waiting time libdax_audioxtr: diff --git a/libburn/mmc.c b/libburn/mmc.c index 8b44064..52e9cd4 100644 --- a/libburn/mmc.c +++ b/libburn/mmc.c @@ -444,9 +444,12 @@ void mmc_close(struct burn_drive *d, int session, int track) d->issue_command(d, &c); /* ts A70918 : Immed : wait for drive to complete command */ - usleep(1000000); /* (in format() there was a race condition) */ - while (!d->test_unit_ready(d)) - usleep(100000); + if (c.error) { + d->cancel = 1; + return; + } + if (spc_wait_unit_attention(d, 3600, "CLOSE TRACK SESSION", 0) <= 0) + d->cancel = 1; } void mmc_get_event(struct burn_drive *d) @@ -2273,6 +2276,9 @@ void mmc_sync_cache(struct burn_drive *d) c.oplen = sizeof(MMC_SYNC_CACHE); */ c.retry = 1; + + c.opcode[1] |= 2; /* ts A70918 : Immed */ + c.page = NULL; c.dir = NO_TRANSFER; @@ -2294,6 +2300,14 @@ void mmc_sync_cache(struct burn_drive *d) } d->issue_command(d, &c); + + /* ts A70918 */ + if (c.error) { + d->cancel = 1; + return; + } + if (spc_wait_unit_attention(d, 3600, "SYNCHRONIZE CACHE", 0) <= 0) + d->cancel = 1; } diff --git a/libburn/sbc.c b/libburn/sbc.c index 3424bc1..1e9d229 100644 --- a/libburn/sbc.c +++ b/libburn/sbc.c @@ -36,9 +36,16 @@ void sbc_load(struct burn_drive *d) c.page = NULL; */ c.retry = 1; + + c.opcode[1] |= 1; /* ts A70918 : Immed */ + c.dir = NO_TRANSFER; d->issue_command(d, &c); - spc_wait_unit_attention(d, 60); + if (c.error) + return; + /* 5 minutes for loading. If this does not suffice then other commands + shall fail righteously. */ + spc_wait_unit_attention(d, 300, "START UNIT (+ LOAD)", 0); } void sbc_eject(struct burn_drive *d) @@ -54,9 +61,16 @@ void sbc_eject(struct burn_drive *d) c.oplen = sizeof(SBC_UNLOAD); c.page = NULL; */ + + c.opcode[1] |= 1; /* ts A70918 : Immed */ + c.page = NULL; c.dir = NO_TRANSFER; d->issue_command(d, &c); + if (c.error) + return; + /* Wait long. A late eject could surprise or hurt user. */ + spc_wait_unit_attention(d, 1800, "STOP UNIT (+ EJECT)", 0); } /* ts A61118 : is it necessary to tell the drive to get ready for use ? */ @@ -74,9 +88,14 @@ int sbc_start_unit(struct burn_drive *d) c.page = NULL; */ c.retry = 1; + + c.opcode[1] |= 1; /* ts A70918 : Immed */ + c.dir = NO_TRANSFER; d->issue_command(d, &c); - return (c.error==0); + if (c.error) + return 0; + return spc_wait_unit_attention(d, 1800, "START UNIT", 0); } diff --git a/libburn/spc.c b/libburn/spc.c index c8b0acc..024653d 100644 --- a/libburn/spc.c +++ b/libburn/spc.c @@ -98,19 +98,52 @@ 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 */ /** Wait until the drive state becomes clear or until max_usec elapsed */ -int spc_wait_unit_attention(struct burn_drive *d, int max_sec) +int spc_wait_unit_attention(struct burn_drive *d, int max_sec, char *cmd_text, + int flag) { int i, ret, key, asc, ascq; + char msg[160]; - for(i=0; i < max_sec; i++) { + if (!(flag & 1)) + usleep(100000); + for(i = !(flag & 1); i < max_sec * 10; i++) { ret = spc_test_unit_ready_r(d, &key, &asc, &ascq); - if(ret > 0 || key!=0x2 || asc!=0x4) /* ready or error */ + if(ret > 0) /* ready */ break; - usleep(1000000); + if(key!=0x2 || asc!=0x4) { + if (key == 0x2 && asc == 0x3A) { + ret = 1; /* medium not present = ok */ + break; + } + if (key == 0x6 && asc == 0x28 && ascq == 0x00) + continue; /* media change notice = try again */ + sprintf(msg, + "Asynchromous SCSI error on %s: key=%X asc=%2.2Xh ascq=%2.2Xh", + cmd_text, (unsigned) key, (unsigned) asc, + (unsigned) ascq); + libdax_msgs_submit(libdax_messenger, d->global_index, + 0x0002014d, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, + msg, 0, 0); + d->cancel = 1; + break; + } + usleep(100000); } - if (i < max_sec) + 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); + + sprintf(msg, "Timeout (%d s) with asynchronous SCSI command %s\n", + max_sec, cmd_text); + libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002014f, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0); return 0; } diff --git a/libburn/spc.h b/libburn/spc.h index 2275f6b..81d2d46 100644 --- a/libburn/spc.h +++ b/libburn/spc.h @@ -28,7 +28,8 @@ int spc_test_unit_ready(struct burn_drive *d); /* ts A70315 */ /** Wait until the drive state becomes clear in or until max_sec elapsed */ -int spc_wait_unit_attention(struct burn_drive *d, int max_sec); +int spc_wait_unit_attention(struct burn_drive *d, int max_sec, char *cmd_text, + int flag); /* ts A61021 : the spc specific part of sg.c:enumerate_common() */