From 463a7ff9b9d542cd5826656b33da18916090281a Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Sat, 19 Dec 2020 14:05:29 +0100 Subject: [PATCH] cdrwtool: Switch to FORMAT UNIT Format Code 1 The specs from MMC-1 to MMC-3 prescribe for FORMAT UNIT on CD-RW media the Format Code 7 and the related format descriptor layout. Beginning with MMC-4 this code and layout have been moved to Legacy Specifications. Pioneer BD-RW BDR-S09 rev 1.51 refuses on this code but works with the more modern Format Code 1 with Format Type 10h "CD-RW/DVD-RW Full Format". So introduce a new function format_disc_code1() and rename the old function format_disc() to format_disc_code7(). Create a new format_disc() which first tries format_disc_code1() and in case of failure tries format_disc_code7(). Signed-off-by: Thomas Schmitt --- cdrwtool/cdrwtool.c | 56 ++++++++++++++++++++++++++++++++++++++++++++- cdrwtool/cdrwtool.h | 8 ++++++- cdrwtool/main.c | 9 ++++---- 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/cdrwtool/cdrwtool.c b/cdrwtool/cdrwtool.c index 69c09e4..742a7c5 100644 --- a/cdrwtool/cdrwtool.c +++ b/cdrwtool/cdrwtool.c @@ -425,7 +425,53 @@ int blank_disc(int fd, int type) return wait_for_unit_ready(fd, "BLANK", WAIT_BLANK_SECONDS); } -int format_disc(int fd, struct cdrw_disc *disc) +/* + * Format Code 1, Type 10h CD-RW/DVD-RW Full Format, + * as of MMC-4 to at least MMC-6 + */ +int format_disc_code1(int fd, struct cdrw_disc *disc, write_params_t *w) +{ + struct cdrom_generic_command cgc; + unsigned char buffer[16]; + int ret; + int i; + + memset(&cgc, 0, sizeof(cgc)); + memset(buffer, 0, sizeof(buffer)); + + cgc.cmd[0] = GPCMD_FORMAT_UNIT; + cgc.cmd[1] = 1 << 4 | 1; + cgc.buflen = 16; + + /* format list header */ + buffer[0] = 0; + buffer[1] = 0; /* FOV: 0 (use defaults) */ + buffer[1] |= ((USE_IMMED || USE_IMMED_WITH_FORMAT_1) << 1); + buffer[2] = 0; + buffer[3] = 8; + + /* format descriptor */ + buffer[4] = (disc->offset >> 24) & 0xff; /* Number of Blocks */ + buffer[5] = (disc->offset >> 16) & 0xff; + buffer[6] = (disc->offset >> 8) & 0xff; + buffer[7] = disc->offset & 0xff; + buffer[8] = 0x10 << 2; /* Format Type 10h , Format Sub-type 0 */ + + /* Fixed Packet Size as used in Mode Page 5 */ + buffer[9] = (w->packet_size >> 16) & 0xff; + buffer[10] = (w->packet_size >> 8) & 0xff; + buffer[11] = w->packet_size & 0xff; + + if ((ret = wait_cmd(fd, &cgc, buffer, CGC_DATA_WRITE, WAIT_BLANK)) < 0) + { + perror("format disc"); + return ret; + } + return wait_for_unit_ready(fd, "FORMAT UNIT 1", WAIT_BLANK_SECONDS); +} + +/* Legacy Format Code 7 as of MMC-1 to MMC-3, deprecated in MMC-4 */ +int format_disc_code7(int fd, struct cdrw_disc *disc) { struct cdrom_generic_command cgc; unsigned char buffer[16]; @@ -468,6 +514,14 @@ int format_disc(int fd, struct cdrw_disc *disc) return wait_for_unit_ready(fd, "FORMAT UNIT 7", WAIT_BLANK_SECONDS); } +int format_disc(int fd, struct cdrw_disc *disc, write_params_t *w) +{ + if (format_disc_code1(fd, disc, w) == 0) + return 0; + printf("Re-trying formatting with legacy code 7\n"); + return format_disc_code7(fd, disc); +} + int read_disc_info(int fd, disc_info_t *di) { struct cdrom_generic_command cgc; diff --git a/cdrwtool/cdrwtool.h b/cdrwtool/cdrwtool.h index 25d8b79..090fd0f 100644 --- a/cdrwtool/cdrwtool.h +++ b/cdrwtool/cdrwtool.h @@ -38,6 +38,12 @@ * the device for completion. */ #define USE_IMMED 1 +/* + * With FORMAT UNIT Format Code 1 on 12x CD-RW, LG BD-RE BH16NS40 gets stuck + * if not the Immed bit is set. So even when setting USE_IMMED to 0, better + * let this macro stay 1, in order to prevent such a mishap. + */ +#define USE_IMMED_WITH_FORMAT_1 1 #define PAGE_CURRENT 0 #define PAGE_CHANGE 1 @@ -204,7 +210,7 @@ int sync_cache(int); int write_blocks(int, unsigned char *, int, int); int write_file(int, struct cdrw_disc *); int blank_disc(int, int); -int format_disc(int, struct cdrw_disc *); +int format_disc(int, struct cdrw_disc *, write_params_t *); int read_disc_info(int, disc_info_t *); int read_track_info(int, track_info_t *, int); int reserve_track(int, struct cdrw_disc *); diff --git a/cdrwtool/main.c b/cdrwtool/main.c index c6198d1..38d2c95 100644 --- a/cdrwtool/main.c +++ b/cdrwtool/main.c @@ -117,7 +117,8 @@ int write_func(struct udf_disc *disc, struct udf_extent *ext) return 0; } -int quick_setup(int fd, struct cdrw_disc *disc, const char *device) +int quick_setup(int fd, struct cdrw_disc *disc, const char *device, + write_params_t *w) { disc_info_t di; track_info_t ti; @@ -169,7 +170,7 @@ int quick_setup(int fd, struct cdrw_disc *disc, const char *device) if (!disc->offset) disc->offset = blocks; printf("Formatting track\n"); - if ((ret = format_disc(fd, disc))) + if ((ret = format_disc(fd, disc, w))) return ret; add_type2_sparable_partition(&disc->udf_disc, 0, 2, 32); disc->udf_disc.udf_pd[0]->accessType = cpu_to_le32(PD_ACCESS_TYPE_REWRITABLE); @@ -332,7 +333,7 @@ int main(int argc, char *argv[]) if (disc.quick_setup) { - ret = quick_setup(fd, &disc, filename); + ret = quick_setup(fd, &disc, filename, &w); cdrom_close(fd); return ret; } @@ -346,7 +347,7 @@ int main(int argc, char *argv[]) if (disc.format) { - ret = format_disc(fd, &disc); + ret = format_disc(fd, &disc, &w); cdrom_close(fd); return ret; } -- 2.20.1