extractedLnx/linux-2.6.9/drivers/s390/char/tape_34xx.c_tape_34xx_unit_check.c
static int
tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
struct irb *irb)
{
int inhibit_cu_recovery;
__u8* sense;
inhibit_cu_recovery = (*device->modeset_byte & 0x80) ? 1 : 0;
sense = irb->ecw;
#ifdef CONFIG_S390_TAPE_BLOCK
if (request->op == TO_BLOCK) {
/*
* Recovery for block device requests. Set the block_position
* to something invalid and retry.
*/
device->blk_data.block_position = -1;
if (request->retries-- <= 0)
return tape_34xx_erp_failed(request, -EIO);
else
return tape_34xx_erp_retry(request);
}
#endif
if (
sense[0] & SENSE_COMMAND_REJECT &&
sense[1] & SENSE_WRITE_PROTECT
) {
if (
request->op == TO_DSE ||
request->op == TO_WRI ||
request->op == TO_WTM
) {
/* medium is write protected */
return tape_34xx_erp_failed(request, -EACCES);
} else {
return tape_34xx_erp_bug(device, request, irb, -3);
}
}
/*
* Special cases for various tape-states when reaching
* end of recorded area
*
* FIXME: Maybe a special case of the special case:
* sense[0] == SENSE_EQUIPMENT_CHECK &&
* sense[1] == SENSE_DRIVE_ONLINE &&
* sense[3] == 0x47 (Volume Fenced)
*
* This was caused by continued FSF or FSR after an
* 'End Of Data'.
*/
if ((
sense[0] == SENSE_DATA_CHECK ||
sense[0] == SENSE_EQUIPMENT_CHECK ||
sense[0] == SENSE_EQUIPMENT_CHECK + SENSE_DEFERRED_UNIT_CHECK
) && (
sense[1] == SENSE_DRIVE_ONLINE ||
sense[1] == SENSE_BEGINNING_OF_TAPE + SENSE_WRITE_MODE
)) {
switch (request->op) {
/*
* sense[0] == SENSE_DATA_CHECK &&
* sense[1] == SENSE_DRIVE_ONLINE
* sense[3] == 0x36 (End Of Data)
*
* Further seeks might return a 'Volume Fenced'.
*/
case TO_FSF:
case TO_FSB:
/* Trying to seek beyond end of recorded area */
return tape_34xx_erp_failed(request, -ENOSPC);
case TO_BSB:
return tape_34xx_erp_retry(request);
/*
* sense[0] == SENSE_DATA_CHECK &&
* sense[1] == SENSE_DRIVE_ONLINE &&
* sense[3] == 0x36 (End Of Data)
*/
case TO_LBL:
/* Block could not be located. */
tape_34xx_delete_sbid_from(device, 0);
return tape_34xx_erp_failed(request, -EIO);
case TO_RFO:
/* Read beyond end of recorded area -> 0 bytes read */
return tape_34xx_erp_failed(request, 0);
/*
* sense[0] == SENSE_EQUIPMENT_CHECK &&
* sense[1] == SENSE_DRIVE_ONLINE &&
* sense[3] == 0x38 (Physical End Of Volume)
*/
case TO_WRI:
/* Writing at physical end of volume */
return tape_34xx_erp_failed(request, -ENOSPC);
default:
PRINT_ERR("Invalid op in %s:%i\n",
__FUNCTION__, __LINE__);
return tape_34xx_erp_failed(request, 0);
}
}
/* Sensing special bits */
if (sense[0] & SENSE_BUS_OUT_CHECK)
return tape_34xx_erp_retry(request);
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.
return tape_34xx_erp_bug(device, request,
irb, -4);
/* data check is permanent, CU recovery has failed */
PRINT_WARN("Permanent read error\n");
return tape_34xx_erp_failed(request, -EIO);
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.
return tape_34xx_erp_bug(device, request,
irb, -5);
// data check is permanent, cu-recovery has failed
PRINT_WARN("Permanent write error\n");
return tape_34xx_erp_failed(request, -EIO);
case 0x26:
/* Data Check (read opposite) occurred. */
return tape_34xx_erp_read_opposite(device, request);
case 0x28:
/* ID-Mark at tape start couldn't be written */
PRINT_WARN("ID-Mark could not be written.\n");
return tape_34xx_erp_failed(request, -EIO);
case 0x31:
/* Tape void. Tried to read beyond end of device. */
PRINT_WARN("Read beyond end of recorded area.\n");
return tape_34xx_erp_failed(request, -ENOSPC);
case 0x41:
/* Record sequence error. */
PRINT_WARN("Invalid block-id sequence found.\n");
return tape_34xx_erp_failed(request, -EIO);
default:
/* all data checks for 3480 should result in one of
* the above erpa-codes. For 3490, other data-check
* conditions do exist. */
if (device->cdev->id.driver_info == tape_3480)
return tape_34xx_erp_bug(device, request,
irb, -6);
}
}
if (sense[0] & SENSE_OVERRUN)
return tape_34xx_erp_overrun(device, request, irb);
if (sense[1] & SENSE_RECORD_SEQUENCE_ERR)
return tape_34xx_erp_sequence(device, request, irb);
/* Sensing erpa codes */
switch (sense[3]) {
case 0x00:
/* Unit check with erpa code 0. Report and ignore. */
PRINT_WARN("Non-error sense was found. "
"Unit-check will be ignored.\n");
return TAPE_IO_SUCCESS;
case 0x21:
/*
* Data streaming not operational. CU will switch to
* interlock mode. Reissue the command.
*/
PRINT_WARN("Data streaming not operational. "
"Switching to interlock-mode.\n");
return tape_34xx_erp_retry(request);
case 0x22:
/*
* Path equipment check. Might be drive adapter error, buffer
* error on the lower interface, internal path not usable,
* or error during cartridge load.
*/
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 usable, error "
"during cartridge load.\n");
return tape_34xx_erp_failed(request, -EIO);
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".
*/
return tape_34xx_erp_succeeded(request);
case 0x27:
/*
* Command reject. May indicate illegal channel program or
* buffer over/underrun. Since all channel programs are
* issued by this driver and ought be correct, we assume a
* over/underrun situation and retry the channel program.
*/
return tape_34xx_erp_retry(request);
case 0x29:
/*
* Function incompatible. Either the tape is idrc compressed
* but the hardware isn't capable to do idrc, or a perform
* subsystem func is issued and the CU is not on-line.
*/
PRINT_WARN ("Function incompatible. Try to switch off idrc\n");
return tape_34xx_erp_failed(request, -EIO);
case 0x2a:
/*
* Unsolicited environmental data. An internal counter
* overflows, we can ignore this and reissue the cmd.
*/
return tape_34xx_erp_retry(request);
case 0x2b:
/*
* Environmental data present. Indicates either unload
* completed ok or read buffered log command completed ok.
*/
if (request->op == TO_RUN) {
/* Rewind unload completed ok. */
tape_med_state_set(device, MS_UNLOADED);
return tape_34xx_erp_succeeded(request);
}
/* tape_34xx doesn't use read buffered log commands. */
return tape_34xx_erp_bug(device, request, irb, sense[3]);
case 0x2c:
/*
* Permanent equipment check. CU has tried recovery, but
* did not succeed.
*/
return tape_34xx_erp_failed(request, -EIO);
case 0x2d:
/* Data security erase failure. */
if (request->op == TO_DSE)
return tape_34xx_erp_failed(request, -EIO);
/* Data security erase failure, but no such command issued. */
return tape_34xx_erp_bug(device, request, irb, sense[3]);
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.
*/
PRINT_WARN("Drive not capable processing the tape format!\n");
return tape_34xx_erp_failed(request, -EMEDIUMTYPE);
case 0x30:
/* The medium is write protected. */
PRINT_WARN("Medium is write protected!\n");
return tape_34xx_erp_failed(request, -EACCES);
case 0x32:
// Tension loss. We cannot recover this, it's an I/O error.
PRINT_WARN("The drive lost tape tension.\n");
return tape_34xx_erp_failed(request, -EIO);
case 0x33:
/*
* Load Failure. The cartridge was not inserted correctly or
* the tape is not threaded correctly.
*/
PRINT_WARN("Cartridge load failure. Reload the cartridge "
"and try again.\n");
tape_34xx_delete_sbid_from(device, 0);
return tape_34xx_erp_failed(request, -EIO);
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 (request->op == TO_RUN)
return tape_34xx_erp_failed(request, -EIO);
return tape_34xx_erp_bug(device, request, irb, sense[3]);
case 0x35:
/*
* Drive equipment check. One of the following:
* - cu cannot recover from a drive detected error
* - a check code message is shown on drive display
* - 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");
return tape_34xx_erp_failed(request, -EIO);
case 0x36:
if (device->cdev->id.driver_info == tape_3490)
/* End of data. */
return tape_34xx_erp_failed(request, -EIO);
/* This erpa is reserved for 3480 */
return tape_34xx_erp_bug(device, request, irb, sense[3]);
case 0x37:
/*
* Tape length error. The tape is shorter than reported in
* the beginning-of-tape data.
*/
PRINT_WARN("Tape length error.\n");
return tape_34xx_erp_failed(request, -EIO);
case 0x38:
/*
* Physical end of tape. A read/write operation reached
* the physical end of tape.
*/
if (request->op==TO_WRI ||
request->op==TO_DSE ||
request->op==TO_WTM)
return tape_34xx_erp_failed(request, -ENOSPC);
return tape_34xx_erp_failed(request, -EIO);
case 0x39:
/* Backward at Beginning of tape. */
return tape_34xx_erp_failed(request, -EIO);
case 0x3a:
/* Drive switched to not ready. */
PRINT_WARN("Drive not ready. Turn the ready/not ready switch "
"to ready position and try again.\n");
return tape_34xx_erp_failed(request, -EIO);
case 0x3b:
/* Manual rewind or unload. This causes an I/O error. */
PRINT_WARN("Medium was rewound or unloaded manually.\n");
tape_34xx_delete_sbid_from(device, 0);
return tape_34xx_erp_failed(request, -EIO);
case 0x42:
/*
* Degraded mode. A condition that can cause degraded
* performance is detected.
*/
PRINT_WARN("Subsystem is running in degraded mode.\n");
return tape_34xx_erp_retry(request);
case 0x43:
/* Drive not ready. */
tape_34xx_delete_sbid_from(device, 0);
tape_med_state_set(device, MS_UNLOADED);
/* Some commands commands are successful even in this case */
if (sense[1] & SENSE_DRIVE_ONLINE) {
switch(request->op) {
case TO_ASSIGN:
case TO_UNASSIGN:
case TO_DIS:
case TO_NOP:
return tape_34xx_done(request);
break;
default:
break;
}
}
PRINT_WARN("The drive is not ready.\n");
return tape_34xx_erp_failed(request, -ENOMEDIUM);
case 0x44:
/* Locate Block unsuccessful. */
if (request->op != TO_BLOCK && request->op != TO_LBL)
/* No locate block was issued. */
return tape_34xx_erp_bug(device, request,
irb, sense[3]);
return tape_34xx_erp_failed(request, -EIO);
case 0x45:
/* The drive is assigned to a different channel path. */
PRINT_WARN("The drive is assigned elsewhere.\n");
return tape_34xx_erp_failed(request, -EIO);
case 0x46:
/*
* Drive not on-line. 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 on-line.");
return tape_34xx_erp_failed(request, -EIO);
case 0x47:
/* Volume fenced. CU reports volume integrity is lost. */
PRINT_WARN("Volume fenced. The volume integrity is lost.\n");
tape_34xx_delete_sbid_from(device, 0);
return tape_34xx_erp_failed(request, -EIO);
case 0x48:
/* Log sense data and retry request. */
return tape_34xx_erp_retry(request);
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 "
"has been corrupted.\n");
return tape_34xx_erp_failed(request, -EIO);
case 0x4a:
/* Control unit erp failed. */
PRINT_WARN("The control unit I/O error recovery failed.\n");
return tape_34xx_erp_failed(request, -EIO);
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");
return tape_34xx_erp_failed(request, -EIO);
case 0x4c:
/*
* Recovered Check-One failure. Cu develops a hardware error,
* but is able to recover.
*/
return tape_34xx_erp_retry(request);
case 0x4d:
if (device->cdev->id.driver_info == tape_3490)
/*
* Resetting event received. Since the driver does
* not support resetting event recovery (which has to
* be handled by the I/O Layer), retry our command.
*/
return tape_34xx_erp_retry(request);
/* This erpa is reserved for 3480. */
return tape_34xx_erp_bug(device, request, irb, sense[3]);
case 0x4e:
if (device->cdev->id.driver_info == tape_3490) {
/*
* Maximum block size exceeded. This indicates, that
* the block to be written is larger than allowed for
* buffered mode.
*/
PRINT_WARN("Maximum block size for buffered "
"mode exceeded.\n");
return tape_34xx_erp_failed(request, -ENOBUFS);
}
/* This erpa is reserved for 3480. */
return tape_34xx_erp_bug(device, request, irb, sense[3]);
case 0x50:
/*
* Read buffered log (Overflow). CU is running in extended
* buffered log mode, and a counter overflows. This should
* never happen, since we're never running in extended
* buffered log mode.
*/
return tape_34xx_erp_retry(request);
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.
*/
return tape_34xx_erp_retry(request);
case 0x52:
/* End of Volume complete. Rewind unload completed ok. */
if (request->op == TO_RUN) {
tape_med_state_set(device, MS_UNLOADED);
tape_34xx_delete_sbid_from(device, 0);
return tape_34xx_erp_succeeded(request);
}
return tape_34xx_erp_bug(device, request, irb, sense[3]);
case 0x53:
/* Global command intercept. */
return tape_34xx_erp_retry(request);
case 0x54:
/* Channel interface recovery (temporary). */
return tape_34xx_erp_retry(request);
case 0x55:
/* Channel interface recovery (permanent). */
PRINT_WARN("A permanent channel interface error occurred.\n");
return tape_34xx_erp_failed(request, -EIO);
case 0x56:
/* Channel protocol error. */
PRINT_WARN("A channel protocol error occurred.\n");
return tape_34xx_erp_failed(request, -EIO);
case 0x57:
if (device->cdev->id.driver_info == tape_3480) {
/* Attention intercept. */
PRINT_WARN("An attention intercept occurred, "
"which will be recovered.\n");
return tape_34xx_erp_retry(request);
} else {
/* Global status intercept. */
PRINT_WARN("An global status intercept was received, "
"which will be recovered.\n");
return tape_34xx_erp_retry(request);
}
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\n");
PRINT_WARN("Tape length exceeds IBM enhanced capacity "
"cartdridge length or a medium\n");
PRINT_WARN("with EC-CST identification mark has been mounted "
"in a device that writes\n");
PRINT_WARN("3480 or 3480 XF format.\n");
return tape_34xx_erp_failed(request, -EIO);
case 0x5b:
/* Format 3480 XF incompatible */
if (sense[1] & SENSE_BEGINNING_OF_TAPE)
/* The tape will get overwritten. */
return tape_34xx_erp_retry(request);
PRINT_WARN("Format 3480 XF Incompatible\n");
PRINT_WARN("Medium has been created in 3480 format. "
"To change the format writes\n");
PRINT_WARN("must be issued at BOT.\n");
return tape_34xx_erp_failed(request, -EIO);
case 0x5c:
/* Format 3480-2 XF incompatible */
PRINT_WARN("Format 3480-2 XF Incompatible\n");
PRINT_WARN("Device can only read 3480 or 3480 XF format.\n");
return tape_34xx_erp_failed(request, -EIO);
case 0x5d:
/* Tape length violation. */
PRINT_WARN("Tape Length Violation\n");
PRINT_WARN("The mounted tape exceeds IBM Enhanced Capacity "
"Cartdridge System Tape length.\n");
PRINT_WARN("This may cause damage to the drive or tape when "
"processing to the EOV\n");
return tape_34xx_erp_failed(request, -EMEDIUMTYPE);
case 0x5e:
/* Compaction algorithm incompatible. */
PRINT_WARN("Compaction Algorithm Incompatible\n");
PRINT_WARN("The volume is recorded using an incompatible "
"compaction algorithm,\n");
PRINT_WARN("which is not supported by the device.\n");
return tape_34xx_erp_failed(request, -EMEDIUMTYPE);
/* The following erpas should have been covered earlier. */
case 0x23: /* Read data check. */
case 0x25: /* Write data check. */
case 0x26: /* Data check (read opposite). */
case 0x28: /* Write id mark check. */
case 0x31: /* Tape void. */
case 0x40: /* Overrun error. */
case 0x41: /* Record sequence error. */
/* All other erpas are reserved for future use. */
default:
return tape_34xx_erp_bug(device, request, irb, sense[3]);
}
}
Generated by GNU enscript 1.6.4.