+
+static void disc_seed_diag_clear (disc *d) {
+ if (!d)
+ return;
+ memset (&d -> seed_diagnostic, 0, sizeof (d -> seed_diagnostic));
+}
+
+static void disc_seed_diag_log (disc *d, const char *fmt, ...) {
+ va_list ap;
+ if (!d || !d -> seed_diagnostic_active || !fmt)
+ return;
+ xbox_ref_log_fprintf (stderr, "[SEED-DIAG] ");
+ va_start (ap, fmt);
+ /* xbox_ref_log_fprintf is variadic rather than vfprintf-based, so format
+ * into a bounded buffer before sending the line to both console and log. */
+ {
+ char line[768];
+ vsnprintf (line, sizeof (line), fmt, ap);
+ xbox_ref_log_fprintf (stderr, "%s\n", line);
+ }
+ va_end (ap);
+}
+
+static void disc_seed_diag_fail (
+ disc *d,
+ u_int32_t sector_start,
+ u_int32_t sector_end,
+ int retry,
+ const char *stage,
+ const char *detail,
+ int transport_result,
+ bool capture_command
+) {
+ dvd_command_diagnostic command;
+ char cdb_text[3 * 12 + 1];
+ int i;
+ int used;
+
+ if (!d || !d -> seed_diagnostic_active)
+ return;
+ disc_seed_diag_clear (d);
+ d -> seed_diagnostic.valid = true;
+ d -> seed_diagnostic.seed_block_index = d -> seed_diagnostic_block;
+ d -> seed_diagnostic.sector_start = sector_start;
+ d -> seed_diagnostic.sector_end = sector_end;
+ d -> seed_diagnostic.retry = retry;
+ snprintf (d -> seed_diagnostic.stage, sizeof (d -> seed_diagnostic.stage), "%s", stage ? stage : "unknown");
+ snprintf (d -> seed_diagnostic.detail, sizeof (d -> seed_diagnostic.detail), "%s", detail ? detail : "");
+ d -> seed_diagnostic.transport_result = transport_result;
+
+ memset (&command, 0, sizeof (command));
+ if (capture_command && dvd_get_last_command_diagnostic (d -> dvd, &command)) {
+ d -> seed_diagnostic.transport_result = command.transport_result;
+ d -> seed_diagnostic.os_error = command.os_error;
+ d -> seed_diagnostic.scsi_status = command.scsi_status;
+ d -> seed_diagnostic.sense_key = command.sense_key;
+ d -> seed_diagnostic.asc = command.asc;
+ d -> seed_diagnostic.ascq = command.ascq;
+ d -> seed_diagnostic.cdb_length = command.cdb_length;
+ memcpy (d -> seed_diagnostic.cdb, command.cdb, sizeof (d -> seed_diagnostic.cdb));
+ }
+
+ cdb_text[0] = '\0';
+ used = 0;
+ for (i = 0; i < d -> seed_diagnostic.cdb_length && i < 12; i++) {
+ int wrote = snprintf (cdb_text + used, sizeof (cdb_text) - (size_t) used,
+ "%s%02X", i ? " " : "", d -> seed_diagnostic.cdb[i]);
+ if (wrote < 0 || wrote >= (int) (sizeof (cdb_text) - (size_t) used))
+ break;
+ used += wrote;
+ }
+
+ disc_seed_diag_log (d,
+ "block=%u/20 sectors=%u..%u retry=%d stage=%s result=FAIL rc=%d os=%d scsi=0x%02X sense=%02X/%02X/%02X cdb=[%s] detail=%s",
+ d -> seed_diagnostic.seed_block_index + 1,
+ sector_start, sector_end, retry,
+ d -> seed_diagnostic.stage,
+ d -> seed_diagnostic.transport_result,
+ d -> seed_diagnostic.os_error,
+ d -> seed_diagnostic.scsi_status & 0xff,
+ d -> seed_diagnostic.sense_key & 0xff,
+ d -> seed_diagnostic.asc & 0xff,
+ d -> seed_diagnostic.ascq & 0xff,
+ cdb_text[0] ? cdb_text : "none",
+ d -> seed_diagnostic.detail[0] ? d -> seed_diagnostic.detail : "none");
+}
+
+bool disc_get_seed_diagnostic (disc *d, disc_seed_diagnostic *out) {
+ if (!d || !out || !d -> seed_diagnostic.valid)
+ return false;
+ *out = d -> seed_diagnostic;
+ return true;
+}
+