static void info_scsi_cmd_err(struct udev *udev, char *cmd, int err) { if (err == -1) { info(udev, "%s failed\n", cmd); return; } info(udev, "%s failed with SK=%Xh/ASC=%02Xh/ACQ=%02Xh\n", cmd, SK(err), ASC(err), ASCQ(err)); }
/* * Descriptor format sense data. See spc3 p 31. Returns length of * buffer used so far. */ int _sense_header_build(uint8_t *data, int len, uint8_t key, uint16_t code, uint8_t additional_len, const char *file, int line) { if (len < 8) return 0; data[0] = 0x72; /* current, not deferred */ data[1] = key; data[2] = ASC(code); data[3] = ASCQ(code); data[7] = additional_len; /* additional length, beyond these 8 bytes */ osd_warning("%s:%d: _sense_header_build key=%d code=%x additional_len=%d", file, line, key, code, additional_len); return 8; }
void write_fini(void) { print_n_flush(gettext("Finalizing (Can take several minutes)...")); /* Some drives don't like this while in test write mode */ if (!simulation) { if (!finalize(target)) { /* * It is possible that the drive is busy writing the * buffered portion. So do not get upset yet. */ (void) sleep(10); if (!finalize(target)) { if (debug) { (void) printf("status %x, %x/%x/%x\n", uscsi_status, SENSE_KEY(rqbuf), ASC(rqbuf), ASCQ(rqbuf)); } /* * Different vendor drives return different * sense error info for CLOSE SESSION command. * The Panasonic drive that we are using is * one such drive. */ if (device_type == DVD_MINUS) { if (verbose) { (void) printf( "skipping finalizing\n"); } } else { /* l10n_NOTE : 'failed' as in finishing up...failed */ (void) printf(gettext("failed.\n")); err_msg(gettext( "Could not finalize the disc.\n")); exit(1); } } } if (vol_running) { (void) eject_media(target); } } else if (check_device(target, CHECK_MEDIA_IS_NOT_BLANK)) { /* * Some drives such as the pioneer A04 will retain a * ghost TOC after a simulation write is done. The * media will actually be blank, but the drive will * report a TOC. There is currently no other way to * re-initialize the media other than ejecting or * to ask the drive to clear the leadout. The laser * is currently off so nothing is written to the * media (on a good behaving drive). * NOTE that a device reset does not work to make * the drive re-initialize the media. */ blanking_type = "clear_ghost"; blank(); } /* l10n_NOTE : 'done' as in "Finishing up...done" */ (void) printf(gettext("done.\n")); }
/* * Close session. This will write TOC. */ int finalize(cd_device *dev) { uchar_t *di; int count, ret, err; int immediate; int finalize_max; /* * For ATAPI devices we will use the immediate mode and will * poll the command for completion so that this command may * not hog the channel. But for SCSI, we will use the treditional * way of issuing the command with a large enough timeout. This * is done because immediate mode was designed for ATAPI and some * SCSI RW drives might not be even tested with it. */ if ((dev->d_inq[2] & 7) != 0) { /* SCSI device */ immediate = 0; } else { /* non-SCSI (e.g ATAPI) device */ immediate = 1; } /* We need to close track before close session */ if (device_type == DVD_PLUS) { if (!close_track(dev->d_fd, 0, 0, immediate)) return (0); } if (!close_track(dev->d_fd, 0, 1, immediate)) { /* * For DAO mode which we use for DVD-RW, the latest MMC * specification does not mention close_track. Some * newer drives will return an ILLEGAL INSTRUCTION * which we will ignore. We have also found a Panasonic * drive which will return a MEDIA ERROR. It is safe * to ignore both errors as this is not needed for * these drives. * This is kept for older drives which had needed * us to issue close_track to flush the cache fully. * once we are certain these drives have cleared the * market, this can be removed. */ if (device_type == DVD_MINUS) { return (0); } } else { if (!immediate) return (1); } if (immediate) { (void) sleep(10); di = (uchar_t *)my_zalloc(DISC_INFO_BLOCK_SIZE); err = 0; if (device_type == CD_RW) { /* Finalization should not take more than 6 minutes */ finalize_max = FINALIZE_TIMEOUT; } else { /* some DVD-RW drives take longer than 6 minutes */ finalize_max = FINALIZE_TIMEOUT*2; } for (count = 0; count < finalize_max; count++) { ret = read_disc_info(dev->d_fd, di); if (ret != 0) break; if (uscsi_status != 2) err = 1; if (SENSE_KEY(rqbuf) == 2) { /* not ready but not becoming ready */ if (ASC(rqbuf) != 4) err = 1; } else if (SENSE_KEY(rqbuf) == 5) { /* illegal mode for this track */ if (ASC(rqbuf) != 0x64) err = 1; } else { err = 1; } if (err == 1) { if (debug) { (void) printf("Finalization failed\n"); (void) printf("%x %x %x %x\n", uscsi_status, SENSE_KEY(rqbuf), ASC(rqbuf), ASCQ(rqbuf)); } free(di); return (0); } if (uscsi_status == 2) { int i; /* illegal field in command packet */ if (ASC(rqbuf) == 0x24) { /* print it out! */ (void) printf("\n"); for (i = 0; i < 18; i++) (void) printf("%x ", (unsigned)(rqbuf[i])); (void) printf("\n"); } } (void) sleep(5); } free(di); } return (ret); }
static void info_scsi_cmd_err(struct udev *udev, const char *cmd, int err) { if (err == -1) { log_debug("%s failed", cmd); return; } log_debug("%s failed with SK=%Xh/ASC=%02Xh/ACQ=%02Xh", cmd, SK(err), ASC(err), ASCQ(err)); }
int uscsi(int fd, struct uscsi_cmd *scmd) { char rqbuf[RQLEN]; int ret; int i, retries, total_retries; int max_retries = 20; scmd->uscsi_flags |= USCSI_RQENABLE; scmd->uscsi_rqlen = RQLEN; scmd->uscsi_rqbuf = rqbuf; for (retries = 0; retries < max_retries; retries++) { scmd->uscsi_status = 0; memset(rqbuf, 0, RQLEN); ret = ioctl(fd, USCSICMD, scmd); if ((ret == 0) && (scmd->uscsi_status == 2)) { ret = -1; errno = EIO; } if ((ret < 0) && (scmd->uscsi_status == 2)) { /* * The drive is not ready to recieve commands but * may be in the process of becoming ready. * sleep for a short time then retry command. * SENSE/ASC = 2/4 : not ready * ASCQ = 0 Not Reportable. * ASCQ = 1 Becoming ready. * ASCQ = 4 FORMAT in progress. * ASCQ = 7 Operation in progress. */ if ((SENSE_KEY(rqbuf) == 2) && (ASC(rqbuf) == 4) && ((ASCQ(rqbuf) == 0) || (ASCQ(rqbuf) == 1) || (ASCQ(rqbuf) == 4)) || (ASCQ(rqbuf) == 7)) { total_retries++; sleep(1); continue; } /* * Device is not ready to transmit or a device reset * has occurred. wait for a short period of time then * retry the command. */ if ((SENSE_KEY(rqbuf) == 6) && ((ASC(rqbuf) == 0x28) || (ASC(rqbuf) == 0x29))) { sleep(1); total_retries++; continue; } /* * Blank Sense, we don't know what the error is or if * the command succeeded, Hope for the best. Some * drives return blank sense periodically and will * fail if this is removed. */ if ((SENSE_KEY(rqbuf) == 0) && (ASC(rqbuf) == 0) && (ASCQ(rqbuf) == 0)) { ret = 0; break; } HAL_DEBUG (("cmd: 0x%02x ret:%i status:%02x " " sense: %02x ASC: %02x ASCQ:%02x\n", (uchar_t)scmd->uscsi_cdb[0], ret, scmd->uscsi_status, (uchar_t)SENSE_KEY(rqbuf), (uchar_t)ASC(rqbuf), (uchar_t)ASCQ(rqbuf))); } break; } if (retries) { HAL_DEBUG (("total retries: %d\n", total_retries)); } return (ret); }