patch-2.0.25 linux/drivers/block/ide-tape.c
Next file: linux/drivers/block/ide-tape.h
Previous file: linux/arch/i386/kernel/traps.c
Back to the patch index
Back to the overall index
- Lines: 275
- Date:
Wed Nov 6 14:48:32 1996
- Orig file:
v2.0.24/linux/drivers/block/ide-tape.c
- Orig date:
Tue Oct 8 21:20:09 1996
diff -u --recursive --new-file v2.0.24/linux/drivers/block/ide-tape.c linux/drivers/block/ide-tape.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/block/ide-tape.c Version 1.8 - ALPHA Sep 26, 1996
+ * linux/drivers/block/ide-tape.c Version 1.9 - ALPHA Nov 5, 1996
*
* Copyright (C) 1995, 1996 Gadi Oxman <gadio@netvision.net.il>
*
@@ -189,6 +189,12 @@
* Ver 1.7 Sep 10 96 Minor changes for the CONNER CTT8000-A model.
* Ver 1.8 Sep 26 96 Attempt to find a better balance between good
* interactive response and high system throughput.
+ * Ver 1.9 Nov 5 96 Automatically cross encountered filemarks rather
+ * than requiring an explicit FSF command.
+ * Abort pending requests at end of media.
+ * MTTELL was sometimes returning incorrect results.
+ * Return the real block size in the MTIOCGET ioctl.
+ * Some error recovery bug fixes.
*
* We are currently in an *alpha* stage. The driver is not complete and not
* much tested. I would strongly suggest to:
@@ -418,8 +424,9 @@
#define IDETAPE_READ_REQUEST 92
#define IDETAPE_WRITE_REQUEST 93
+#define IDETAPE_ABORTED_WRITE_REQUEST 94
-#define IDETAPE_LAST_REQUEST 93
+#define IDETAPE_LAST_REQUEST 94
/*
* A macro which can be used to check if a we support a given
@@ -1205,10 +1212,6 @@
printk ("Unable to register character device interface !\n");
/* ??? */
}
- else {
- printk ("ide-tape: %s <-> %s : Character device interface on major = %d\n",
- drive->name,idetape_chrdev.name,major);
- }
}
/*
@@ -1260,10 +1263,8 @@
#if IDETAPE_PIPELINE
tape->max_number_of_stages=IDETAPE_MIN_PIPELINE_STAGES;
- printk ("ide-tape: Operating in pipelined (fast and tricky) operation mode.\n");
#else
tape->max_number_of_stages=0;
- printk ("ide-tape: Operating in non-pipelined (slow and safe) operation mode.\n");
#endif /* IDETAPE_PIPELINE */
idetape_get_mode_sense_results (drive);
@@ -2474,7 +2475,12 @@
pc->abort=1;
}
}
-
+ if (pc->c[0] == IDETAPE_WRITE_CMD) {
+ if (result->eom || (result->sense_key == 0xd && result->asc == 0x0 && result->ascq == 0x2)) {
+ pc->error = IDETAPE_RQ_ERROR_EOD;
+ pc->abort = 1;
+ }
+ }
if (pc->c[0] == IDETAPE_READ_CMD || pc->c[0] == IDETAPE_WRITE_CMD) {
if (result->sense_key == 8) {
pc->error=IDETAPE_RQ_ERROR_EOD;
@@ -2853,6 +2859,17 @@
}
}
+static void idetape_abort_pipeline (ide_drive_t *drive)
+{
+ idetape_tape_t *tape = &drive->tape;
+ idetape_pipeline_stage_t *stage = tape->next_stage;
+
+ while (stage) {
+ stage->rq.cmd = IDETAPE_ABORTED_WRITE_REQUEST;
+ stage = stage->next;
+ }
+}
+
/*
* Functions which handle requests.
*/
@@ -2880,7 +2897,9 @@
if (!rq->errors) /* In case rq->errors is already set, */
rq->errors=!uptodate; /* we won't change it. */
error=rq->errors;
-
+ if (error)
+ tape->failed_pc = NULL;
+
if (tape->active_data_request == rq) { /* The request was a pipelined data transfer request */
if (rq->cmd == IDETAPE_READ_REQUEST) {
@@ -2896,8 +2915,11 @@
tape->active_data_request=NULL;
if (rq->cmd == IDETAPE_WRITE_REQUEST) {
- if (rq->errors)
+ if (rq->errors) {
tape->error_in_pipeline_stage=rq->errors;
+ if (error == IDETAPE_RQ_ERROR_EOD)
+ idetape_abort_pipeline (drive);
+ }
idetape_remove_stage_head (drive);
}
@@ -3078,6 +3100,12 @@
idetape_issue_packet_command (drive,pc,&idetape_pc_intr);
return;
+ case IDETAPE_ABORTED_WRITE_REQUEST:
+ rq->cmd = IDETAPE_WRITE_REQUEST;
+ rq->errors = IDETAPE_RQ_ERROR_EOD;
+ idetape_end_request (1, HWGROUP(drive));
+ return;
+
case IDETAPE_PACKET_COMMAND_REQUEST_TYPE1:
case IDETAPE_PACKET_COMMAND_REQUEST_TYPE2:
/*
@@ -3282,8 +3310,11 @@
bytes_read=tape->tape_block_size*(rq_ptr->nr_sectors-rq_ptr->current_nr_sectors);
rq_ptr->nr_sectors=rq_ptr->current_nr_sectors=0;
idetape_copy_buffer_from_stage (tape->first_stage,buffer);
- if (rq_ptr->errors != IDETAPE_RQ_ERROR_FILEMARK)
+ if (rq_ptr->errors != IDETAPE_RQ_ERROR_FILEMARK) {
+ tape->filemark = 0;
idetape_remove_stage_head (drive);
+ } else
+ tape->filemark = 1;
#if IDETAPE_DEBUG_BUGS
if (bytes_read > blocks*tape->tape_block_size) {
printk ("ide-tape: bug: trying to return more bytes than requested\n");
@@ -3686,7 +3717,7 @@
ide_drive_t *drive=idetape_chrdev.drive;
idetape_tape_t *tape=&(drive->tape);
char *buf_ptr=buf;
- int bytes_read,temp,actually_read=0;
+ int bytes_read,temp,actually_read=0, original_count = count;
#if IDETAPE_DEBUG_LOG
printk ("Reached idetape_chrdev_read\n");
@@ -3730,7 +3761,7 @@
while (count >= tape->data_buffer_size) {
bytes_read=idetape_add_chrdev_read_request (drive,tape->capabilities.ctl,tape->merge_buffer);
if (bytes_read <= 0)
- return (actually_read);
+ goto finish;
memcpy_tofs (buf_ptr,tape->merge_buffer,bytes_read);
buf_ptr+=bytes_read;count-=bytes_read;actually_read+=bytes_read;
}
@@ -3738,13 +3769,16 @@
if (count) {
bytes_read=idetape_add_chrdev_read_request (drive,tape->capabilities.ctl,tape->merge_buffer);
if (bytes_read <= 0)
- return (actually_read);
+ goto finish;
temp=IDETAPE_MIN (count,bytes_read);
memcpy_tofs (buf_ptr,tape->merge_buffer,temp);
actually_read+=temp;
tape->merge_buffer_offset=temp;
tape->merge_buffer_size=bytes_read-temp;
}
+finish:
+ if (actually_read < original_count && tape->filemark)
+ idetape_space_over_filemarks (drive, MTFSF, 1);
return (actually_read);
}
@@ -3817,6 +3851,26 @@
return (actually_written);
}
+static int idetape_pipeline_size (ide_drive_t *drive)
+{
+ idetape_tape_t *tape = &drive->tape;
+ idetape_pipeline_stage_t *stage;
+ struct request *rq;
+ int size = 0;
+
+ idetape_wait_for_pipeline (drive);
+ stage = tape->first_stage;
+ while (stage != NULL) {
+ rq = &stage->rq;
+ size += tape->tape_block_size * (rq->nr_sectors-rq->current_nr_sectors);
+ if (rq->errors == IDETAPE_RQ_ERROR_FILEMARK)
+ size += tape->tape_block_size;
+ stage = stage->next;
+ }
+ size += tape->merge_buffer_size;
+ return size;
+}
+
/*
* Our character device ioctls.
*
@@ -3827,17 +3881,7 @@
*
* MTIOCTOP - Refer to idetape_mtioctop for detailed description.
*
- * MTIOCGET - The mt_dsreg field in the returned mtget structure
- * will be set to (recommended block size <<
- * MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK, which
- * is currently equal to the size itself.
- * The other mtget fields are not supported.
- *
- * Note that we do not actually return the tape's
- * block size. Rather, we provide the recommended
- * number of bytes which should be used as a "user
- * block size" with the character device read/write
- * functions to maximize throughput.
+ * MTIOCGET - Some of the fields are not supported.
*
* MTIOCPOS - The current tape "position" is returned.
* (A unique number which can be used with the MTSEEK
@@ -3857,7 +3901,7 @@
struct mtop mtop;
struct mtget mtget;
struct mtpos mtpos;
- int retval;
+ int retval, block_offset = 0;
#if IDETAPE_DEBUG_LOG
printk ("Reached idetape_chrdev_ioctl, cmd=%u\n",cmd);
@@ -3867,14 +3911,16 @@
idetape_empty_write_pipeline (drive);
idetape_flush_tape_buffers (drive);
}
-
- if (tape->chrdev_direction == idetape_direction_read && cmd != MTIOCTOP)
- idetape_discard_read_pipeline (drive);
-
pc.buffer=pc.temp_buffer;
pc.buffer_size=IDETAPE_TEMP_BUFFER_SIZE;
pc.current_position=pc.temp_buffer;
+ if (cmd == MTIOCGET || cmd == MTIOCPOS) {
+ block_offset = idetape_pipeline_size (drive) / tape->tape_block_size;
+ idetape_create_read_position_cmd (&pc);
+ retval=idetape_queue_pc_tail (drive,&pc);
+ if (retval) return (retval);
+ }
switch (cmd) {
case MTIOCTOP:
retval=verify_area (VERIFY_READ,(char *) arg,sizeof (struct mtop));
@@ -3882,16 +3928,15 @@
memcpy_fromfs ((char *) &mtop, (char *) arg, sizeof (struct mtop));
return (idetape_mtioctop (drive,mtop.mt_op,mtop.mt_count));
case MTIOCGET:
+ memset (&mtget, 0, sizeof (struct mtget));
+ mtget.mt_blkno = tape->block_address - block_offset;
mtget.mt_dsreg=(tape->data_buffer_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK;
retval=verify_area (VERIFY_WRITE,(char *) arg,sizeof (struct mtget));
if (retval) return (retval);
memcpy_tofs ((char *) arg,(char *) &mtget, sizeof (struct mtget));
return (0);
case MTIOCPOS:
- idetape_create_read_position_cmd (&pc);
- retval=idetape_queue_pc_tail (drive,&pc);
- if (retval) return (retval);
- mtpos.mt_blkno=tape->block_address;
+ mtpos.mt_blkno = tape->block_address - block_offset;
retval=verify_area (VERIFY_WRITE,(char *) arg,sizeof (struct mtpos));
if (retval) return (retval);
memcpy_tofs ((char *) arg,(char *) &mtpos, sizeof (struct mtpos));
@@ -4052,6 +4097,7 @@
*/
tape->merge_buffer_size=tape->merge_buffer_offset=0;
+ tape->filemark = 0;
while (tape->first_stage != NULL) {
/*
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov