Enscript Output

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.