lkml.org 
[lkml]   [2002]   [Nov]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patches in this message
/
Date
From
SubjectFixes for the ide-tape driver
Alan Cox and lkml:

I have accumulated a series of changes for the ide-tape driver. They
address a number of problems, but primarily they fix the use of DMA (which
did not work at all previously) and the handling of filemarks. These
changes are essential for use of my Seagate TapeStor 20GB ATAPI drive.

There doesn't seem to be an official maintainer for the ide-tape driver,
although Willem Riede handles the OnStream maintenance. I have sent my
changes to him for testing, and he has said that they work properly on his
system. Therefore I am sending my patches to the list for any additional
testing and to you for inclusion in the official kernel source.

Thank you.

Alan Stern
--- linux/drivers/ide/ide-tape.c.orig Wed Oct 16 11:47:36 2002
+++ linux/drivers/ide/ide-tape.c Thu Oct 17 15:12:28 2002
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/ide-tape.c Version 1.17a Jan, 2001
+ * linux/drivers/ide/ide-tape.c Version 1.17b Oct, 2002
*
* Copyright (C) 1995 - 1999 Gadi Oxman <gadio@netvision.net.il>
*
@@ -291,6 +291,28 @@
* Ver 1.17a Apr 2001 Willem Riede osst@riede.org
* - Get drive's actual block size from mode sense block descriptor
* - Limit size of pipeline
+ * Ver 1.17b Oct 2002 Alan Stern <stern@rowland.harvard.edu>
+ * Changed IDETAPE_MIN_PIPELINE_STAGES to 1 and actually used
+ * it in the code!
+ * Actually removed aborted stages in idetape_abort_pipeline
+ * instead of just changing the command code.
+ * Made the transfer byte count for Request Sense equal to the
+ * actual length of the data transfer.
+ * Changed handling of partial data transfers: they do not
+ * cause DMA errors.
+ * Moved initiation of DMA transfers to the correct place.
+ * Removed reference to unallocated memory.
+ * Made __idetape_discard_read_pipeline return the number of
+ * sectors skipped, not the number of stages.
+ * Replaced errant kfree() calls with __idetape_kfree_stage().
+ * Fixed off-by-one error in testing the pipeline length.
+ * Fixed handling of filemarks in the read pipeline.
+ * Small code optimization for MTBSF and MTBSFM ioctls.
+ * Don't try to unlock the door during device close if is
+ * already unlocked!
+ * Cosmetic fixes to miscellaneous debugging output messages.
+ * Set the minimum /proc/ide/hd?/settings values for "pipeline",
+ * "pipeline_min", and "pipeline_max" to 1.
*
* Here are some words from the first releases of hd.c, which are quoted
* in ide.c and apply here as well:
@@ -400,7 +422,7 @@
* sharing a (fast) ATA-2 disk with any (slow) new ATAPI device.
*/

-#define IDETAPE_VERSION "1.17a"
+#define IDETAPE_VERSION "1.17b"

#include <linux/config.h>
#include <linux/module.h>
@@ -577,9 +599,10 @@
* whenever we sense that the pipeline is empty, until we reach
* the optimum value or until we reach MAX.
*
- * Setting the following parameter to 0 will disable the pipelined mode.
+ * Setting the following parameter to 0 is illegal: the pipelined mode
+ * cannot be disabled (calculate_speeds() divides by tape->max_stages.)
*/
-#define IDETAPE_MIN_PIPELINE_STAGES 200
+#define IDETAPE_MIN_PIPELINE_STAGES 1
#define IDETAPE_MAX_PIPELINE_STAGES 400
#define IDETAPE_INCREASE_STAGES_RATE 20

@@ -601,8 +624,8 @@
* is verified to be stable enough. This will make it much more
* esthetic.
*/
-#define IDETAPE_DEBUG_INFO 1
-#define IDETAPE_DEBUG_LOG 1
+#define IDETAPE_DEBUG_INFO 0
+#define IDETAPE_DEBUG_LOG 0
#define IDETAPE_DEBUG_LOG_VERBOSE 0
#define IDETAPE_DEBUG_BUGS 1

@@ -1696,24 +1719,6 @@
}
}

-static void idetape_abort_pipeline (ide_drive_t *drive)
-{
- idetape_tape_t *tape = drive->driver_data;
- idetape_stage_t *stage = tape->next_stage;
-
-#if IDETAPE_DEBUG_LOG
- if (tape->debug_level >= 4)
- printk(KERN_INFO "ide-tape: %s: idetape_abort_pipeline called\n", tape->name);
-#endif
- while (stage) {
- if (stage->rq.cmd == IDETAPE_WRITE_RQ)
- stage->rq.cmd = IDETAPE_ABORTED_WRITE_RQ;
- else if (stage->rq.cmd == IDETAPE_READ_RQ)
- stage->rq.cmd = IDETAPE_ABORTED_READ_RQ;
- stage = stage->next;
- }
-}
-
/*
* idetape_active_next_stage will declare the next stage as "active".
*/
@@ -1758,7 +1763,7 @@
printk (KERN_INFO "ide-tape: Reached idetape_increase_max_pipeline_stages\n");
#endif /* IDETAPE_DEBUG_LOG */

- tape->max_stages += increase;
+ tape->max_stages += IDE_MAX(increase, 1);
tape->max_stages = IDE_MAX(tape->max_stages, tape->min_pipeline);
tape->max_stages = IDE_MIN(tape->max_stages, tape->max_pipeline);
}
@@ -1831,6 +1836,29 @@
}
}

+static void idetape_abort_pipeline (ide_drive_t *drive, idetape_stage_t *last_stage)
+{
+ idetape_tape_t *tape = drive->driver_data;
+ idetape_stage_t *stage = tape->next_stage;
+ idetape_stage_t *nstage;
+
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 4)
+ printk(KERN_INFO "ide-tape: %s: idetape_abort_pipeline called\n", tape->name);
+#endif
+ while (stage) {
+ nstage = stage->next;
+ idetape_kfree_stage(tape, stage);
+ --tape->nr_stages;
+ --tape->nr_pending_stages;
+ stage = nstage;
+ }
+ tape->last_stage = last_stage;
+ if (last_stage)
+ last_stage->next = NULL;
+ tape->next_stage = NULL;
+}
+
/*
* idetape_end_request is used to finish servicing a request, and to
* insert a pending pipeline request into the main device queue.
@@ -1843,6 +1871,7 @@
unsigned long flags;
int error;
int remove_stage = 0;
+ idetape_stage_t *active_stage;
#if ONSTREAM_DEBUG
idetape_stage_t *stage;
os_aux_t *aux;
@@ -1865,6 +1894,7 @@

spin_lock_irqsave(&tape->spinlock, flags);
if (tape->active_data_request == rq) { /* The request was a pipelined data transfer request */
+ active_stage = tape->active_stage;
tape->active_stage = NULL;
tape->active_data_request = NULL;
tape->nr_pending_stages--;
@@ -1887,15 +1917,17 @@
printk("ide-tape: %s: skipping over config parition..\n", tape->name);
#endif
tape->onstream_write_error = OS_PART_ERROR;
- if (tape->waiting)
+ if (tape->waiting) {
+ rq->waiting = NULL;
complete(tape->waiting);
+ }
}
}
remove_stage = 1;
if (error) {
set_bit (IDETAPE_PIPELINE_ERROR, &tape->flags);
if (error == IDETAPE_ERROR_EOD)
- idetape_abort_pipeline (drive);
+ idetape_abort_pipeline(drive, active_stage);
if (tape->onstream && !tape->raw && error == IDETAPE_ERROR_GENERAL && tape->sense.sense_key == 3) {
clear_bit (IDETAPE_PIPELINE_ERROR, &tape->flags);
printk(KERN_ERR "ide-tape: %s: write error, enabling error recovery\n", tape->name);
@@ -1904,14 +1936,16 @@
tape->nr_pending_stages++;
tape->next_stage = tape->first_stage;
rq->current_nr_sectors = rq->nr_sectors;
- if (tape->waiting)
+ if (tape->waiting) {
+ rq->waiting = NULL;
complete(tape->waiting);
+ }
}
}
} else if (rq->cmd == IDETAPE_READ_RQ) {
if (error == IDETAPE_ERROR_EOD) {
set_bit (IDETAPE_PIPELINE_ERROR, &tape->flags);
- idetape_abort_pipeline(drive);
+ idetape_abort_pipeline(drive, active_stage);
}
}
if (tape->next_stage != NULL && !tape->onstream_write_error) {
@@ -1957,7 +1991,7 @@
idetape_init_pc (pc);
pc->c[0] = IDETAPE_REQUEST_SENSE_CMD;
pc->c[4] = 20;
- pc->request_transfer = 18;
+ pc->request_transfer = 20;
pc->callback = &idetape_request_sense_callback;
}

