extractedLnx/linux-2.5.9/drivers/s390/char/tape34xx.c_tape34xx_error_recovery.c
void
tape34xx_error_recovery (tape_info_t* ti)
{
__u8* sense=ti->devstat.ii.sense.data;
int inhibit_cu_recovery=0;
int cu_type=ti->discipline->cu_type;
if ((((tape34xx_disc_data_t *) ti->discdata)->modeset_byte)&0x80) inhibit_cu_recovery=1;
if (tapestate_get(ti)==TS_BLOCK_INIT) {
// no recovery for block device, bottom half will retry...
tape34xx_error_recovery_has_failed(ti,EIO);
return;
}
if (sense[0]&SENSE_COMMAND_REJECT)
switch (tapestate_get(ti)) {
case TS_BLOCK_INIT:
case TS_DSE_INIT:
case TS_EGA_INIT:
case TS_WRI_INIT:
case TS_WTM_INIT:
if (sense[1]&SENSE_WRITE_PROTECT) {
// trying to write, but medium is write protected
tape34xx_error_recovery_has_failed(ti,EACCES);
return;
}
default:
tape34xx_error_recovery_HWBUG(ti,1);
return;
}
// special cases for various tape-states when reaching end of recorded area
if (((sense[0]==0x08) || (sense[0]==0x10) || (sense[0]==0x12)) &&
((sense[1]==0x40) || (sense[1]==0x0c)))
switch (tapestate_get(ti)) {
case TS_FSF_INIT:
// Trying to seek beyond end of recorded area
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case TS_LBL_INIT:
// Block could not be located.
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case TS_RFO_INIT:
// Try to read beyond end of recorded area -> 0 bytes read
tape34xx_error_recovery_has_failed(ti,0);
return;
}
// Sensing special bits
if (sense[0]&SENSE_BUS_OUT_CHECK) {
tape34xx_error_recovery_do_retry(ti);
return;
}
if (sense[0]&SENSE_DATA_CHECK) {
// hardware failure, damaged tape or improper operating conditions
switch (sense[3]) {
case 0x23:
// a read data check occurred
if ((sense[2]&SENSE_TAPE_SYNC_MODE) ||
(inhibit_cu_recovery)) {
// data check is not permanent, may be recovered.
// We always use async-mode with cu-recovery, so this should *never* happen.
tape34xx_error_recovery_HWBUG(ti,2);
return;
} else {
// data check is permanent, CU recovery has failed
PRINT_WARN("Permanent read error, recovery failed!\n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
}
case 0x25:
// a write data check occurred
if ((sense[2]&SENSE_TAPE_SYNC_MODE) ||
(inhibit_cu_recovery)) {
// data check is not permanent, may be recovered.
// We always use async-mode with cu-recovery, so this should *never* happen.
tape34xx_error_recovery_HWBUG(ti,3);
return;
} else {
// data check is permanent, cu-recovery has failed
PRINT_WARN("Permanent write error, recovery failed!\n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
}
case 0x26:
// Data Check (read opposite) occurred. We'll recover this.
tape34xx_error_recovery_read_opposite(ti);
return;
case 0x28:
// The ID-Mark at the beginning of the tape could not be written. This is fatal, we'll report and exit.
PRINT_WARN("ID-Mark could not be written. Check your hardware!\n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x31:
// Tape void. Tried to read beyond end of device. We'll report and exit.
PRINT_WARN("Try to read beyond end of recorded area!\n");
tape34xx_error_recovery_has_failed(ti,ENOSPC);
return;
case 0x41:
// Record sequence error. cu detected incorrect block-id sequence on tape. We'll report and exit.
PRINT_WARN("Illegal block-id sequence found!\n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
default:
// well, all data checks for 3480 should result in one of the above erpa-codes. if not -> bug
// On 3490, other data-check conditions do exist.
if (cu_type==0x3480) {
tape34xx_error_recovery_HWBUG(ti,4);
return;
}
}
}
if (sense[0]&SENSE_OVERRUN) {
// A data overrun between cu and drive occurred. The channel speed is to slow! We'll report this and exit!
switch (sense[3]) {
case 0x40: // overrun error
PRINT_WARN ("Data overrun error between control-unit and drive. Use a faster channel connection, if possible! \n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
default:
// Overrun bit is set, but erpa does not show overrun error. This is a bug.
tape34xx_error_recovery_HWBUG(ti,5);
return;
}
}
if (sense[1]&SENSE_RECORD_SEQUENCE_ERR) {
switch (sense[3]) {
case 0x41:
// Record sequence error. cu detected incorrect block-id sequence on tape. We'll report and exit.
PRINT_WARN("Illegal block-id sequence found!\n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
default:
// Record sequence error bit is set, but erpa does not show record sequence error. This is a bug.
tape34xx_error_recovery_HWBUG(ti,6);
return;
}
}
// Sensing erpa codes
switch (sense[3]) {
case 0x00:
// Everything is fine, but we got a unit check. Report and ignore!
PRINT_WARN ("Non-error sense was found. Unit-check will be ignored, expect errors...\n");
return;
case 0x21:
// Data streaming not operational. Cu switches to interlock mode, we reissue the command.
PRINT_WARN ("Data streaming not operational. Switching to interlock-mode! \n");
tape34xx_error_recovery_do_retry(ti);
return;
case 0x22:
// Path equipment check. Might be drive adapter error, buffer error on the lower interface, internal path not useable, or error during cartridge load.
// All of the above are not recoverable
PRINT_WARN ("A path equipment check occurred. One of the following conditions occurred:\n");
PRINT_WARN ("drive adapter error,buffer error on the lower interface, internal path not useable, error during cartridge load.\n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x23:
// Read data check. Should have been be covered earlier -> Bug!
tape34xx_error_recovery_HWBUG(ti,7);
return;
case 0x24:
// Load display check. Load display was command was issued, but the drive is displaying a drive check message. Can be threated as "device end".
tape34xx_error_recovery_succeded(ti);
return;
case 0x25:
// Write data check. Should have been covered earlier -> Bug!
tape34xx_error_recovery_HWBUG(ti,8);
return;
case 0x26:
// Data check (read opposite). Should have been covered earlier -> Bug!
tape34xx_error_recovery_HWBUG(ti,9);
return;
case 0x27:
// Command reject. May indicate illegal channel program or buffer over/underrun.
// Since all channel programms are issued by this driver and ought be correct,
// we assume a over/underrun situaltion and retry the channel program.
tape34xx_error_recovery_do_retry(ti);
return;
case 0x28:
// Write id mark check. Should have beed covered earlier -> bug!
tape34xx_error_recovery_HWBUG(ti,10);
return;
case 0x29:
// Function incompatible. Either idrc is on but hardware not capable doing idrc
// or a perform subsystem func is issued and the cu is not online. Anyway, this
// cannot be recovered and is an I/O error.
PRINT_WARN ("Function incompatible. Try to switch off idrc! \n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x2a:
// Unsolicited environmental data. An internal counter overflows, we can ignore
// this and reissue the cmd.
tape34xx_error_recovery_do_retry(ti);
return;
case 0x2b:
// Environmental data present. Indicates either unload completed ok or read buffered
// log command completed ok.
if (tapestate_get(ti)==TS_RUN_INIT) {
// Rewind unload completed ok.
tape34xx_error_recovery_succeded(ti);
return;
}
// Since we do not issue read buffered log commands, this should never occur -> bug.
tape34xx_error_recovery_HWBUG(ti,11);
return;
case 0x2c:
// Permanent equipment check. cu has tried recovery, but did not succeed. This is an
// I/O error.
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x2d:
// Data security erase failure.
if (tapestate_get(ti)==TS_DSE_INIT) {
// report an I/O error
tape34xx_error_recovery_has_failed(ti,EIO);
return;
}
// Data security erase failure, but no such command issued. This is a bug.
tape34xx_error_recovery_HWBUG(ti,12);
return;
case 0x2e:
// Not capable. This indicates either that the drive fails reading the format id mark
// or that that format specified is not supported by the drive. We write a message and
// return an I/O error.
PRINT_WARN("Drive not capable processing the tape format!");
tape34xx_error_recovery_has_failed(ti,EMEDIUMTYPE);
return;
case 0x2f:
// This erpa is reserved. This is a bug.
tape34xx_error_recovery_HWBUG(ti,13);
return;
case 0x30:
// The medium is write protected, while trying to write on it. We'll report this.
PRINT_WARN("Medium is write protected!\n");
tape34xx_error_recovery_has_failed(ti,EACCES);
return;
case 0x31:
// Tape void. Should have beed covered ealier -> bug
tape34xx_error_recovery_HWBUG(ti,14);
return;
case 0x32:
// Tension loss. We cannot recover this, it's an I/O error.
PRINT_WARN("The drive lost tape tension.\n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x33:
// Load Failure. The catridge was not inserted correctly or the tape is not threaded
// correctly. We cannot recover this, the user has to reload the catridge.
PRINT_WARN("Cartridge load failure. Reload the cartridge and try again.\n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x34:
// Unload failure. The drive cannot maintain tape tension and control tape movement
// during an unload operation.
PRINT_WARN("Failure during cartridge unload. Please try manually.\n");
if (tapestate_get(ti)!=TS_RUN_INIT) {
tape34xx_error_recovery_HWBUG(ti,15);
return;
}
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x35:
// Drive equipment check. One of the following:
// - cu cannot recover from a drive detected error
// - a check code message is displayed on drive message/load displays
// - the cartridge loader does not respond correctly
// - a failure occurs during an index, load, or unload cycle
PRINT_WARN("Equipment check! Please check the drive and the cartridge loader.\n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x36:
switch (cu_type) {
case 0x3480:
// This erpa is reserved for 3480 -> BUG
tape34xx_error_recovery_HWBUG(ti,16);
return;
case 0x3490:
// End of data. This is a permanent I/O error, which cannot be recovered.
// A read-type command has reached the end-of-data mark.
tape34xx_error_recovery_has_failed(ti,EIO);
return;
}
case 0x37:
// Tape length error. The tape is shorter than reported in the beginning-of-tape data.
PRINT_WARN("Tape length error.\n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x38:
// Physical end of tape. A read/write operation reached the physical end of tape.
if (tapestate_get(ti)==TS_WRI_INIT ||
tapestate_get(ti)==TS_DSE_INIT ||
tapestate_get(ti)==TS_EGA_INIT ||
tapestate_get(ti)==TS_WTM_INIT){
tape34xx_error_recovery_has_failed(ti,ENOSPC);
} else {
tape34xx_error_recovery_has_failed(ti,EIO);
}
return;
case 0x39:
// Backward at BOT. The drive is at BOT and is requestet to move backward.
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x3a:
// Drive switched not ready, but the command needs the drive to be ready.
PRINT_WARN("Drive not ready. Turn the ready/not ready switch to ready position and try again.\n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x3b:
// Manual rewind or unload. This causes an I/O error.
PRINT_WARN("Medium was rewound or unloaded manually. Expect errors! Please do only use the mtoffl and mtrew ioctl to unload tapes or rewind tapes.\n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x3c:
case 0x3d:
case 0x3e:
case 0x3f:
// These erpas are reserved -> BUG
tape34xx_error_recovery_HWBUG(ti,17);
return;
case 0x40:
// Overrun error. This should have been covered earlier -> bug.
tape34xx_error_recovery_HWBUG(ti,18);
return;
case 0x41:
// Record sequence error. This should have been covered earlier -> bug.
tape34xx_error_recovery_HWBUG(ti,19);
return;
case 0x42:
// Degraded mode. A condition that can cause degraded performace is detected.
PRINT_WARN("Subsystem is running in degraded mode. This may compromise your performace.\n");
tape34xx_error_recovery_do_retry(ti);
return;
case 0x43:
// Drive not ready. Probably swith the ready/not ready switch to ready?
PRINT_WARN("The drive is not ready. Maybe no medium in?\n");
tape34xx_error_recovery_has_failed(ti,ENOMEDIUM);
return;
case 0x44:
// Locate Block unsuccessfull. We'll report this.
if ((tapestate_get(ti)!=TS_BLOCK_INIT) &&
(tapestate_get(ti)!=TS_LBL_INIT)) {
tape34xx_error_recovery_HWBUG(ti,20); // No locate block was issued...
return;
}
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x45:
// The drive is assigned elsewhere [to a different channel path/computer].
PRINT_WARN("The drive is assigned elsewhere.\n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x46:
// Drive not online. Drive may be switched offline, the power supply may be switched off
// or the drive address may not be set correctly.
PRINT_WARN("The drive is not online.");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x47:
// Volume fenced. cu reports volume integrity is lost!
PRINT_WARN("Volume fenced. The volume integrity is lost! \n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x48:
// Log sense data and retry request. We'll do so...
tape34xx_error_recovery_do_retry(ti);
return;
case 0x49:
// Bus out check. A parity check error on the bus was found. PRINT_WARN("Bus out check. A data transfer over the bus was corrupted.\n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x4a:
// Control unit erp failed. We'll report this.
PRINT_WARN("The control unit failed recovering an I/O error.\n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x4b:
// Cu and drive incompatible. The drive requests micro-program patches, which are not available on the cu.
PRINT_WARN("The drive needs microprogram patches from the control unit, which are not available.\n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x4c:
// Recovered Check-One failure. Cu develops a hardware error, but is able to recover. We'll reissue the command.
tape34xx_error_recovery_do_retry(ti);
return;
case 0x4d:
switch (cu_type) {
case 0x3480:
// This erpa is reserved for 3480 -> bug
tape34xx_error_recovery_HWBUG(ti,21);
return;
case 0x3490:
// Resetting event received. Since the driver does not support resetting event recovery
// (which has to be handled by the I/O Layer), we'll report and retry our command.
tape34xx_error_recovery_do_retry(ti);
return;
}
case 0x4e:
switch (cu_type) {
case 0x3480:
// This erpa is reserved for 3480 -> bug.
tape34xx_error_recovery_HWBUG(ti,22);
return;
case 0x3490:
// Maximum block size exeeded. This indicates, that the block to be written is larger
// than allowed for buffered mode. We'll report this...
PRINT_WARN("Maximum block size for buffered mode exceeded.\n");
tape34xx_error_recovery_has_failed(ti,ENOBUFS);
return;
}
case 0x4f:
// These erpas are reserved -> bug
tape34xx_error_recovery_HWBUG(ti,23);
return;
case 0x50:
// Read buffered log (Overflow). Cu is running in extended beffered log mode, and a counter overflows.
// This should never happen, since we're never running in extended buffered log mode -> bug.
tape34xx_error_recovery_do_retry(ti);
return;
case 0x51:
// Read buffered log (EOV). EOF processing occurs while the cu is in extended buffered log mode.
// This should never happen, since we're never running in extended buffered log mode -> bug.
tape34xx_error_recovery_do_retry(ti);
return;
case 0x52:
// End of Volume complete. Rewind unload completed ok. We'll report to the user...
if (tapestate_get(ti)!=TS_RUN_INIT) {
tape34xx_error_recovery_HWBUG(ti,24);
return;
}
tape34xx_error_recovery_succeded(ti);
return;
case 0x53:
// Global command intercept. We'll have to reissue our command.
tape34xx_error_recovery_do_retry(ti);
return;
case 0x54:
// Channel interface recovery (temporary). This can be recovered by reissuing the command.
tape34xx_error_recovery_do_retry(ti);
return;
case 0x55:
// Channel interface recovery (permanent). This cannot be recovered, we'll inform the user.
PRINT_WARN("A permanent channel interface error occurred.\n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x56:
// Channel protocol error. This cannot be recovered.
PRINT_WARN("A channel protocol error occurred.\n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x57:
switch (cu_type) {
case 0x3480:
// Attention intercept. We have to reissue the command.
PRINT_WARN("An attention intercept occurred, which will be recovered.\n");
tape34xx_error_recovery_do_retry(ti);
return;
case 0x3490:
// Global status intercept. We have to reissue the command.
PRINT_WARN("An global status intercept was received, which will be recovered.\n");
tape34xx_error_recovery_do_retry(ti);
return;
}
case 0x58:
case 0x59:
// These erpas are reserved -> bug.
tape34xx_error_recovery_HWBUG(ti,25);
return;
case 0x5a:
// Tape length incompatible. The tape inserted is too long,
// which could cause damage to the tape or the drive.
PRINT_WARN("Tape length incompatible [should be IBM Cartridge System Tape]. May cause damage to drive or tape.n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x5b:
// Format 3480 XF incompatible
if (sense[1]&SENSE_BEGINNING_OF_TAPE) {
// Everything is fine. The tape will be overwritten in a different format.
tape34xx_error_recovery_do_retry(ti);
return;
}
PRINT_WARN("Tape format is incompatible to the drive, which writes 3480-2 XF.\n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x5c:
// Format 3480-2 XF incompatible
PRINT_WARN("Tape format is incompatible to the drive. The drive cannot access 3480-2 XF volumes.\n");
tape34xx_error_recovery_has_failed(ti,EIO);
return;
case 0x5d:
// Tape length violation.
PRINT_WARN("Tape length violation [should be IBM Enhanced Capacity Cartridge System Tape]. May cause damage to drive or tape.\n");
tape34xx_error_recovery_has_failed(ti,EMEDIUMTYPE);
return;
case 0x5e:
// Compaction algorithm incompatible.
PRINT_WARN("The volume is recorded using an incompatible compaction algorith, which is not supported by the control unit.\n");
tape34xx_error_recovery_has_failed(ti,EMEDIUMTYPE);
return;
default:
// Reserved erpas -> bug
tape34xx_error_recovery_HWBUG(ti,26);
return;
}
}
Generated by GNU enscript 1.6.4.