patch-2.4.4 linux/drivers/s390/char/tape34xx.c
Next file: linux/drivers/s390/char/tape34xx.h
Previous file: linux/drivers/s390/char/tape3490.h
Back to the patch index
Back to the overall index
- Lines: 1104
- Date:
Wed Apr 11 19:02:28 2001
- Orig file:
v2.4.3/linux/drivers/s390/char/tape34xx.c
- Orig date:
Fri Mar 2 11:12:07 2001
diff -u --recursive --new-file v2.4.3/linux/drivers/s390/char/tape34xx.c linux/drivers/s390/char/tape34xx.c
@@ -3,12 +3,11 @@
* drivers/s390/char/tape34xx.c
* common tape device discipline for 34xx tapes.
*
- * S390 version
- * Copyright (C) 2000 IBM Corporation
- * Author(s): Tuan Ngo-Anh <ngoanh@de.ibm.com>
- * Carsten Otte <cotte@de.ibm.com>
+ * S390 and zSeries version
+ * Copyright (C) 2001 IBM Corporation
+ * Author(s): Carsten Otte <cotte@de.ibm.com>
+ * Tuan Ngo-Anh <ngoanh@de.ibm.com>
*
- * UNDER CONSTRUCTION: Work in progress...:-)
****************************************************************************
*/
@@ -36,19 +35,19 @@
tape_event_handler_t tape34xx_event_handler_table[TS_SIZE][TE_SIZE] =
{
/* {START , DONE, FAILED, ERROR, OTHER } */
- {NULL, tape34xx_unused_done, NULL, tape34xx_unused_error, NULL}, /* TS_UNUSED */
- {NULL, tape34xx_idle_done, NULL, tape34xx_idle_error, NULL}, /* TS_IDLE */
+ {NULL, tape34xx_unused_done, NULL, NULL, NULL}, /* TS_UNUSED */
+ {NULL, tape34xx_idle_done, NULL, NULL, NULL}, /* TS_IDLE */
{NULL, NULL, NULL, NULL, NULL}, /* TS_DONE */
{NULL, NULL, NULL, NULL, NULL}, /* TS_FAILED */
- {NULL, tape34xx_block_done, NULL, tape34xx_block_error, NULL}, /* TS_BLOCK_INIT */
+ {NULL, tape34xx_block_done, NULL, NULL, NULL}, /* TS_BLOCK_INIT */
{NULL, tape34xx_bsb_init_done, NULL, NULL, NULL}, /* TS_BSB_INIT */
{NULL, tape34xx_bsf_init_done, NULL, NULL, NULL}, /* TS_BSF_INIT */
{NULL, tape34xx_dse_init_done, NULL, NULL, NULL}, /* TS_DSE_INIT */
{NULL, NULL, NULL, NULL, NULL}, /* TS_EGA_INIT */
{NULL, tape34xx_fsb_init_done, NULL, NULL, NULL}, /* TS_FSB_INIT */
- {NULL, tape34xx_fsf_init_done, NULL, tape34xx_fsf_init_error, NULL}, /* TS_FSF_INIT */
+ {NULL, tape34xx_fsf_init_done, NULL, NULL, NULL}, /* TS_FSF_INIT */
{NULL, NULL, NULL, NULL, NULL}, /* TS_LDI_INIT */
- {NULL, tape34xx_lbl_init_done, NULL, tape34xx_lbl_init_error, NULL}, /* TS_LBL_INIT */
+ {NULL, tape34xx_lbl_init_done, NULL, NULL, NULL}, /* TS_LBL_INIT */
{NULL, NULL, NULL, NULL, NULL}, /* TS_MSE_INIT */
{NULL, tape34xx_nop_init_done, NULL, NULL, NULL}, /* TS_NOP_INIT */
{NULL, NULL, NULL, NULL, NULL}, /* TS_RBA_INIT */
@@ -56,11 +55,11 @@
{NULL, NULL, NULL, NULL, NULL}, /* TS_RBU_INIT */
{NULL, NULL, NULL, NULL, NULL}, /* TS_RBL_INIT */
{NULL, NULL, NULL, NULL, NULL}, /* TS_RDC_INIT */
- {NULL, tape34xx_rfo_init_done, NULL, tape34xx_rfo_init_error, NULL}, /* TS_RFO_INIT */
+ {NULL, tape34xx_rfo_init_done, NULL, NULL, NULL}, /* TS_RFO_INIT */
{NULL, NULL, NULL, NULL, NULL}, /* TS_RSD_INIT */
- {NULL, tape34xx_rew_init_done, NULL, tape34xx_rew_init_error, NULL}, /* TS_REW_INIT */
- {NULL, tape34xx_rew_release_init_done, NULL, tape34xx_rew_release_init_error, NULL}, /* TS_REW_RELEASE_IMIT */
- {NULL, tape34xx_run_init_done, NULL, tape34xx_run_init_error, NULL}, /* TS_RUN_INIT */
+ {NULL, tape34xx_rew_init_done, NULL, NULL, NULL}, /* TS_REW_INIT */
+ {NULL, tape34xx_rew_release_init_done, NULL, NULL, NULL}, /* TS_REW_RELEASE_IMIT */
+ {NULL, tape34xx_run_init_done, NULL, NULL, NULL}, /* TS_RUN_INIT */
{NULL, NULL, NULL, NULL, NULL}, /* TS_SEN_INIT */
{NULL, NULL, NULL, NULL, NULL}, /* TS_SID_INIT */
{NULL, NULL, NULL, NULL, NULL}, /* TS_SNP_INIT */
@@ -70,8 +69,8 @@
{NULL, NULL, NULL, NULL, NULL}, /* TS_SYN_INIT */
{NULL, NULL, NULL, NULL, NULL}, /* TS_TIO_INIT */
{NULL, NULL, NULL, NULL, NULL}, /* TS_UNA_INIT */
- {NULL, tape34xx_wri_init_done, NULL, tape34xx_wri_init_error, NULL}, /* TS_WRI_INIT */
- {NULL, tape34xx_wtm_init_done, NULL, tape34xx_wtm_init_error, NULL}, /* TS_WTM_INIT */
+ {NULL, tape34xx_wri_init_done, NULL, NULL, NULL}, /* TS_WRI_INIT */
+ {NULL, tape34xx_wtm_init_done, NULL, NULL, NULL}, /* TS_WTM_INIT */
{NULL, NULL, NULL, NULL, NULL}}; /* TS_NOT_OPER */
@@ -205,6 +204,59 @@
#endif /* TAPE_DEBUG */
return cqr;
}
+ccw_req_t *
+tape34xx_read_opposite (tape_info_t * tape,int novalue)
+{
+ ccw_req_t *cqr;
+ ccw1_t *ccw;
+ size_t count;
+ // first, retrieve the count from the old cqr.
+ cqr = tape->cqr;
+ ccw = cqr->cpaddr;
+ ccw++;
+ count=ccw->count;
+ // free old cqr.
+ clear_normalized_cda (ccw);
+ tape_free_request (cqr);
+ // build new cqr
+ cqr = tape_alloc_ccw_req (tape, 3, 0);
+ if (!cqr) {
+#ifdef TAPE_DEBUG
+ debug_text_exception (tape_debug_area,6,"xrop nomem");
+#endif /* TAPE_DEBUG */
+ return NULL;
+ }
+ ccw = cqr->cpaddr;
+ ccw->cmd_code = MODE_SET_DB;
+ ccw->flags = CCW_FLAG_CC;
+ ccw->count = 1;
+ set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+ ccw++;
+
+ ccw->cmd_code = READ_BACKWARD;
+ ccw->flags = CCW_FLAG_CC;
+ ccw->count = count;
+ set_normalized_cda (ccw, (unsigned long) tape->kernbuf);
+ if ((ccw->cda) == 0) {
+ tape_free_request (cqr);
+ return NULL;
+ }
+ ccw++;
+ ccw->cmd_code = FORSPACEBLOCK;
+ ccw->flags = CCW_FLAG_CC;
+ ccw->count = 1;
+ ccw->cda = (unsigned long)ccw;
+ ccw++;
+ ccw->cmd_code = NOP;
+ ccw->flags = 0;
+ ccw->count = 1;
+ ccw->cda = (unsigned long)ccw;
+ tapestate_set (tape, TS_RBA_INIT);
+#ifdef TAPE_DEBUG
+ debug_text_event (tape_debug_area,6,"xrop ccwg");
+#endif /* TAPE_DEBUG */
+ return cqr;
+}
void
tape34xx_free_read_block (ccw_req_t * cqr, tape_info_t * tape)
@@ -233,7 +285,6 @@
#endif /* TAPE_DEBUG */
}
-
/*
* The IOCTL interface is implemented in the following section,
* excepted the MTRESET, MTSETBLK which are handled by tapechar.c
@@ -1329,7 +1380,7 @@
else
bhct++;
}
- if ((data = kmalloc (4 * sizeof (__u8), GFP_KERNEL)) == NULL) {
+ if ((data = kmalloc (4 * sizeof (__u8), GFP_ATOMIC)) == NULL) {
#ifdef TAPE_DEBUG
debug_text_exception (tape_debug_area,3,"xBREDnomem");
#endif /* TAPE_DEBUG */
@@ -1395,9 +1446,8 @@
size,
blksize_size[tapeblock_major][tape->blk_minor],
req->nr_sectors);
-
- tape_free_request (cqr);
kfree(data);
+ tape_free_request (cqr);
return NULL;
}
}
@@ -1506,17 +1556,6 @@
}
}
-void
-tape34xx_unused_error (tape_info_t * tape)
-{
-#ifdef TAPE_DEBUG
- debug_text_event (tape_debug_area,3,"unsol.irq!");
- debug_text_event (tape_debug_area,3,"unit chk!");
- debug_int_exception (tape_debug_area,3,tape->devinfo.irq);
-#endif /* TAPE_DEBUG */
- PRINT_WARN ("Unsolicited IRQ (Unit Check) caught in unused state.\n");
- tape_dump_sense (&tape->devstat);
-}
void
tape34xx_idle_done (tape_info_t * tape)
@@ -1531,18 +1570,6 @@
}
void
-tape34xx_idle_error (tape_info_t * tape)
-{
-#ifdef TAPE_DEBUG
- debug_text_event (tape_debug_area,3,"unsol.irq!");
- debug_text_event (tape_debug_area,3,"unit chk!");
- debug_int_exception (tape_debug_area,3,tape->devinfo.irq);
-#endif /* TAPE_DEBUG */
- PRINT_WARN ("Unsolicited IRQ (Unit Check) caught in idle state.\n");
- tape_dump_sense (&tape->devstat);
-}
-
-void
tape34xx_block_done (tape_info_t * tape)
{
#ifdef TAPE_DEBUG
@@ -1553,16 +1580,6 @@
}
void
-tape34xx_block_error (tape_info_t * tape)
-{
-#ifdef TAPE_DEBUG
- debug_text_event (tape_debug_area,3,"x:xREQfail");
-#endif /* TAPE_DEBUG */
- tapestate_set(tape,TS_FAILED);
- schedule_tapeblock_exec_IO(tape);
-}
-
-void
tape34xx_bsf_init_done (tape_info_t * tape)
{
#ifdef TAPE_DEBUG
@@ -1599,27 +1616,6 @@
}
void
-tape34xx_fsf_init_error (tape_info_t * tape)
-{
- if (((tape->devstat.ii.sense.data[0] == 0x08) || // sense.data[0]=08 -> first time
- (tape->devstat.ii.sense.data[0] == 0x10) || // an alternate one...
- (tape->devstat.ii.sense.data[0] == 0x12)) && // sense.data[1]=12 -> repeated message
- (tape->devstat.ii.sense.data[1] == 0x40)) {
- // end of recorded area!
-#ifdef TAPE_DEBUG
- debug_text_event (tape_debug_area,3,"fsf fail");
- debug_text_exception (tape_debug_area,3,"eoRecArea");
-#endif /* TAPE_DEBUG */
- tape->rc = -EIO;
- tapestate_set (tape, TS_FAILED);
- tape->wanna_wakeup=1;
- wake_up_interruptible (&tape->wq);
- } else {
- tape34xx_unexpect_uchk_handler (tape);
- }
-}
-
-void
tape34xx_fsb_init_done (tape_info_t * tape)
{
#ifdef TAPE_DEBUG
@@ -1657,29 +1653,6 @@
}
void
-tape34xx_lbl_init_error (tape_info_t * tape)
-{
- if (((tape->devstat.ii.sense.data[0] == 0x00) || // sense.data[0]=00 -> first time
- (tape->devstat.ii.sense.data[0] == 0x08) || // an alternate one...
- (tape->devstat.ii.sense.data[0] == 0x10) || // alternate, too
- (tape->devstat.ii.sense.data[0] == 0x12)) && // sense.data[1]=12 -> repeated message
- ((tape->devstat.ii.sense.data[1] == 0x40) ||
- (tape->devstat.ii.sense.data[1] == 0xc0))) {
- // block not found!
-#ifdef TAPE_DEBUG
- debug_text_event (tape_debug_area,3,"lbl fail");
- debug_text_exception (tape_debug_area,3,"blk nfound");
-#endif /* TAPE_DEBUG */
- tape->rc = -EIO;
- tapestate_set (tape, TS_FAILED);
- tape->wanna_wakeup=1;
- wake_up_interruptible (&tape->wq);
- } else {
- tape34xx_unexpect_uchk_handler (tape);
- }
-}
-
-void
tape34xx_nop_init_done (tape_info_t * tape)
{
#ifdef TAPE_DEBUG
@@ -1699,11 +1672,8 @@
#ifdef TAPE_DEBUG
debug_text_event (tape_debug_area,6,"rfo done");
#endif
- //BH: use irqsave
- //s390irq_spin_lock(tape->devinfo.irq);
tapestate_set (tape, TS_DONE);
tape->rc = 0;
- //s390irq_spin_unlock(tape->devinfo.irq);
tape->wanna_wakeup=1;
wake_up_interruptible (&tape->wq);
}
@@ -1729,50 +1699,6 @@
}
void
-tape34xx_rfo_init_error (tape_info_t * tape)
-{
- if (((tape->devstat.ii.sense.data[0] == 0x08) || // sense.data[0]=08 -> first time
- (tape->devstat.ii.sense.data[0] == 0x10) || // an alternate one...
- (tape->devstat.ii.sense.data[0] == 0x12)) && // sense.data[1]=12 -> repeated message
- (tape->devstat.ii.sense.data[1] == 0x40)) {
- // end of recorded area!
-#ifdef TAPE_DEBUG
- debug_text_event (tape_debug_area,3,"rfo fail");
- debug_text_exception (tape_debug_area,3,"eoRecArea");
-#endif /* TAPE_DEBUG */
- tape->rc = 0;
- tapestate_set (tape, TS_FAILED);
- tape->wanna_wakeup=1;
- wake_up_interruptible (&tape->wq);
- } else {
- switch (tape->devstat.ii.sense.data[3]) {
- case 0x48:
-#ifdef TAPE_DEBUG
- debug_text_event (tape_debug_area,3,"rfo fail");
- debug_text_exception (tape_debug_area,3,"recov x48");
-#endif /* TAPE_DEBUG */
- //s390irq_spin_lock(tape->devinfo.irq);
- do_IO (tape->devinfo.irq, tape->cqr->cpaddr, (unsigned long) (tape->cqr), 0x00, tape->cqr->options);
- //s390irq_spin_unlock(tape->devinfo.irq);
- break;
- case 0x2c:
- PRINT_ERR ("TAPE: Permanent Unit Check. Please check your hardware!");
-#ifdef TAPE_DEBUG
- debug_text_event (tape_debug_area,3,"rfo fail");
- debug_text_exception (tape_debug_area,3,"Perm UCK");
-#endif
- tape->rc = -EIO;
- tapestate_set (tape, TS_FAILED);
- tape->wanna_wakeup=1;
- wake_up_interruptible (&tape->wq);
- break;
- default:
- tape34xx_unexpect_uchk_handler (tape);
- }
- }
-}
-
-void
tape34xx_rew_init_done (tape_info_t * tape)
{
#ifdef TAPE_DEBUG
@@ -1788,44 +1714,6 @@
}
void
-tape34xx_rew_release_init_error (tape_info_t * tape)
-{
- if ((tape->devstat.ii.sense.data[0] == 0x40) &&
- (tape->devstat.ii.sense.data[1] == 0x40) &&
- (tape->devstat.ii.sense.data[3] == 0x43)) {
- // no tape in the drive
- PRINT_INFO ("Drive %d not ready. No volume loaded.\n", tape->rew_minor / 2);
-#ifdef TAPE_DEBUG
- debug_text_event (tape_debug_area,3,"rewR fail");
- debug_text_exception (tape_debug_area,3,"no medium");
-#endif
- tapestate_set (tape, TS_FAILED);
- tape->rc = -ENOMEDIUM;
- tape->wanna_wakeup=1;
- wake_up (&tape->wq);
- } else {
- PRINT_ERR ("TAPE34XX: An unexpected Unit Check occurred.\n");
- PRINT_ERR ("TAPE34XX: Please send the following 20 lines of output to cotte@de.ibm.com\n");
- PRINT_ERR ("TAPE34XX: Current state is: %s",
- (((tapestate_get (tape) < TS_SIZE) && (tapestate_get (tape) >= 0)) ?
- state_verbose[tapestate_get (tape)] : "->UNKNOWN STATE<-"));
- tapestate_set (tape, TS_FAILED);
-#ifdef TAPE_DEBUG
- debug_text_event (tape_debug_area,3,"rewR unexp");
- debug_text_event (tape_debug_area,3,"state:");
- debug_text_event (tape_debug_area,3,((tapestate_get (tape) < TS_SIZE) &&
- (tapestate_get (tape) >= 0)) ?
- state_verbose[tapestate_get (tape)] :
- "TS UNKNOWN");
-#endif /* TAPE_DEBUG */
- tape_dump_sense (&tape->devstat);
- tape->rc = -EIO;
- tape->wanna_wakeup=1;
- wake_up (&tape->wq);
- }
-}
-
-void
tape34xx_rew_release_init_done (tape_info_t * tape)
{
#ifdef TAPE_DEBUG
@@ -1839,12 +1727,6 @@
}
void
-tape34xx_rew_init_error (tape_info_t * tape)
-{
- tape34xx_unexpect_uchk_handler (tape);
-}
-
-void
tape34xx_run_init_done (tape_info_t * tape)
{
#ifdef TAPE_DEBUG
@@ -1857,27 +1739,6 @@
}
void
-tape34xx_run_init_error (tape_info_t * tape)
-{
-
- switch (tape->devstat.ii.sense.data[3]) {
- case 0x52:
- // This error is fine for rewind and unload
- // It reports that no volume is loaded...
-#ifdef TAPE_DEBUG
- debug_text_event (tape_debug_area,6,"run done");
-#endif /* TAPE_DEBUG */
- tapestate_set (tape, TS_DONE);
- tape->rc = 0;
- tape->wanna_wakeup=1;
- wake_up_interruptible (&tape->wq);
- break;
- default:
- tape34xx_unexpect_uchk_handler (tape);
- }
-}
-
-void
tape34xx_wri_init_done (tape_info_t * tape)
{
#ifdef TAPE_DEBUG
@@ -1893,72 +1754,632 @@
}
void
-tape34xx_wri_init_error (tape_info_t * tape)
+tape34xx_wtm_init_done (tape_info_t * tape)
{
- if ((tape->devstat.ii.sense.data[0]==0x80)&&(tape->devstat.ii.sense.data[1]==0x4a)) {
- // tape is write protected
#ifdef TAPE_DEBUG
- debug_text_event (tape_debug_area,3,"wri fail");
- debug_text_exception (tape_debug_area,3,"writProte");
-#endif /* TAPE_DEBUG */
- tape->rc = -EACCES;
- tapestate_set (tape, TS_FAILED);
+ debug_text_event (tape_debug_area,3,"wtm done");
+#endif
+ tapestate_set (tape, TS_DONE);
+ tape->rc = 0;
tape->wanna_wakeup=1;
wake_up_interruptible (&tape->wq);
- } else {
- switch (tape->devstat.ii.sense.data[3]) {
- case 0x48:
-#ifdef TAPE_DEBUG
- debug_text_event (tape_debug_area,3,"wri fail");
- debug_text_exception (tape_debug_area,3,"recov x48");
-#endif /* TAPE_DEBUG */
- //s390irq_spin_lock(tape->devinfo.irq);
- do_IO (tape->devinfo.irq, tape->cqr->cpaddr, (unsigned long) (tape->cqr), 0x00, tape->cqr->options);
- //s390irq_spin_unlock(tape->devinfo.irq);
- break;
- case 0x2c:
- PRINT_ERR ("TAPE: Permanent Unit Check. Please check your hardware!\n");
-#ifdef TAPE_DEBUG
- debug_text_event (tape_debug_area,3,"wri fail");
- debug_text_exception (tape_debug_area,3,"Perm UCK");
-#endif
- tape->rc = -EIO;
- tapestate_set (tape, TS_FAILED);
- tape->wanna_wakeup=1;
- wake_up_interruptible (&tape->wq);
- break;
- case 0x38: //end of tape
-#ifdef TAPE_DEBUG
- PRINT_WARN ("TAPE: End of Tape reached.\n");
- debug_text_event (tape_debug_area,3,"wri fail");
- debug_text_exception (tape_debug_area,3,"EOT!");
-#endif
- tape->rc = tape->devstat.rescnt;
- tapestate_set (tape, TS_FAILED);
- tape->wanna_wakeup=1;
- wake_up_interruptible (&tape->wq);
- break;
+}
+
+/* This function analyses the tape's sense-data in case of a unit-check. If possible,
+ it tries to recover from the error. Else the user is informed about the problem. */
+void
+tape34xx_error_recovery (tape_info_t* tape)
+{
+ __u8* sense=tape->devstat.ii.sense.data;
+ int inhibit_cu_recovery=0;
+ int cu_type=tape->discipline->cu_type;
+ if ((((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)&0x80) inhibit_cu_recovery=1;
+ if (tapestate_get(tape)==TS_BLOCK_INIT) {
+ // no recovery for block device, bottom half will retry...
+ tape34xx_error_recovery_has_failed(tape,EIO);
+ return;
+ }
+ if (sense[0]&SENSE_COMMAND_REJECT)
+ switch (tapestate_get(tape)) {
+ 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(tape,EACCES);
+ return;
+ }
default:
- tape34xx_unexpect_uchk_handler (tape);
+ tape34xx_error_recovery_HWBUG(tape,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(tape)) {
+ case TS_FSF_INIT:
+ // Trying to seek beyond end of recorded area
+ tape34xx_error_recovery_has_failed(tape,EIO);
+ return;
+ case TS_LBL_INIT:
+ // Block could not be located.
+ tape34xx_error_recovery_has_failed(tape,EIO);
+ return;
+ case TS_RFO_INIT:
+ // Try to read beyond end of recorded area -> 0 bytes read
+ tape34xx_error_recovery_has_failed(tape,0);
+ return;
+ }
+ // Sensing special bits
+ if (sense[0]&SENSE_BUS_OUT_CHECK) {
+ tape34xx_error_recovery_do_retry(tape);
+ 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(tape,2);
+ return;
+ } else {
+ // data check is permanent, CU recovery has failed
+ PRINT_WARN("Permanent read error, recovery failed!\n");
+ tape34xx_error_recovery_has_failed(tape,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(tape,3);
+ return;
+ } else {
+ // data check is permanent, cu-recovery has failed
+ PRINT_WARN("Permanent write error, recovery failed!\n");
+ tape34xx_error_recovery_has_failed(tape,EIO);
+ return;
+ }
+ case 0x26:
+ // Data Check (read opposite) occurred. We'll recover this.
+ tape34xx_error_recovery_read_opposite(tape);
+ 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(tape,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(tape,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(tape,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(tape,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(tape,EIO);
+ return;
+ default:
+ // Overrun bit is set, but erpa does not show overrun error. This is a bug.
+ tape34xx_error_recovery_HWBUG(tape,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(tape,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(tape,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(tape);
+ 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(tape,EIO);
+ return;
+ case 0x23:
+ // Read data check. Should have been be covered earlier -> Bug!
+ tape34xx_error_recovery_HWBUG(tape,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(tape);
+ return;
+ case 0x25:
+ // Write data check. Should have been covered earlier -> Bug!
+ tape34xx_error_recovery_HWBUG(tape,8);
+ return;
+ case 0x26:
+ // Data check (read opposite). Should have been covered earlier -> Bug!
+ tape34xx_error_recovery_HWBUG(tape,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(tape);
+ return;
+ case 0x28:
+ // Write id mark check. Should have beed covered earlier -> bug!
+ tape34xx_error_recovery_HWBUG(tape,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(tape,EIO);
+ return;
+ case 0x2a:
+ // Unsolicited environmental data. An internal counter overflows, we can ignore
+ // this and reissue the cmd.
+ tape34xx_error_recovery_do_retry(tape);
+ return;
+ case 0x2b:
+ // Environmental data present. Indicates either unload completed ok or read buffered
+ // log command completed ok.
+ if (tapestate_get(tape)==TS_RUN_INIT) {
+ // Rewind unload completed ok.
+ tape34xx_error_recovery_succeded(tape);
+ return;
+ }
+ // Since we do not issue read buffered log commands, this should never occur -> bug.
+ tape34xx_error_recovery_HWBUG(tape,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(tape,EIO);
+ return;
+ case 0x2d:
+ // Data security erase failure.
+ if (tapestate_get(tape)==TS_DSE_INIT) {
+ // report an I/O error
+ tape34xx_error_recovery_has_failed(tape,EIO);
+ return;
+ }
+ // Data security erase failure, but no such command issued. This is a bug.
+ tape34xx_error_recovery_HWBUG(tape,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(tape,EMEDIUMTYPE);
+ return;
+ case 0x2f:
+ // This erpa is reserved. This is a bug.
+ tape34xx_error_recovery_HWBUG(tape,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(tape,EACCES);
+ return;
+ case 0x31:
+ // Tape void. Should have beed covered ealier -> bug
+ tape34xx_error_recovery_HWBUG(tape,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(tape,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(tape,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(tape)!=TS_RUN_INIT) {
+ tape34xx_error_recovery_HWBUG(tape,15);
+ return;
+ }
+ tape34xx_error_recovery_has_failed(tape,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(tape,EIO);
+ return;
+ case 0x36:
+ switch (cu_type) {
+ case 0x3480:
+ // This erpa is reserved for 3480 -> BUG
+ tape34xx_error_recovery_HWBUG(tape,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(tape,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(tape,EIO);
+ return;
+ case 0x38:
+ // Physical end of tape. A read/write operation reached the physical end of tape.
+ if (tapestate_get(tape)==TS_WRI_INIT) {
+ tape34xx_error_recovery_has_failed(tape,ENOSPC);
+ }
+ return;
+ case 0x39:
+ // Backward at BOT. The drive is at BOT and is requestet to move backward.
+ tape34xx_error_recovery_has_failed(tape,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(tape,EIO);
+ return;
+ case 0x3b:
+ // Manual rewind or unload. This causes an I/O error.
+ PRINT_WARN("Medium is rewinded or unloaded manually.\n");
+ tape34xx_error_recovery_has_failed(tape,EIO);
+ return;
+ case 0x3c:
+ case 0x3d:
+ case 0x3e:
+ case 0x3f:
+ // These erpas are reserved -> BUG
+ tape34xx_error_recovery_HWBUG(tape,17);
+ return;
+ case 0x40:
+ // Overrun error. This should have been covered earlier -> bug.
+ tape34xx_error_recovery_HWBUG(tape,18);
+ return;
+ case 0x41:
+ // Record sequence error. This should have been covered earlier -> bug.
+ tape34xx_error_recovery_HWBUG(tape,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(tape);
+ 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(tape,ENOMEDIUM);
+ return;
+ case 0x44:
+ // Locate Block unsuccessfull. We'll report this.
+ if ((tapestate_get(tape)!=TS_BLOCK_INIT) &&
+ (tapestate_get(tape)!=TS_LBL_INIT)) {
+ tape34xx_error_recovery_HWBUG(tape,20); // No locate block was issued...
+ return;
+ }
+ tape34xx_error_recovery_has_failed(tape,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(tape,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(tape,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(tape,EIO);
+ return;
+ case 0x48:
+ // Log sense data and retry request. We'll do so...
+ tape34xx_error_recovery_do_retry(tape);
+ 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(tape,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(tape,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(tape,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(tape);
+ return;
+ case 0x4d:
+ switch (cu_type) {
+ case 0x3480:
+ // This erpa is reserved for 3480 -> bug
+ tape34xx_error_recovery_HWBUG(tape,21);
+ return;
+ case 0x3490:
+ // Resetting event recieved. 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(tape);
+ return;
+ }
+ case 0x4e:
+ switch (cu_type) {
+ case 0x3480:
+ // This erpa is reserved for 3480 -> bug.
+ tape34xx_error_recovery_HWBUG(tape,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(tape,ENOBUFS);
+ return;
+ }
+ case 0x4f:
+ // These erpas are reserved -> bug
+ tape34xx_error_recovery_HWBUG(tape,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(tape);
+ 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(tape);
+ return;
+ case 0x52:
+ // End of Volume complete. Rewind unload completed ok. We'll report to the user...
+ if (tapestate_get(tape)!=TS_RUN_INIT) {
+ tape34xx_error_recovery_HWBUG(tape,24);
+ return;
+ }
+ tape34xx_error_recovery_succeded(tape);
+ return;
+ case 0x53:
+ // Global command intercept. We'll have to reissue our command.
+ tape34xx_error_recovery_do_retry(tape);
+ return;
+ case 0x54:
+ // Channel interface recovery (temporary). This can be recovered by reissuing the command.
+ tape34xx_error_recovery_do_retry(tape);
+ 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(tape,EIO);
+ return;
+ case 0x56:
+ // Channel protocol error. This cannot be recovered.
+ PRINT_WARN("A channel protocol error occurred.\n");
+ tape34xx_error_recovery_has_failed(tape,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(tape);
+ return;
+ case 0x3490:
+ // Global status intercept. We have to reissue the command.
+ PRINT_WARN("An global status intercept was recieved, which will be recovered.\n");
+ tape34xx_error_recovery_do_retry(tape);
+ return;
+ }
+ case 0x58:
+ case 0x59:
+ // These erpas are reserved -> bug.
+ tape34xx_error_recovery_HWBUG(tape,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(tape,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(tape);
+ return;
+ }
+ PRINT_WARN("Tape format is incompatible to the drive, which writes 3480-2 XF.\n");
+ tape34xx_error_recovery_has_failed(tape,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(tape,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(tape,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(tape,EMEDIUMTYPE);
+ return;
+ default:
+ // Reserved erpas -> bug
+ tape34xx_error_recovery_HWBUG(tape,26);
+ return;
+ }
}
-void
-tape34xx_wtm_init_done (tape_info_t * tape)
-{
+void tape34xx_error_recovery_has_failed (tape_info_t* tape,int error_id) {
#ifdef TAPE_DEBUG
- debug_text_event (tape_debug_area,3,"wtm done");
+ debug_text_event (tape_debug_area,3,"xerp fail");
+ debug_text_event (tape_debug_area,3,(((tapestate_get (tape) < TS_SIZE) &&
+ (tapestate_get (tape) >= 0)) ?
+ state_verbose[tapestate_get (tape)] : "UNKNOWN"));
#endif
- tapestate_set (tape, TS_DONE);
- tape->rc = 0;
+ if ((tapestate_get(tape)!=TS_UNUSED) && (tapestate_get(tape)!=TS_IDLE)) {
+ tape_dump_sense(&tape->devstat);
+ tape->rc = -error_id;
tape->wanna_wakeup=1;
- wake_up_interruptible (&tape->wq);
+ switch (tapestate_get(tape)) {
+ case TS_REW_RELEASE_INIT:
+ tapestate_set(tape,TS_FAILED);
+ wake_up (&tape->wq);
+ break;
+ case TS_BLOCK_INIT:
+ tapestate_set(tape,TS_FAILED);
+ schedule_tapeblock_exec_IO(tape);
+ break;
+ default:
+ tapestate_set(tape,TS_FAILED);
+ wake_up_interruptible (&tape->wq);
+ }
+ } else {
+ PRINT_WARN("Recieved an unsolicited IRQ.\n");
+ tape_dump_sense(&tape->devstat);
+ }
+}
+
+void tape34xx_error_recovery_succeded(tape_info_t* tape) {
+#ifdef TAPE_DEBUG
+ debug_text_event (tape_debug_area,3,"xerp done");
+ debug_text_event (tape_debug_area,3,(((tapestate_get (tape) < TS_SIZE) &&
+ (tapestate_get (tape) >= 0)) ?
+ state_verbose[tapestate_get (tape)] : "UNKNOWN"));
+#endif
+ if ((tapestate_get(tape)!=TS_UNUSED) && (tapestate_get(tape)!=TS_DONE)) {
+ tapestate_event (tape, TE_DONE);
+ } else {
+ PRINT_WARN("Recieved an unsolicited IRQ.\n");
+ tape_dump_sense(&tape->devstat);
+ }
}
-void
-tape34xx_wtm_init_error (tape_info_t * tape)
-{
- tape34xx_unexpect_uchk_handler (tape);
+void tape34xx_error_recovery_do_retry(tape_info_t* tape) {
+#ifdef TAPE_DEBUG
+ debug_text_event (tape_debug_area,3,"xerp retr");
+ debug_text_event (tape_debug_area,3,(((tapestate_get (tape) < TS_SIZE) &&
+ (tapestate_get (tape) >= 0)) ?
+ state_verbose[tapestate_get (tape)] : "UNKNOWN"));
+#endif
+ if ((tapestate_get(tape)!=TS_UNUSED) && (tapestate_get(tape)!=TS_IDLE)) {
+ tape_dump_sense(&tape->devstat);
+ while (do_IO (tape->devinfo.irq, tape->cqr->cpaddr, (unsigned long) tape->cqr, 0x00, tape->cqr->options));
+ } else {
+ PRINT_WARN("Recieved an unsolicited IRQ.\n");
+ tape_dump_sense(&tape->devstat);
+ }
+}
+void
+tape34xx_error_recovery_read_opposite (tape_info_t* tape) {
+ switch (tapestate_get(tape)) {
+ case TS_RFO_INIT:
+ // We did read forward, but the data could not be read *correctly*.
+ // We will read backward and then skip forward again.
+ tape->cqr=tape34xx_read_opposite(tape,0);
+ if (tape->cqr==NULL)
+ tape34xx_error_recovery_has_failed(tape,EIO);
+ else
+ tape34xx_error_recovery_do_retry(tape);
+ break;
+ case TS_RBA_INIT:
+ // We tried to read forward and backward, but hat no success -> failed.
+ tape34xx_error_recovery_has_failed(tape,EIO);
+ break;
+ case TS_BLOCK_INIT:
+ tape34xx_error_recovery_do_retry(tape);
+ break;
+ default:
+ PRINT_WARN("read_opposite_recovery_called_with_state:%s\n",
+ (((tapestate_get (tape) < TS_SIZE) &&
+ (tapestate_get (tape) >= 0)) ?
+ state_verbose[tapestate_get (tape)] : "UNKNOWN"));
+ }
+}
+
+void
+tape34xx_error_recovery_HWBUG (tape_info_t* tape,int condno) {
+ devstat_t* stat=&tape->devstat;
+ PRINT_WARN("An unexpected condition #%d was caught in tape error recovery.\n",condno);
+ PRINT_WARN("Please report this incident.\n");
+ PRINT_WARN("State of the tape:%s\n",
+ (((tapestate_get (tape) < TS_SIZE) &&
+ (tapestate_get (tape) >= 0)) ?
+ state_verbose[tapestate_get (tape)] : "UNKNOWN"));
+ PRINT_INFO ("Sense data: %02X%02X%02X%02X %02X%02X%02X%02X "
+ " %02X%02X%02X%02X %02X%02X%02X%02X \n",
+ stat->ii.sense.data[0], stat->ii.sense.data[1],
+ stat->ii.sense.data[2], stat->ii.sense.data[3],
+ stat->ii.sense.data[4], stat->ii.sense.data[5],
+ stat->ii.sense.data[6], stat->ii.sense.data[7],
+ stat->ii.sense.data[8], stat->ii.sense.data[9],
+ stat->ii.sense.data[10], stat->ii.sense.data[11],
+ stat->ii.sense.data[12], stat->ii.sense.data[13],
+ stat->ii.sense.data[14], stat->ii.sense.data[15]);
+ PRINT_INFO ("Sense data: %02X%02X%02X%02X %02X%02X%02X%02X "
+ " %02X%02X%02X%02X %02X%02X%02X%02X \n",
+ stat->ii.sense.data[16], stat->ii.sense.data[17],
+ stat->ii.sense.data[18], stat->ii.sense.data[19],
+ stat->ii.sense.data[20], stat->ii.sense.data[21],
+ stat->ii.sense.data[22], stat->ii.sense.data[23],
+ stat->ii.sense.data[24], stat->ii.sense.data[25],
+ stat->ii.sense.data[26], stat->ii.sense.data[27],
+ stat->ii.sense.data[28], stat->ii.sense.data[29],
+ stat->ii.sense.data[30], stat->ii.sense.data[31]);
+ tape34xx_error_recovery_has_failed(tape,EIO);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)