@@ -2057,7 +2091,7 @@

#ifdef CONFIG_BLK_DEV_IDEDMA
if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
- if (HWIF(drive)->dmaproc(ide_dma_end, drive)) {
+ if (HWIF(drive)->dmaproc(ide_dma_end, drive) || status.b.check) {
/*
* A DMA error is sometimes expected. For example,
* if the tape is crossing a filemark during a
@@ -2069,8 +2103,18 @@
* actually transferred (we can't receive that
* information from the DMA engine on most chipsets).
*/
+
+ /*
+ * On the contrary, a DMA error is never expected;
+ * it usually indicates a hardware error or abort.
+ * If the tape crosses a filemark during a READ
+ * command, it will issue an irq and position itself
+ * after the filemark (not before). Only a partial
+ * data transfer will occur, but no DMA error.
+ * (AS, 19 Apr 2001)
+ */
set_bit (PC_DMA_ERROR, &pc->flags);
- } else if (!status.b.check) {
+ } else {
pc->actually_transferred = pc->request_transfer;
idetape_update_buffers (pc);
}
@@ -2103,7 +2147,7 @@
if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) { /* Error detected */
#if IDETAPE_DEBUG_LOG
if (tape->debug_level >= 1)
- printk (KERN_INFO "ide-tape: %s: I/O error, ",tape->name);
+ printk(KERN_INFO "ide-tape: %s: I/O error\n",tape->name);
#endif /* IDETAPE_DEBUG_LOG */
if (pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
printk (KERN_ERR "ide-tape: I/O error in request sense command\n");
@@ -2255,6 +2299,10 @@
}
tape->cmd_start_time = jiffies;
ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* Set the interrupt routine */
+#ifdef CONFIG_BLK_DEV_IDEDMA
+ if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) /* Begin DMA, if necessary */
+ (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
+#endif
atapi_output_bytes (drive,pc->c,12); /* Send the actual packet */
return ide_started;
}
@@ -2279,8 +2327,7 @@
/*
* We will "abort" retrying a packet command in case
* a legitimate error code was received (crossing a
- * filemark, or DMA error in the end of media, for
- * example).
+ * filemark, or end of the media, for example).
*/
if (!test_bit (PC_ABORT, &pc->flags)) {
if (!(pc->c[0] == IDETAPE_TEST_UNIT_READY_CMD && tape->sense_key == 2 &&
@@ -2297,7 +2344,7 @@
}
#if IDETAPE_DEBUG_LOG
if (tape->debug_level >= 2)
- printk (KERN_INFO "ide-tape: Retry number - %d\n", pc->retries);
+ printk(KERN_INFO "ide-tape: Retry number - %d, cmd = %02X\n", pc->retries, pc->c[0]);
#endif /* IDETAPE_DEBUG_LOG */

pc->retries++;
@@ -2321,9 +2368,8 @@
OUT_BYTE (bcount.b.low, IDE_BCOUNTL_REG);
OUT_BYTE (drive->select.all, IDE_SELECT_REG);
#ifdef CONFIG_BLK_DEV_IDEDMA
- if (dma_ok) { /* Begin DMA, if necessary */
+ if (dma_ok) { /* Will begin DMA later */
set_bit (PC_DMA_IN_PROGRESS, &pc->flags);
- (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
}
#endif /* CONFIG_BLK_DEV_IDEDMA */
if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
@@ -3086,7 +3132,7 @@
tape->waiting = &wait;
spin_unlock(&tape->spinlock);
wait_for_completion(&wait);
- rq->waiting = NULL;
+ /* The stage and its struct request have been deallocated */
tape->waiting = NULL;
spin_lock_irq(&tape->spinlock);
}
@@ -3345,11 +3391,15 @@

if (tape->chrdev_direction != idetape_direction_read)
return 0;
+ cnt = tape->merge_stage_size / tape->tape_block_size;
+ if (test_and_clear_bit(IDETAPE_FILEMARK, &tape->flags))
+ ++cnt; /* Filemarks count as 1 sector */
tape->merge_stage_size = 0;
if (tape->merge_stage != NULL) {
__idetape_kfree_stage (tape->merge_stage);
tape->merge_stage = NULL;
}
+ clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
tape->chrdev_direction = idetape_direction_none;

if (tape->first_stage == NULL)
@@ -3361,9 +3411,14 @@
idetape_wait_for_request(drive, tape->active_data_request);
spin_unlock_irqrestore(&tape->spinlock, flags);

- cnt = tape->nr_stages - tape->nr_pending_stages;
- while (tape->first_stage != NULL)
- idetape_remove_stage_head (drive);
+ while (tape->first_stage != NULL) {
+ struct request *rq_ptr = &tape->first_stage->rq;
+
+ cnt += rq_ptr->nr_sectors - rq_ptr->current_nr_sectors;
+ if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK)
+ ++cnt;
+ idetape_remove_stage_head(drive);
+ }
tape->nr_pending_stages = 0;
tape->max_stages = tape->min_pipeline;
return cnt;
@@ -3951,7 +4006,7 @@
*/
bytes_read = idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, 0, tape->merge_stage->bh);
if (bytes_read < 0) {
- kfree (tape->merge_stage);
+ __idetape_kfree_stage(tape->merge_stage);
tape->merge_stage = NULL;
tape->chrdev_direction = idetape_direction_none;
return bytes_read;
@@ -3963,7 +4018,7 @@
rq.cmd = IDETAPE_READ_RQ;
rq.sector = tape->first_frame_position;
rq.nr_sectors = rq.current_nr_sectors = blocks;
- if (!test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags) && tape->nr_stages <= max_stages) {
+ if (!test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags) && tape->nr_stages < max_stages) {
new_stage = idetape_kmalloc_stage (tape);
while (new_stage != NULL) {
new_stage->rq = rq;
@@ -4073,6 +4128,12 @@
#endif /* IDETAPE_DEBUG_LOG */

/*
+ * If we are at a filemark, return a read length of 0
+ */
+ if (test_bit(IDETAPE_FILEMARK, &tape->flags))
+ return 0;
+
+ /*
* Wait for the next logical block to be available at the head
* of the pipeline
*/
@@ -4099,14 +4160,7 @@
}
if (rq_ptr->errors == IDETAPE_ERROR_EOD)
return 0;
- if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK) {
- idetape_switch_buffers (tape, tape->first_stage);
- set_bit (IDETAPE_FILEMARK, &tape->flags);
-#if USE_IOTRACE
- IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
-#endif
- calculate_speeds(drive);
- } else {
+ else {
idetape_switch_buffers (tape, tape->first_stage);
if (rq_ptr->errors == IDETAPE_ERROR_GENERAL) {
#if ONSTREAM_DEBUG
@@ -4114,7 +4168,8 @@
printk(KERN_INFO "ide-tape: error detected, bytes_read %d\n", bytes_read);
#endif
}
- clear_bit (IDETAPE_FILEMARK, &tape->flags);
+ if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK)
+ set_bit(IDETAPE_FILEMARK, &tape->flags);
spin_lock_irqsave(&tape->spinlock, flags);
idetape_remove_stage_head (drive);
spin_unlock_irqrestore(&tape->spinlock, flags);
@@ -4478,6 +4533,14 @@
tape->restart_speed_control_req = 1;
return retval;
}
+
+ if (mt_count == 0)
+ return 0;
+ if (MTBSF == mt_op || MTBSFM == mt_op) {
+ if (!tape->capabilities.sprev)
+ return -EIO;
+ mt_count = - mt_count;
+ }

if (tape->chrdev_direction == idetape_direction_read) {
/*
@@ -4485,28 +4548,36 @@
* filemarks.
*/
tape->merge_stage_size = 0;
- clear_bit (IDETAPE_FILEMARK, &tape->flags);
+ if (test_and_clear_bit(IDETAPE_FILEMARK, &tape->flags))
+ ++count;
while (tape->first_stage != NULL) {
- idetape_wait_first_stage(drive);
- if (tape->first_stage->rq.errors == IDETAPE_ERROR_FILEMARK)
- count++;
if (count == mt_count) {
- switch (mt_op) {
- case MTFSF:
- spin_lock_irqsave(&tape->spinlock, flags);
- idetape_remove_stage_head (drive);
- spin_unlock_irqrestore(&tape->spinlock, flags);
- case MTFSFM:
- return (0);
- default:
- break;
- }
+ if (mt_op == MTFSFM)
+ set_bit(IDETAPE_FILEMARK, &tape->flags);
+ return 0;
}
spin_lock_irqsave(&tape->spinlock, flags);
+ if (tape->first_stage == tape->active_stage) {
+ /*
+ * We have reached the active stage in the read pipeline.
+ * There is no point in allowing the drive to continue
+ * reading any farther, so we stop the pipeline.
+ *
+ * This section should be moved to a separate subroutine,
+ * because a similar function is performed in
+ * __idetape_discard_read_pipeline(), for example.
+ */
+ tape->next_stage = NULL;
+ spin_unlock_irqrestore(&tape->spinlock, flags);
+ idetape_wait_first_stage(drive);
+ tape->next_stage = tape->first_stage->next;
+ } else
+ spin_unlock_irqrestore(&tape->spinlock, flags);
+ if (tape->first_stage->rq.errors == IDETAPE_ERROR_FILEMARK)
+ ++count;
idetape_remove_stage_head (drive);
- spin_unlock_irqrestore(&tape->spinlock, flags);
}
- idetape_discard_read_pipeline (drive, 1);
+ idetape_discard_read_pipeline(drive, 0);
}

/*
@@ -4515,25 +4586,17 @@
*/
switch (mt_op) {
case MTFSF:
+ case MTBSF:
idetape_create_space_cmd (&pc,mt_count-count,IDETAPE_SPACE_OVER_FILEMARK);
return (idetape_queue_pc_tail (drive, &pc));
case MTFSFM:
- if (!tape->capabilities.sprev)
- return (-EIO);
- retval = idetape_space_over_filemarks (drive, MTFSF, mt_count-count);
- if (retval) return (retval);
- return (idetape_space_over_filemarks (drive, MTBSF, 1));
- case MTBSF:
- if (!tape->capabilities.sprev)
- return (-EIO);
- idetape_create_space_cmd (&pc,-(mt_count+count),IDETAPE_SPACE_OVER_FILEMARK);
- return (idetape_queue_pc_tail (drive, &pc));
case MTBSFM:
if (!tape->capabilities.sprev)
return (-EIO);
- retval = idetape_space_over_filemarks (drive, MTBSF, mt_count+count);
+ retval = idetape_space_over_filemarks(drive, MTFSF, mt_count-count);
if (retval) return (retval);
- return (idetape_space_over_filemarks (drive, MTFSF, 1));
+ count = (MTBSFM == mt_op ? 1 : -1);
+ return (idetape_space_over_filemarks(drive, MTFSF, count));
default:
printk (KERN_ERR "ide-tape: MTIO operation %d not supported\n",mt_op);
return (-EIO);
@@ -4862,7 +4925,7 @@
*/
retval = idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, 0, tape->merge_stage->bh);
if (retval < 0) {
- kfree (tape->merge_stage);
+ __idetape_kfree_stage(tape->merge_stage);
tape->merge_stage = NULL;
tape->chrdev_direction = idetape_direction_none;
return retval;
@@ -5436,9 +5499,11 @@
MOD_DEC_USE_COUNT;
return -EBUSY;
}
- idetape_read_position(drive);
+ if (tape->onstream)
+ idetape_read_position(drive);
MOD_DEC_USE_COUNT;
- clear_bit (IDETAPE_PIPELINE_ERROR, &tape->flags);
+ if (tape->chrdev_direction != idetape_direction_read)
+ clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);

if (tape->chrdev_direction == idetape_direction_none) {
MOD_INC_USE_COUNT;
@@ -5511,10 +5576,11 @@
if (minor < 128)
(void) idetape_rewind_tape (drive);
if (tape->chrdev_direction == idetape_direction_none) {
- if (tape->door_locked != DOOR_EXPLICITLY_LOCKED) {
- if (idetape_create_prevent_cmd(drive, &pc, 0))
+ if (tape->door_locked == DOOR_LOCKED) {
+ if (idetape_create_prevent_cmd(drive, &pc, 0)) {
if (!idetape_queue_pc_tail (drive, &pc))
tape->door_locked = DOOR_UNLOCKED;
+ }
}
MOD_DEC_USE_COUNT;
}
@@ -5548,34 +5614,34 @@
printk (KERN_INFO "ide-tape: Dumping ATAPI Identify Device tape parameters\n");
printk (KERN_INFO "ide-tape: Protocol Type: ");
switch (gcw.protocol) {
- case 0: case 1: printk (KERN_INFO "ATA\n");break;
- case 2: printk (KERN_INFO "ATAPI\n");break;
- case 3: printk (KERN_INFO "Reserved (Unknown to ide-tape)\n");break;
+ case 0: case 1: printk ("ATA\n");break;
+ case 2: printk ("ATAPI\n");break;
+ case 3: printk ("Reserved (Unknown to ide-tape)\n");break;
}
printk (KERN_INFO "ide-tape: Device Type: %x - ",gcw.device_type);
switch (gcw.device_type) {
- case 0: printk (KERN_INFO "Direct-access Device\n");break;
- case 1: printk (KERN_INFO "Streaming Tape Device\n");break;
- case 2: case 3: case 4: printk (KERN_INFO "Reserved\n");break;
- case 5: printk (KERN_INFO "CD-ROM Device\n");break;
- case 6: printk (KERN_INFO "Reserved\n");
- case 7: printk (KERN_INFO "Optical memory Device\n");break;
- case 0x1f: printk (KERN_INFO "Unknown or no Device type\n");break;
- default: printk (KERN_INFO "Reserved\n");
+ case 0: printk ("Direct-access Device\n");break;
+ case 1: printk ("Streaming Tape Device\n");break;
+ case 2: case 3: case 4: printk ("Reserved\n");break;
+ case 5: printk ("CD-ROM Device\n");break;
+ case 6: printk ("Reserved\n");
+ case 7: printk ("Optical memory Device\n");break;
+ case 0x1f: printk ("Unknown or no Device type\n");break;
+ default: printk ("Reserved\n");
}
printk (KERN_INFO "ide-tape: Removable: %s",gcw.removable ? "Yes\n":"No\n");
printk (KERN_INFO "ide-tape: Command Packet DRQ Type: ");
switch (gcw.drq_type) {
- case 0: printk (KERN_INFO "Microprocessor DRQ\n");break;
- case 1: printk (KERN_INFO "Interrupt DRQ\n");break;
- case 2: printk (KERN_INFO "Accelerated DRQ\n");break;
- case 3: printk (KERN_INFO "Reserved\n");break;
+ case 0: printk ("Microprocessor DRQ\n");break;
+ case 1: printk ("Interrupt DRQ\n");break;
+ case 2: printk ("Accelerated DRQ\n");break;
+ case 3: printk ("Reserved\n");break;
}
printk (KERN_INFO "ide-tape: Command Packet Size: ");
switch (gcw.packet_size) {
- case 0: printk (KERN_INFO "12 bytes\n");break;
- case 1: printk (KERN_INFO "16 bytes\n");break;
- default: printk (KERN_INFO "Reserved\n");break;
+ case 0: printk ("12 bytes\n");break;
+ case 1: printk ("16 bytes\n");break;
+ default: printk ("Reserved\n");break;
}
printk (KERN_INFO "ide-tape: Model: %.40s\n",id->model);
printk (KERN_INFO "ide-tape: Firmware Revision: %.8s\n",id->fw_rev);
@@ -5591,44 +5657,44 @@
printk (KERN_INFO "ide-tape: Single Word DMA supported modes: ");
for (i=0,mask=1;i<8;i++,mask=mask << 1) {
if (id->dma_1word & mask)
- printk (KERN_INFO "%d ",i);
+ printk ("%d ",i);
if (id->dma_1word & (mask << 8))
- printk (KERN_INFO "(active) ");
+ printk ("(active) ");
}
- printk (KERN_INFO "\n");
+ printk ("\n");
printk (KERN_INFO "ide-tape: Multi Word DMA supported modes: ");
for (i=0,mask=1;i<8;i++,mask=mask << 1) {
if (id->dma_mword & mask)
- printk (KERN_INFO "%d ",i);
+ printk ("%d ",i);
if (id->dma_mword & (mask << 8))
- printk (KERN_INFO "(active) ");
+ printk ("(active) ");
}
- printk (KERN_INFO "\n");
+ printk ("\n");
if (id->field_valid & 0x0002) {
printk (KERN_INFO "ide-tape: Enhanced PIO Modes: %s\n",id->eide_pio_modes & 1 ? "Mode 3":"None");
printk (KERN_INFO "ide-tape: Minimum Multi-word DMA cycle per word: ");
if (id->eide_dma_min == 0)
- printk (KERN_INFO "Not supported\n");
+ printk ("Not supported\n");
else
- printk (KERN_INFO "%d ns\n",id->eide_dma_min);
+ printk ("%d ns\n",id->eide_dma_min);

printk (KERN_INFO "ide-tape: Manufacturer\'s Recommended Multi-word cycle: ");
if (id->eide_dma_time == 0)
- printk (KERN_INFO "Not supported\n");
+ printk ("Not supported\n");
else
- printk (KERN_INFO "%d ns\n",id->eide_dma_time);
+ printk ("%d ns\n",id->eide_dma_time);

printk (KERN_INFO "ide-tape: Minimum PIO cycle without IORDY: ");
if (id->eide_pio == 0)
- printk (KERN_INFO "Not supported\n");
+ printk ("Not supported\n");
else
- printk (KERN_INFO "%d ns\n",id->eide_pio);
+ printk ("%d ns\n",id->eide_pio);

printk (KERN_INFO "ide-tape: Minimum PIO cycle with IORDY: ");
if (id->eide_pio_iordy == 0)
- printk (KERN_INFO "Not supported\n");
+ printk ("Not supported\n");
else
- printk (KERN_INFO "%d ns\n",id->eide_pio_iordy);
+ printk ("%d ns\n",id->eide_pio_iordy);

} else
printk (KERN_INFO "ide-tape: According to the device, fields 64-70 are not valid.\n");
@@ -5937,9 +6003,9 @@
* drive setting name read/write ioctl ioctl data type min max mul_factor div_factor data pointer set function
*/
ide_add_setting(drive, "buffer", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 2, &tape->capabilities.buffer_size, NULL);
- ide_add_setting(drive, "pipeline_min", SETTING_RW, -1, -1, TYPE_INT, 2, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL);
- ide_add_setting(drive, "pipeline", SETTING_RW, -1, -1, TYPE_INT, 2, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL);
- ide_add_setting(drive, "pipeline_max", SETTING_RW, -1, -1, TYPE_INT, 2, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL);
+ ide_add_setting(drive, "pipeline_min", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL);
+ ide_add_setting(drive, "pipeline", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL);
+ ide_add_setting(drive, "pipeline_max", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL);
ide_add_setting(drive, "pipeline_used",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_stages, NULL);
ide_add_setting(drive, "pipeline_pending",SETTING_READ,-1, -1, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_pending_stages, NULL);
ide_add_setting(drive, "speed", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->capabilities.speed, NULL);
@@ -6054,8 +6120,11 @@
si_meminfo(&si);
if ( tape->max_stages * tape->stage_size > si.totalram * si.mem_unit / 10)
tape->max_stages = si.totalram * si.mem_unit / (10 * tape->stage_size);
- tape->min_pipeline = tape->max_stages;
- tape->max_pipeline = tape->max_stages * 2;
+ tape->max_stages = IDE_MIN(tape->max_stages, IDETAPE_MAX_PIPELINE_STAGES);
+ tape->min_pipeline = IDE_MIN(tape->max_stages, IDETAPE_MIN_PIPELINE_STAGES);
+ tape->max_pipeline = IDE_MIN(tape->max_stages * 2, IDETAPE_MAX_PIPELINE_STAGES);
+ if (tape->max_stages == 0)
+ tape->max_stages = tape->min_pipeline = tape->max_pipeline = 1;

t1 = (tape->stage_size * HZ) / (speed * 1000);
tmid = (tape->capabilities.buffer_size * 32 * HZ) / (speed * 125);--- linux/drivers/ide/ide-tape.c.orig Thu Oct 17 15:14:50 2002
+++ linux/drivers/ide/ide-tape.c Thu Oct 17 15:15:41 2002
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/ide-tape.c Version 1.17a Jan, 2001
+ * linux/drivers/ide/ide-tape.c Version 1.17b Oct, 2002
*
* Copyright (C) 1995 - 1999 Gadi Oxman <gadio@netvision.net.il>
*
@@ -291,6 +291,28 @@
* Ver 1.17a Apr 2001 Willem Riede osst@riede.org
* - Get drive's actual block size from mode sense block descriptor
* - Limit size of pipeline
+ * Ver 1.17b Oct 2002 Alan Stern <stern@rowland.harvard.edu>
+ * Changed IDETAPE_MIN_PIPELINE_STAGES to 1 and actually used
+ * it in the code!
+ * Actually removed aborted stages in idetape_abort_pipeline
+ * instead of just changing the command code.
+ * Made the transfer byte count for Request Sense equal to the
+ * actual length of the data transfer.
+ * Changed handling of partial data transfers: they do not
+ * cause DMA errors.
+ * Moved initiation of DMA transfers to the correct place.
+ * Removed reference to unallocated memory.
+ * Made __idetape_discard_read_pipeline return the number of
+ * sectors skipped, not the number of stages.
+ * Replaced errant kfree() calls with __idetape_kfree_stage().
+ * Fixed off-by-one error in testing the pipeline length.
+ * Fixed handling of filemarks in the read pipeline.
+ * Small code optimization for MTBSF and MTBSFM ioctls.
+ * Don't try to unlock the door during device close if is
+ * already unlocked!
+ * Cosmetic fixes to miscellaneous debugging output messages.
+ * Set the minimum /proc/ide/hd?/settings values for "pipeline",
+ * "pipeline_min", and "pipeline_max" to 1.
*
* Here are some words from the first releases of hd.c, which are quoted
* in ide.c and apply here as well:
@@ -400,7 +422,7 @@
* sharing a (fast) ATA-2 disk with any (slow) new ATAPI device.
*/

-#define IDETAPE_VERSION "1.17a"
+#define IDETAPE_VERSION "1.17b"

#include <linux/config.h>
#include <linux/module.h>
@@ -577,9 +599,10 @@
* whenever we sense that the pipeline is empty, until we reach
* the optimum value or until we reach MAX.
*
- * Setting the following parameter to 0 will disable the pipelined mode.
+ * Setting the following parameter to 0 is illegal: the pipelined mode
+ * cannot be disabled (calculate_speeds() divides by tape->max_stages.)
*/
-#define IDETAPE_MIN_PIPELINE_STAGES 200
+#define IDETAPE_MIN_PIPELINE_STAGES 1
#define IDETAPE_MAX_PIPELINE_STAGES 400
#define IDETAPE_INCREASE_STAGES_RATE 20

@@ -601,8 +624,8 @@
* is verified to be stable enough. This will make it much more
* esthetic.
*/
-#define IDETAPE_DEBUG_INFO 1
-#define IDETAPE_DEBUG_LOG 1
+#define IDETAPE_DEBUG_INFO 0
+#define IDETAPE_DEBUG_LOG 0
#define IDETAPE_DEBUG_LOG_VERBOSE 0
#define IDETAPE_DEBUG_BUGS 1

@@ -1613,24 +1636,6 @@
}
}

-static void idetape_abort_pipeline (ide_drive_t *drive)
-{
- idetape_tape_t *tape = drive->driver_data;
- idetape_stage_t *stage = tape->next_stage;
-
-#if IDETAPE_DEBUG_LOG
- if (tape->debug_level >= 4)
- printk(KERN_INFO "ide-tape: %s: idetape_abort_pipeline called\n", tape->name);
-#endif
- while (stage) {
- if (stage->rq.flags == IDETAPE_WRITE_RQ)
- stage->rq.flags = IDETAPE_ABORTED_WRITE_RQ;
- else if (stage->rq.flags == IDETAPE_READ_RQ)
- stage->rq.flags = IDETAPE_ABORTED_READ_RQ;
- stage = stage->next;
- }
-}
-
/*
* idetape_active_next_stage will declare the next stage as "active".
*/
@@ -1675,7 +1680,7 @@
printk (KERN_INFO "ide-tape: Reached idetape_increase_max_pipeline_stages\n");
#endif /* IDETAPE_DEBUG_LOG */

- tape->max_stages += increase;
+ tape->max_stages += max(increase, 1);
tape->max_stages = max(tape->max_stages, tape->min_pipeline);
tape->max_stages = min(tape->max_stages, tape->max_pipeline);
}
@@ -1748,6 +1753,29 @@
}
}

+static void idetape_abort_pipeline (ide_drive_t *drive, idetape_stage_t *last_stage)
+{
+ idetape_tape_t *tape = drive->driver_data;
+ idetape_stage_t *stage = tape->next_stage;
+ idetape_stage_t *nstage;
+
+#if IDETAPE_DEBUG_LOG
+ if (tape->debug_level >= 4)
+ printk(KERN_INFO "ide-tape: %s: idetape_abort_pipeline called\n", tape->name);
+#endif
+ while (stage) {
+ nstage = stage->next;
+ idetape_kfree_stage(tape, stage);
+ --tape->nr_stages;
+ --tape->nr_pending_stages;
+ stage = nstage;
+ }
+ tape->last_stage = last_stage;
+ if (last_stage)
+ last_stage->next = NULL;
+ tape->next_stage = NULL;
+}
+
/*
* idetape_end_request is used to finish servicing a request, and to
* insert a pending pipeline request into the main device queue.
@@ -1759,6 +1787,7 @@
unsigned long flags;
int error;
int remove_stage = 0;
+ idetape_stage_t *active_stage;
#if ONSTREAM_DEBUG
idetape_stage_t *stage;
os_aux_t *aux;
@@ -1783,6 +1812,7 @@

/* The request was a pipelined data transfer request */
if (tape->active_data_request == rq) {
+ active_stage = tape->active_stage;
tape->active_stage = NULL;
tape->active_data_request = NULL;
tape->nr_pending_stages--;
@@ -1805,15 +1835,17 @@
printk("ide-tape: %s: skipping over config parition..\n", tape->name);
#endif
tape->onstream_write_error = OS_PART_ERROR;
- if (tape->waiting)
+ if (tape->waiting) {
+ rq->waiting = NULL;
complete(tape->waiting);
+ }
}
}
remove_stage = 1;
if (error) {
set_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
if (error == IDETAPE_ERROR_EOD)
- idetape_abort_pipeline(drive);
+ idetape_abort_pipeline(drive, active_stage);
if (tape->onstream && !tape->raw &&
error == IDETAPE_ERROR_GENERAL &&
tape->sense.sense_key == 3) {
@@ -1824,14 +1856,16 @@
tape->nr_pending_stages++;
tape->next_stage = tape->first_stage;
rq->current_nr_sectors = rq->nr_sectors;
- if (tape->waiting)
+ if (tape->waiting) {
+ rq->waiting = NULL;
complete(tape->waiting);
+ }
}
}
} else if (rq->flags == IDETAPE_READ_RQ) {
if (error == IDETAPE_ERROR_EOD) {
set_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
- idetape_abort_pipeline(drive);
+ idetape_abort_pipeline(drive, active_stage);
}
}
if (tape->next_stage != NULL && !tape->onstream_write_error) {
@@ -1882,7 +1916,7 @@
idetape_init_pc(pc);
pc->c[0] = IDETAPE_REQUEST_SENSE_CMD;
pc->c[4] = 20;
- pc->request_transfer = 18;
+ pc->request_transfer = 20;
pc->callback = &idetape_request_sense_callback;
}

@@ -1984,7 +2018,7 @@

#ifdef CONFIG_BLK_DEV_IDEDMA
if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
- if (HWIF(drive)->ide_dma_end(drive)) {
+ if (HWIF(drive)->ide_dma_end(drive) || status.b.check) {
/*
* A DMA error is sometimes expected. For example,
* if the tape is crossing a filemark during a
@@ -1996,8 +2030,18 @@
* actually transferred (we can't receive that
* information from the DMA engine on most chipsets).
*/
+
+ /*
+ * On the contrary, a DMA error is never expected;
+ * it usually indicates a hardware error or abort.
+ * If the tape crosses a filemark during a READ
+ * command, it will issue an irq and position itself
+ * after the filemark (not before). Only a partial
+ * data transfer will occur, but no DMA error.
+ * (AS, 19 Apr 2001)
+ */
set_bit(PC_DMA_ERROR, &pc->flags);
- } else if (!status.b.check) {
+ } else {
pc->actually_transferred = pc->request_transfer;
idetape_update_buffers(pc);
}
@@ -2034,7 +2078,7 @@
if (status.b.check || test_bit(PC_DMA_ERROR, &pc->flags)) { /* Error detected */
#if IDETAPE_DEBUG_LOG
if (tape->debug_level >= 1)
- printk(KERN_INFO "ide-tape: %s: I/O error, ",
+ printk(KERN_INFO "ide-tape: %s: I/O error\n",
tape->name);
#endif /* IDETAPE_DEBUG_LOG */
if (pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
@@ -2202,6 +2246,10 @@
BUG();
/* Set the interrupt routine */
ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
+#ifdef CONFIG_BLK_DEV_IDEDMA
+ if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) /* Begin DMA, if necessary */
+ (void) (HWIF(drive)->ide_dma_begin(drive));
+#endif
/* Send the actual packet */
HWIF(drive)->atapi_output_bytes(drive, pc->c, 12);
return ide_started;
@@ -2230,8 +2278,7 @@
/*
* We will "abort" retrying a packet command in case
* a legitimate error code was received (crossing a
- * filemark, or DMA error in the end of media, for
- * example).
+ * filemark, or end of the media, for example).
*/
if (!test_bit(PC_ABORT, &pc->flags)) {
if (!(pc->c[0] == IDETAPE_TEST_UNIT_READY_CMD &&
@@ -2256,7 +2303,7 @@
}
#if IDETAPE_DEBUG_LOG
if (tape->debug_level >= 2)
- printk(KERN_INFO "ide-tape: Retry number - %d\n", pc->retries);
+ printk(KERN_INFO "ide-tape: Retry number - %d, cmd = %02X\n", pc->retries, pc->c[0]);
#endif /* IDETAPE_DEBUG_LOG */

pc->retries++;
@@ -2285,9 +2332,8 @@
OUT_BYTE(bcount.b.low, IDE_BCOUNTL_REG);
OUT_BYTE(drive->select.all, IDE_SELECT_REG);
#ifdef CONFIG_BLK_DEV_IDEDMA
- if (dma_ok) { /* Begin DMA, if necessary */
+ if (dma_ok) { /* Will begin DMA later */
set_bit(PC_DMA_IN_PROGRESS, &pc->flags);
- (void) (HWIF(drive)->ide_dma_begin(drive));
}
#endif /* CONFIG_BLK_DEV_IDEDMA */
if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
@@ -3080,7 +3126,7 @@
tape->waiting = &wait;
spin_unlock(&tape->spinlock);
wait_for_completion(&wait);
- rq->waiting = NULL;
+ /* The stage and its struct request have been deallocated */
tape->waiting = NULL;
spin_lock_irq(&tape->spinlock);
}
@@ -3344,11 +3390,15 @@

if (tape->chrdev_direction != idetape_direction_read)
return 0;
+ cnt = tape->merge_stage_size / tape->tape_block_size;
+ if (test_and_clear_bit(IDETAPE_FILEMARK, &tape->flags))
+ ++cnt; /* Filemarks count as 1 sector */
tape->merge_stage_size = 0;
if (tape->merge_stage != NULL) {
__idetape_kfree_stage(tape->merge_stage);
tape->merge_stage = NULL;
}
+ clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
tape->chrdev_direction = idetape_direction_none;

if (tape->first_stage == NULL)
@@ -3360,9 +3410,14 @@
idetape_wait_for_request(drive, tape->active_data_request);
spin_unlock_irqrestore(&tape->spinlock, flags);

- cnt = tape->nr_stages - tape->nr_pending_stages;
- while (tape->first_stage != NULL)
+ while (tape->first_stage != NULL) {
+ struct request *rq_ptr = &tape->first_stage->rq;
+
+ cnt += rq_ptr->nr_sectors - rq_ptr->current_nr_sectors;
+ if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK)
+ ++cnt;
idetape_remove_stage_head(drive);
+ }
tape->nr_pending_stages = 0;
tape->max_stages = tape->min_pipeline;
return cnt;
@@ -3957,7 +4012,7 @@
*/
bytes_read = idetape_queue_rw_tail(drive, IDETAPE_READ_RQ, 0, tape->merge_stage->bio);
if (bytes_read < 0) {
- kfree(tape->merge_stage);
+ __idetape_kfree_stage(tape->merge_stage);
tape->merge_stage = NULL;
tape->chrdev_direction = idetape_direction_none;
return bytes_read;
@@ -3970,7 +4025,7 @@
rq.sector = tape->first_frame_position;
rq.nr_sectors = rq.current_nr_sectors = blocks;
if (!test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags) &&
- tape->nr_stages <= max_stages) {
+ tape->nr_stages < max_stages) {
new_stage = idetape_kmalloc_stage(tape);
while (new_stage != NULL) {
new_stage->rq = rq;
@@ -4080,6 +4135,12 @@
#endif /* IDETAPE_DEBUG_LOG */

/*
+ * If we are at a filemark, return a read length of 0
+ */
+ if (test_bit(IDETAPE_FILEMARK, &tape->flags))
+ return 0;
+
+ /*
* Wait for the next logical block to be available at the head
* of the pipeline
*/
@@ -4108,14 +4169,7 @@
}
if (rq_ptr->errors == IDETAPE_ERROR_EOD)
return 0;
- if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK) {
- idetape_switch_buffers(tape, tape->first_stage);
- set_bit(IDETAPE_FILEMARK, &tape->flags);
-#if USE_IOTRACE
- IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
-#endif
- calculate_speeds(drive);
- } else {
+ else {
idetape_switch_buffers(tape, tape->first_stage);
if (rq_ptr->errors == IDETAPE_ERROR_GENERAL) {
#if ONSTREAM_DEBUG
@@ -4123,7 +4177,8 @@
printk(KERN_INFO "ide-tape: error detected, bytes_read %d\n", bytes_read);
#endif
}
- clear_bit(IDETAPE_FILEMARK, &tape->flags);
+ if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK)
+ set_bit(IDETAPE_FILEMARK, &tape->flags);
spin_lock_irqsave(&tape->spinlock, flags);
idetape_remove_stage_head(drive);
spin_unlock_irqrestore(&tape->spinlock, flags);
@@ -4488,6 +4543,14 @@
tape->restart_speed_control_req = 1;
return retval;
}
+
+ if (mt_count == 0)
+ return 0;
+ if (MTBSF == mt_op || MTBSFM == mt_op) {
+ if (!tape->capabilities.sprev)
+ return -EIO;
+ mt_count = - mt_count;
+ }

if (tape->chrdev_direction == idetape_direction_read) {
/*
@@ -4495,28 +4558,36 @@
* filemarks.
*/
tape->merge_stage_size = 0;
- clear_bit(IDETAPE_FILEMARK, &tape->flags);
+ if (test_and_clear_bit(IDETAPE_FILEMARK, &tape->flags))
+ ++count;
while (tape->first_stage != NULL) {
- idetape_wait_first_stage(drive);
- if (tape->first_stage->rq.errors == IDETAPE_ERROR_FILEMARK)
- count++;
if (count == mt_count) {
- switch (mt_op) {
- case MTFSF:
- spin_lock_irqsave(&tape->spinlock, flags);
- idetape_remove_stage_head(drive);
- spin_unlock_irqrestore(&tape->spinlock, flags);
- case MTFSFM:
- return (0);
- default:
- break;
- }
+ if (mt_op == MTFSFM)
+ set_bit(IDETAPE_FILEMARK, &tape->flags);
+ return 0;
}
spin_lock_irqsave(&tape->spinlock, flags);
+ if (tape->first_stage == tape->active_stage) {
+ /*
+ * We have reached the active stage in the read pipeline.
+ * There is no point in allowing the drive to continue
+ * reading any farther, so we stop the pipeline.
+ *
+ * This section should be moved to a separate subroutine,
+ * because a similar function is performed in
+ * __idetape_discard_read_pipeline(), for example.
+ */
+ tape->next_stage = NULL;
+ spin_unlock_irqrestore(&tape->spinlock, flags);
+ idetape_wait_first_stage(drive);
+ tape->next_stage = tape->first_stage->next;
+ } else
+ spin_unlock_irqrestore(&tape->spinlock, flags);
+ if (tape->first_stage->rq.errors == IDETAPE_ERROR_FILEMARK)
+ ++count;
idetape_remove_stage_head(drive);
- spin_unlock_irqrestore(&tape->spinlock, flags);
}
- idetape_discard_read_pipeline(drive, 1);
+ idetape_discard_read_pipeline(drive, 0);
}

/*
@@ -4525,25 +4596,17 @@
*/
switch (mt_op) {
case MTFSF:
+ case MTBSF:
idetape_create_space_cmd(&pc,mt_count-count,IDETAPE_SPACE_OVER_FILEMARK);
return (idetape_queue_pc_tail(drive, &pc));
case MTFSFM:
- if (!tape->capabilities.sprev)
- return (-EIO);
- retval = idetape_space_over_filemarks(drive, MTFSF, mt_count-count);
- if (retval) return (retval);
- return (idetape_space_over_filemarks(drive, MTBSF, 1));
- case MTBSF:
- if (!tape->capabilities.sprev)
- return (-EIO);
- idetape_create_space_cmd(&pc,-(mt_count+count),IDETAPE_SPACE_OVER_FILEMARK);
- return (idetape_queue_pc_tail(drive, &pc));
case MTBSFM:
if (!tape->capabilities.sprev)
return (-EIO);
- retval = idetape_space_over_filemarks(drive, MTBSF, mt_count+count);
+ retval = idetape_space_over_filemarks(drive, MTFSF, mt_count-count);
if (retval) return (retval);
- return (idetape_space_over_filemarks(drive, MTFSF, 1));
+ count = (MTBSFM == mt_op ? 1 : -1);
+ return (idetape_space_over_filemarks(drive, MTFSF, count));
default:
printk(KERN_ERR "ide-tape: MTIO operation %d not supported\n",mt_op);
return (-EIO);
@@ -4894,7 +4957,7 @@
*/
retval = idetape_queue_rw_tail(drive, IDETAPE_WRITE_RQ, 0, tape->merge_stage->bio);
if (retval < 0) {
- kfree(tape->merge_stage);
+ __idetape_kfree_stage(tape->merge_stage);
tape->merge_stage = NULL;
tape->chrdev_direction = idetape_direction_none;
return retval;
@@ -5482,9 +5545,11 @@
MOD_DEC_USE_COUNT;
return -EBUSY;
}
- idetape_read_position(drive);
+ if (tape->onstream)
+ idetape_read_position(drive);
MOD_DEC_USE_COUNT;
- clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
+ if (tape->chrdev_direction != idetape_direction_read)
+ clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);

if (tape->chrdev_direction == idetape_direction_none) {
MOD_INC_USE_COUNT;
@@ -5557,10 +5622,11 @@
if (minor < 128)
(void) idetape_rewind_tape(drive);
if (tape->chrdev_direction == idetape_direction_none) {
- if (tape->door_locked != DOOR_EXPLICITLY_LOCKED) {
- if (idetape_create_prevent_cmd(drive, &pc, 0))
+ if (tape->door_locked == DOOR_LOCKED) {
+ if (idetape_create_prevent_cmd(drive, &pc, 0)) {
if (!idetape_queue_pc_tail(drive, &pc))
tape->door_locked = DOOR_UNLOCKED;
+ }
}
MOD_DEC_USE_COUNT;
}
@@ -5594,34 +5660,34 @@
printk(KERN_INFO "ide-tape: Dumping ATAPI Identify Device tape parameters\n");
printk(KERN_INFO "ide-tape: Protocol Type: ");
switch (gcw.protocol) {
- case 0: case 1: printk(KERN_INFO "ATA\n");break;
- case 2: printk(KERN_INFO "ATAPI\n");break;
- case 3: printk(KERN_INFO "Reserved (Unknown to ide-tape)\n");break;
+ case 0: case 1: printk("ATA\n");break;
+ case 2: printk("ATAPI\n");break;
+ case 3: printk("Reserved (Unknown to ide-tape)\n");break;
}
printk(KERN_INFO "ide-tape: Device Type: %x - ",gcw.device_type);
switch (gcw.device_type) {
- case 0: printk(KERN_INFO "Direct-access Device\n");break;
- case 1: printk(KERN_INFO "Streaming Tape Device\n");break;
- case 2: case 3: case 4: printk(KERN_INFO "Reserved\n");break;
- case 5: printk(KERN_INFO "CD-ROM Device\n");break;
- case 6: printk(KERN_INFO "Reserved\n");
- case 7: printk(KERN_INFO "Optical memory Device\n");break;
- case 0x1f: printk(KERN_INFO "Unknown or no Device type\n");break;
- default: printk(KERN_INFO "Reserved\n");
+ case 0: printk("Direct-access Device\n");break;
+ case 1: printk("Streaming Tape Device\n");break;
+ case 2: case 3: case 4: printk("Reserved\n");break;
+ case 5: printk("CD-ROM Device\n");break;
+ case 6: printk("Reserved\n");
+ case 7: printk("Optical memory Device\n");break;
+ case 0x1f: printk("Unknown or no Device type\n");break;
+ default: printk("Reserved\n");
}
printk(KERN_INFO "ide-tape: Removable: %s",gcw.removable ? "Yes\n":"No\n");
printk(KERN_INFO "ide-tape: Command Packet DRQ Type: ");
switch (gcw.drq_type) {
- case 0: printk(KERN_INFO "Microprocessor DRQ\n");break;
- case 1: printk(KERN_INFO "Interrupt DRQ\n");break;
- case 2: printk(KERN_INFO "Accelerated DRQ\n");break;
- case 3: printk(KERN_INFO "Reserved\n");break;
+ case 0: printk("Microprocessor DRQ\n");break;
+ case 1: printk("Interrupt DRQ\n");break;
+ case 2: printk("Accelerated DRQ\n");break;
+ case 3: printk("Reserved\n");break;
}
printk(KERN_INFO "ide-tape: Command Packet Size: ");
switch (gcw.packet_size) {
- case 0: printk(KERN_INFO "12 bytes\n");break;
- case 1: printk(KERN_INFO "16 bytes\n");break;
- default: printk(KERN_INFO "Reserved\n");break;
+ case 0: printk("12 bytes\n");break;
+ case 1: printk("16 bytes\n");break;
+ default: printk("Reserved\n");break;
}
printk(KERN_INFO "ide-tape: Model: %.40s\n",id->model);
printk(KERN_INFO "ide-tape: Firmware Revision: %.8s\n",id->fw_rev);
@@ -5637,45 +5703,45 @@
printk(KERN_INFO "ide-tape: Single Word DMA supported modes: ");
for (i=0,mask=1;i<8;i++,mask=mask << 1) {
if (id->dma_1word & mask)
- printk(KERN_INFO "%d ",i);
+ printk("%d ",i);
if (id->dma_1word & (mask << 8))
- printk(KERN_INFO "(active) ");
+ printk("(active) ");
}
- printk(KERN_INFO "\n");
+ printk("\n");
printk(KERN_INFO "ide-tape: Multi Word DMA supported modes: ");
for (i=0,mask=1;i<8;i++,mask=mask << 1) {
if (id->dma_mword & mask)
- printk(KERN_INFO "%d ",i);
+ printk("%d ",i);
if (id->dma_mword & (mask << 8))
- printk(KERN_INFO "(active) ");
+ printk("(active) ");
}
- printk(KERN_INFO "\n");
+ printk("\n");
if (id->field_valid & 0x0002) {
printk(KERN_INFO "ide-tape: Enhanced PIO Modes: %s\n",
id->eide_pio_modes & 1 ? "Mode 3":"None");
printk(KERN_INFO "ide-tape: Minimum Multi-word DMA cycle per word: ");
if (id->eide_dma_min == 0)
- printk(KERN_INFO "Not supported\n");
+ printk("Not supported\n");
else
- printk(KERN_INFO "%d ns\n",id->eide_dma_min);
+ printk("%d ns\n",id->eide_dma_min);

printk(KERN_INFO "ide-tape: Manufacturer\'s Recommended Multi-word cycle: ");
if (id->eide_dma_time == 0)
- printk(KERN_INFO "Not supported\n");
+ printk("Not supported\n");
else
- printk(KERN_INFO "%d ns\n",id->eide_dma_time);
+ printk("%d ns\n",id->eide_dma_time);

printk(KERN_INFO "ide-tape: Minimum PIO cycle without IORDY: ");
if (id->eide_pio == 0)
- printk(KERN_INFO "Not supported\n");
+ printk("Not supported\n");
else
- printk(KERN_INFO "%d ns\n",id->eide_pio);
+ printk("%d ns\n",id->eide_pio);

printk(KERN_INFO "ide-tape: Minimum PIO cycle with IORDY: ");
if (id->eide_pio_iordy == 0)
- printk(KERN_INFO "Not supported\n");
+ printk("Not supported\n");
else
- printk(KERN_INFO "%d ns\n",id->eide_pio_iordy);
+ printk("%d ns\n",id->eide_pio_iordy);

} else
printk(KERN_INFO "ide-tape: According to the device, fields 64-70 are not valid.\n");
@@ -5984,9 +6050,9 @@
* drive setting name read/write ioctl ioctl data type min max mul_factor div_factor data pointer set function
*/
ide_add_setting(drive, "buffer", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 2, &tape->capabilities.buffer_size, NULL);
- ide_add_setting(drive, "pipeline_min", SETTING_RW, -1, -1, TYPE_INT, 2, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL);
- ide_add_setting(drive, "pipeline", SETTING_RW, -1, -1, TYPE_INT, 2, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL);
- ide_add_setting(drive, "pipeline_max", SETTING_RW, -1, -1, TYPE_INT, 2, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL);
+ ide_add_setting(drive, "pipeline_min", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL);
+ ide_add_setting(drive, "pipeline", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL);
+ ide_add_setting(drive, "pipeline_max", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL);
ide_add_setting(drive, "pipeline_used",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_stages, NULL);
ide_add_setting(drive, "pipeline_pending",SETTING_READ,-1, -1, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_pending_stages, NULL);
ide_add_setting(drive, "speed", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->capabilities.speed, NULL);
@@ -6101,8 +6167,11 @@
si_meminfo(&si);
if (tape->max_stages * tape->stage_size > si.totalram * si.mem_unit / 10)
tape->max_stages = si.totalram * si.mem_unit / (10 * tape->stage_size);
- tape->min_pipeline = tape->max_stages;
- tape->max_pipeline = tape->max_stages * 2;
+ tape->max_stages = min(tape->max_stages, IDETAPE_MAX_PIPELINE_STAGES);
+ tape->min_pipeline = min(tape->max_stages, IDETAPE_MIN_PIPELINE_STAGES);
+ tape->max_pipeline = min(tape->max_stages * 2, IDETAPE_MAX_PIPELINE_STAGES);
+ if (tape->max_stages == 0)
+ tape->max_stages = tape->min_pipeline = tape->max_pipeline = 1;

t1 = (tape->stage_size * HZ) / (speed * 1000);
tmid = (tape->capabilities.buffer_size * 32 * HZ) / (speed * 125);
\
 
 \ /
  Last update: 2005-03-22 13:30    [W:0.446 / U:0.208 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site