patch-2.1.15 linux/drivers/block/ide-tape.c
Next file: linux/drivers/block/ide.c
Previous file: linux/drivers/block/ide-probe.c
Back to the patch index
Back to the overall index
- Lines: 380
- Date:
Wed Dec 11 16:45:55 1996
- Orig file:
v2.1.14/linux/drivers/block/ide-tape.c
- Orig date:
Sun Nov 10 20:12:09 1996
diff -u --recursive --new-file v2.1.14/linux/drivers/block/ide-tape.c linux/drivers/block/ide-tape.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/block/ide-tape.c Version 1.10 - BETA Nov 5, 1996
+ * linux/drivers/block/ide-tape.c Version 1.11 - BETA Dec 2, 1996
*
* Copyright (C) 1995, 1996 Gadi Oxman <gadio@netvision.net.il>
*
@@ -202,6 +202,10 @@
* Some portability fixes.
* Removed ide-tape.h.
* Additional minor changes.
+ * Ver 1.11 Dec 2 96 Bug fix in previous DSC timeout handling.
+ * Use ide_stall_queue() for DSC overlap.
+ * Use the maximum speed rather than the current speed
+ * to compute the request service time.
*
* Here are some words from the first releases of hd.c, which are quoted
* in ide.c and apply here as well:
@@ -732,7 +736,8 @@
/*
* IDETAPE_PC_RQ is used to queue a packet command in the request queue.
*/
-#define IDETAPE_PC_RQ 90
+#define IDETAPE_PC_RQ1 90
+#define IDETAPE_PC_RQ2 91
/*
* IDETAPE_READ_RQ and IDETAPE_WRITE_RQ are used by our
@@ -752,13 +757,6 @@
#define IDETAPE_RQ_CMD(cmd) ((cmd >= IDETAPE_FIRST_RQ) && (cmd <= IDETAPE_LAST_RQ))
/*
- * We are now able to postpone an idetape request in the stage
- * where it is polling for DSC and service requests from the other
- * ide device meanwhile.
- */
-#define IDETAPE_RQ_POSTPONED 0x1234
-
-/*
* Error codes which are returned in rq->errors to the higher part
* of the driver.
*/
@@ -1019,9 +1017,6 @@
u8 reserved[2]; /* Reserved */
} idetape_medium_partition_page_t;
-#define IDETAPE_MIN(a,b) ((a)<(b) ? (a):(b))
-#define IDETAPE_MAX(a,b) ((a)>(b) ? (a):(b))
-
/*
* Run time configurable parameters.
*/
@@ -1052,7 +1047,7 @@
{
struct buffer_head *bh = pc->bh;
int count;
-
+
while (bcount) {
#if IDETAPE_DEBUG_BUGS
if (bh == NULL) {
@@ -1061,7 +1056,7 @@
return;
}
#endif /* IDETAPE_DEBUG_BUGS */
- count = IDETAPE_MIN (bh->b_size - bh->b_count, bcount);
+ count = IDE_MIN (bh->b_size - bh->b_count, bcount);
atapi_input_bytes (drive, bh->b_data + bh->b_count, count);
bcount -= count; bh->b_count += count;
if (bh->b_count == bh->b_size) {
@@ -1077,7 +1072,7 @@
{
struct buffer_head *bh = pc->bh;
int count;
-
+
while (bcount) {
#if IDETAPE_DEBUG_BUGS
if (bh == NULL) {
@@ -1085,7 +1080,7 @@
return;
}
#endif /* IDETAPE_DEBUG_BUGS */
- count = IDETAPE_MIN (pc->b_count, bcount);
+ count = IDE_MIN (pc->b_count, bcount);
atapi_output_bytes (drive, pc->b_data, count);
bcount -= count; pc->b_data += count; pc->b_count -= count;
if (!pc->b_count) {
@@ -1113,7 +1108,7 @@
return;
}
#endif /* IDETAPE_DEBUG_BUGS */
- count = IDETAPE_MIN (bh->b_size, bcount);
+ count = IDE_MIN (bh->b_size, bcount);
bh->b_count = count;
if (bh->b_count == bh->b_size)
bh = bh->b_reqnext;
@@ -1124,40 +1119,6 @@
#endif /* CONFIG_BLK_DEV_TRITON */
/*
- * idetape_poll_for_dsc gets invoked by a timer (which was set
- * by idetape_postpone_request) to reinsert our postponed request
- * into the request queue.
- *
- * Note that the procedure done here is different than the method
- * we are using in idetape_queue_pc_head - There we are putting
- * request(s) before our currently called request.
- *
- * Here, on the other hand, HWGROUP(drive)->rq is not our request
- * but rather a request to another device. Therefore, we will let
- * it finish and only then service our postponed request --> We don't
- * touch HWGROUP(drive)->rq.
- */
-static void idetape_poll_for_dsc (unsigned long data)
-{
- ide_drive_t *drive=(ide_drive_t *) data;
- idetape_tape_t *tape = drive->driver_data;
-
- del_timer (&tape->dsc_timer);
-
-#if IDETAPE_DEBUG_LOG
- printk (KERN_INFO "ide-tape: Putting back postponed request\n");
-#endif /* IDETAPE_DEBUG_LOG */
-#if IDETAPE_DEBUG_BUGS
- if (tape->postponed_rq == NULL) {
- printk (KERN_ERR "tape->postponed_rq is NULL in idetape_poll_for_dsc\n");
- return;
- }
-#endif /* IDETAPE_DEBUG_BUGS */
-
- (void) ide_do_drive_cmd (drive, tape->postponed_rq, ide_next);
-}
-
-/*
* idetape_postpone_request postpones the current request so that
* ide.c will be able to service requests from another device on
* the same hwgroup while we are polling for DSC.
@@ -1165,33 +1126,9 @@
static void idetape_postpone_request (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
- struct request *rq;
-
-#if IDETAPE_DEBUG_LOG
- printk (KERN_INFO "Reached idetape_postpone_request\n");
-#endif /* IDETAPE_DEBUG_LOG */
-#if IDETAPE_DEBUG_BUGS
- if (tape->postponed_rq != NULL)
- printk (KERN_ERR "ide-tape.c bug - postponed_rq not NULL in idetape_postpone_request\n");
-#endif /* IDETAPE_DEBUG_BUGS */
-
- /*
- * Set the timer parameters.
- */
- tape->dsc_timer.expires=jiffies + tape->dsc_polling_frequency;
- tape->dsc_timer.data=(unsigned long) drive;
- tape->dsc_timer.function = &idetape_poll_for_dsc;
- init_timer (&tape->dsc_timer);
-
- /*
- * Remove current request from the request queue:
- */
- tape->postponed_rq = rq = HWGROUP(drive)->rq;
- rq->rq_status = IDETAPE_RQ_POSTPONED;
- blk_dev[MAJOR(rq->rq_dev)].current_request = rq->next;
- HWGROUP(drive)->rq = NULL;
- add_timer(&tape->dsc_timer); /* Activate the polling timer */
+ tape->postponed_rq = HWGROUP(drive)->rq;
+ ide_stall_queue(drive, tape->dsc_polling_frequency);
}
/*
@@ -1222,7 +1159,7 @@
ide_init_drive_cmd (rq);
rq->buffer = (char *) pc;
- rq->cmd = IDETAPE_PC_RQ;
+ rq->cmd = IDETAPE_PC_RQ1;
(void) ide_do_drive_cmd (drive, rq, ide_preempt);
}
@@ -1402,7 +1339,7 @@
return;
}
#endif /* IDETAPE_DEBUG_BUGS */
- count = IDETAPE_MIN (bh->b_size - bh->b_count, n);
+ count = IDE_MIN (bh->b_size - bh->b_count, n);
copy_from_user (bh->b_data + bh->b_count, buf, count);
n -= count; bh->b_count += count; buf += count;
if (bh->b_count == bh->b_size) {
@@ -1426,7 +1363,7 @@
return;
}
#endif /* IDETAPE_DEBUG_BUGS */
- count = IDETAPE_MIN (tape->b_count, n);
+ count = IDE_MIN (tape->b_count, n);
copy_to_user (buf, tape->b_data, count);
n -= count; tape->b_data += count; tape->b_count -= count; buf += count;
if (!tape->b_count) {
@@ -1477,7 +1414,7 @@
printk (KERN_INFO "Reached idetape_increase_max_pipeline_stages\n");
#endif /* IDETAPE_DEBUG_LOG */
- tape->max_stages = IDETAPE_MIN (tape->max_stages + IDETAPE_INCREASE_STAGES_RATE, IDETAPE_MAX_PIPELINE_STAGES);
+ tape->max_stages = IDE_MIN (tape->max_stages + IDETAPE_INCREASE_STAGES_RATE, IDETAPE_MAX_PIPELINE_STAGES);
}
/*
@@ -2295,7 +2232,7 @@
}
#if IDETAPE_DEBUG_BUGS
if (postponed_rq != NULL)
- if (postponed_rq->rq_status != RQ_ACTIVE || rq != postponed_rq) {
+ if (rq != postponed_rq) {
printk (KERN_ERR "ide-tape: ide-tape.c bug - Two DSC requests were queued\n");
idetape_end_request (0,HWGROUP (drive));
return;
@@ -2309,6 +2246,8 @@
* the other device meanwhile.
*/
status.all = GET_STAT();
+ if (!drive->dsc_overlap && rq->cmd != IDETAPE_PC_RQ2)
+ set_bit (IDETAPE_IGNORE_DSC, &tape->flags);
if (!clear_bit (IDETAPE_IGNORE_DSC, &tape->flags) && !status.b.dsc) {
if (postponed_rq == NULL) {
tape->dsc_polling_start = jiffies;
@@ -2316,7 +2255,7 @@
tape->dsc_timeout = jiffies + IDETAPE_DSC_RW_TIMEOUT;
} else if ((signed long) (jiffies - tape->dsc_timeout) > 0) {
printk (KERN_ERR "ide-tape: %s: DSC timeout\n", tape->name);
- if (rq->cmd == IDETAPE_PC_RQ)
+ if (rq->cmd == IDETAPE_PC_RQ2)
idetape_media_access_finished (drive);
else
ide_do_reset (drive);
@@ -2340,13 +2279,13 @@
rq->errors = IDETAPE_ERROR_EOD;
idetape_end_request (1, HWGROUP(drive));
return;
- case IDETAPE_PC_RQ:
- if (postponed_rq != NULL) {
- idetape_media_access_finished (drive);
- return;
- }
+ case IDETAPE_PC_RQ1:
pc=(idetape_pc_t *) rq->buffer;
+ rq->cmd = IDETAPE_PC_RQ2;
break;
+ case IDETAPE_PC_RQ2:
+ idetape_media_access_finished (drive);
+ return;
default:
printk (KERN_ERR "ide-tape: bug in IDETAPE_RQ_CMD macro\n");
idetape_end_request (0,HWGROUP (drive));
@@ -2381,7 +2320,7 @@
ide_init_drive_cmd (&rq);
rq.buffer = (char *) pc;
- rq.cmd = IDETAPE_PC_RQ;
+ rq.cmd = IDETAPE_PC_RQ1;
return ide_do_drive_cmd (drive, &rq, ide_wait);
}
@@ -2640,11 +2579,11 @@
while (bcount) {
bh = tape->merge_stage->bh;
- count = IDETAPE_MIN (tape->stage_size, bcount);
+ count = IDE_MIN (tape->stage_size, bcount);
bcount -= count;
blocks = count / tape->tape_block_size;
while (count) {
- bh->b_count = IDETAPE_MIN (count, bh->b_size);
+ bh->b_count = IDE_MIN (count, bh->b_size);
memset (bh->b_data, 0, bh->b_count);
count -= bh->b_count;
bh = bh->b_reqnext;
@@ -2839,7 +2778,7 @@
static ide_drive_t *get_drive_ptr (kdev_t i_rdev)
{
unsigned int i = MINOR(i_rdev) & ~0x80;
-
+
if (i >= MAX_HWIFS * MAX_DRIVES)
return NULL;
return (idetape_chrdevs[i].drive);
@@ -2948,7 +2887,7 @@
{
ide_drive_t *drive = get_drive_ptr (inode->i_rdev);
idetape_tape_t *tape = drive->driver_data;
- int bytes_read,temp,actually_read=0, original_count = count;
+ int bytes_read,temp,actually_read=0;
#if IDETAPE_DEBUG_LOG
printk (KERN_INFO "Reached idetape_chrdev_read\n");
@@ -2988,7 +2927,7 @@
if (count==0)
return (0);
if (tape->merge_stage_size) {
- actually_read=IDETAPE_MIN (tape->merge_stage_size,count);
+ actually_read=IDE_MIN (tape->merge_stage_size,count);
idetape_copy_stage_to_user (tape, buf, tape->merge_stage, actually_read);
buf += actually_read; tape->merge_stage_size -= actually_read; count-=actually_read;
}
@@ -3003,13 +2942,13 @@
bytes_read=idetape_add_chrdev_read_request (drive, tape->capabilities.ctl);
if (bytes_read <= 0)
goto finish;
- temp=IDETAPE_MIN (count,bytes_read);
+ temp=IDE_MIN (count,bytes_read);
idetape_copy_stage_to_user (tape, buf, tape->merge_stage, temp);
actually_read+=temp;
tape->merge_stage_size=bytes_read-temp;
}
finish:
- if (actually_read < original_count && test_bit (IDETAPE_FILEMARK, &tape->flags))
+ if (!actually_read && test_bit (IDETAPE_FILEMARK, &tape->flags))
idetape_space_over_filemarks (drive, MTFSF, 1);
return (actually_read);
}
@@ -3063,7 +3002,7 @@
tape->merge_stage_size=0;
}
#endif /* IDETAPE_DEBUG_BUGS */
- actually_written=IDETAPE_MIN (tape->stage_size-tape->merge_stage_size,count);
+ actually_written=IDE_MIN (tape->stage_size-tape->merge_stage_size,count);
idetape_copy_stage_from_user (tape, tape->merge_stage, buf, actually_written);
buf+=actually_written;tape->merge_stage_size+=actually_written;count-=actually_written;
@@ -3577,9 +3516,11 @@
{
ide_hwif_t *hwif = HWIF(drive);
unsigned long t1, tmid, tn, t;
+ u16 speed;
drive->driver_data = tape;
drive->ready_stat = 0; /* An ATAPI device ignores DRDY */
+ drive->dsc_overlap = 1;
memset (tape, 0, sizeof (idetape_tape_t));
tape->drive = drive;
tape->minor = minor;
@@ -3609,9 +3550,10 @@
* good latency and good system throughput. It will be nice to
* have all this configurable in run time at some point.
*/
- t1 = (tape->stage_size * HZ) / (tape->capabilities.speed * 1000);
- tmid = (tape->capabilities.buffer_size * 32 * HZ) / (tape->capabilities.speed * 125);
- tn = (IDETAPE_FIFO_THRESHOLD * tape->stage_size * HZ) / (tape->capabilities.speed * 1000);
+ speed = IDE_MAX (tape->capabilities.speed, tape->capabilities.max_speed);
+ t1 = (tape->stage_size * HZ) / (speed * 1000);
+ tmid = (tape->capabilities.buffer_size * 32 * HZ) / (speed * 125);
+ tn = (IDETAPE_FIFO_THRESHOLD * tape->stage_size * HZ) / (speed * 1000);
if (tape->max_stages) {
if (drive->using_dma)
@@ -3624,12 +3566,12 @@
}
} else
t = t1;
- t = IDETAPE_MIN (t, tmid);
+ t = IDE_MIN (t, tmid);
/*
* Ensure that the number we got makes sense.
*/
- tape->best_dsc_rw_frequency = IDETAPE_MAX (IDETAPE_MIN (t, IDETAPE_DSC_RW_MAX), IDETAPE_DSC_RW_MIN);
+ tape->best_dsc_rw_frequency = IDE_MAX (IDE_MIN (t, IDETAPE_DSC_RW_MAX), IDETAPE_DSC_RW_MIN);
if (tape->best_dsc_rw_frequency != t) {
printk (KERN_NOTICE "ide-tape: Although the recommended polling period is %lu jiffies\n", t);
printk (KERN_NOTICE "ide-tape: we will use %lu jiffies\n", tape->best_dsc_rw_frequency);
@@ -3681,6 +3623,7 @@
ide_tape, /* media */
1, /* busy */
1, /* supports_dma */
+ 1, /* supports_dsc_overlap */
idetape_cleanup, /* cleanup */
idetape_do_request, /* do_request */
idetape_end_request, /* end_request */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov