patch-2.2.0-pre2 linux/drivers/block/ide-tape.c
Next file: linux/drivers/block/ide.c
Previous file: linux/drivers/block/ide-dma.c
Back to the patch index
Back to the overall index
- Lines: 231
- Date:
Wed Dec 30 14:51:31 1998
- Orig file:
v2.2.0-pre1/linux/drivers/block/ide-tape.c
- Orig date:
Fri Oct 9 13:27:07 1998
diff -u --recursive --new-file v2.2.0-pre1/linux/drivers/block/ide-tape.c linux/drivers/block/ide-tape.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/block/ide-tape.c Version 1.13 Jan 2, 1998
+ * linux/drivers/block/ide-tape.c Version 1.14 Dec 30, 1998
*
* Copyright (C) 1995 - 1998 Gadi Oxman <gadio@netvision.net.il>
*
@@ -212,6 +212,8 @@
* number of tape blocks.
* Add support for INTERRUPT DRQ devices.
* Ver 1.13 Jan 2 98 Add "speed == 0" work-around for HP COLORADO 5GB
+ * Ver 1.14 Dec 30 99 Partial fixes for the Sony/AIWA tape drives.
+ * Replace cli()/sti() with hwgroup spinlocks.
*
* Here are some words from the first releases of hd.c, which are quoted
* in ide.c and apply here as well:
@@ -479,6 +481,11 @@
#define IDETAPE_FIFO_THRESHOLD 2
/*
+ * Some tape drives require a long irq timeout
+ */
+#define IDETAPE_WAIT_CMD 60
+
+/*
* DSC timings.
*/
#define IDETAPE_DSC_RW_MIN 5*HZ/100 /* 50 msec */
@@ -1432,8 +1439,7 @@
#if IDETAPE_DEBUG_LOG
printk (KERN_INFO "Reached idetape_add_stage_tail\n");
#endif /* IDETAPE_DEBUG_LOG */
- save_flags (flags); /* all CPUs (overkill?) */
- cli(); /* all CPUs (overkill?) */
+ spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags);
stage->next=NULL;
if (tape->last_stage != NULL)
tape->last_stage->next=stage;
@@ -1444,7 +1450,7 @@
tape->next_stage=tape->last_stage;
tape->nr_stages++;
tape->nr_pending_stages++;
- restore_flags (flags); /* all CPUs (overkill?) */
+ spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
}
/*
@@ -1756,6 +1762,8 @@
ide__sti(); /* local CPU only */
+ if (status.b.check && pc->c[0] == IDETAPE_REQUEST_SENSE_CMD)
+ status.b.check = 0;
if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) { /* Error detected */
#if IDETAPE_DEBUG_LOG
printk (KERN_INFO "ide-tape: %s: I/O error, ",tape->name);
@@ -1811,7 +1819,7 @@
if (temp > pc->buffer_size) {
printk (KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n");
idetape_discard_data (drive,bcount.all);
- ide_set_handler (drive,&idetape_pc_intr,WAIT_CMD);
+ ide_set_handler (drive,&idetape_pc_intr,IDETAPE_WAIT_CMD);
return;
}
#if IDETAPE_DEBUG_LOG
@@ -1833,7 +1841,7 @@
pc->actually_transferred+=bcount.all; /* Update the current position */
pc->current_position+=bcount.all;
- ide_set_handler (drive,&idetape_pc_intr,WAIT_CMD); /* And set the interrupt handler again */
+ ide_set_handler (drive,&idetape_pc_intr,IDETAPE_WAIT_CMD); /* And set the interrupt handler again */
}
/*
@@ -1884,18 +1892,29 @@
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t *pc = tape->pc;
idetape_ireason_reg_t ireason;
+ int retries = 100;
if (ide_wait_stat (drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) {
printk (KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n");
return;
}
ireason.all=IN_BYTE (IDE_IREASON_REG);
+ while (retries-- && (!ireason.b.cod || ireason.b.io)) {
+ printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing a packet command, retrying\n");
+ udelay(100);
+ ireason.all = IN_BYTE(IDE_IREASON_REG);
+ if (retries == 0) {
+ printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing a packet command, ignoring\n");
+ ireason.b.cod = 1;
+ ireason.b.io = 0;
+ }
+ }
if (!ireason.b.cod || ireason.b.io) {
printk (KERN_ERR "ide-tape: (IO,CoD) != (0,1) while issuing a packet command\n");
ide_do_reset (drive);
return;
}
- ide_set_handler(drive, &idetape_pc_intr, WAIT_CMD); /* Set the interrupt routine */
+ ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD); /* Set the interrupt routine */
atapi_output_bytes (drive,pc->c,12); /* Send the actual packet */
}
@@ -1961,7 +1980,7 @@
}
#endif /* CONFIG_BLK_DEV_IDEDMA */
if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
- ide_set_handler(drive, &idetape_transfer_pc, WAIT_CMD);
+ ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD);
OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG);
} else {
OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG);
@@ -2313,7 +2332,7 @@
* The caller should ensure that the request will not be serviced
* before we install the semaphore (usually by disabling interrupts).
*/
-static void idetape_wait_for_request (struct request *rq)
+static void idetape_wait_for_request (ide_drive_t *drive, struct request *rq)
{
struct semaphore sem = MUTEX_LOCKED;
@@ -2324,7 +2343,9 @@
}
#endif /* IDETAPE_DEBUG_BUGS */
rq->sem = &sem;
- down (&sem);
+ spin_unlock(&HWGROUP(drive)->spinlock);
+ down(&sem);
+ spin_lock_irq(&HWGROUP(drive)->spinlock);
}
/*
@@ -2398,11 +2419,10 @@
*/
return (idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, blocks, tape->merge_stage->bh));
}
- save_flags (flags); /* all CPUs (overkill?) */
- cli(); /* all CPUs (overkill?) */
+ spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags);
if (tape->active_stage == tape->first_stage)
- idetape_wait_for_request (tape->active_data_request);
- restore_flags (flags); /* all CPUs (overkill?) */
+ idetape_wait_for_request(drive, tape->active_data_request);
+ spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
rq_ptr = &tape->first_stage->rq;
bytes_read = tape->tape_block_size * (rq_ptr->nr_sectors - rq_ptr->current_nr_sectors);
@@ -2451,13 +2471,12 @@
* Pay special attention to possible race conditions.
*/
while ((new_stage = idetape_kmalloc_stage (tape)) == NULL) {
- save_flags (flags); /* all CPUs (overkill?) */
- cli(); /* all CPUs (overkill?) */
+ spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags);
if (idetape_pipeline_active (tape)) {
- idetape_wait_for_request (tape->active_data_request);
- restore_flags (flags); /* all CPUs (overkill?) */
+ idetape_wait_for_request(drive, tape->active_data_request);
+ spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
} else {
- restore_flags (flags); /* all CPUs (overkill?) */
+ spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
idetape_insert_pipeline_into_queue (drive);
if (idetape_pipeline_active (tape))
continue;
@@ -2513,13 +2532,12 @@
if (tape->first_stage == NULL)
return;
-
- save_flags (flags); /* all CPUs (overkill?) */
- cli(); /* all CPUs (overkill?) */
+
+ spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags);
tape->next_stage = NULL;
if (idetape_pipeline_active (tape))
- idetape_wait_for_request (tape->active_data_request);
- restore_flags (flags); /* all CPUs (overkill?) */
+ idetape_wait_for_request(drive, tape->active_data_request);
+ spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
while (tape->first_stage != NULL)
idetape_remove_stage_head (drive);
@@ -2539,8 +2557,7 @@
if (!idetape_pipeline_active (tape))
idetape_insert_pipeline_into_queue (drive);
- save_flags (flags); /* all CPUs (overkill?) */
- cli(); /* all CPUs (overkill?) */
+ spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags);
if (!idetape_pipeline_active (tape))
goto abort;
#if IDETAPE_DEBUG_BUGS
@@ -2548,9 +2565,9 @@
printk ("ide-tape: tape->last_stage == NULL\n");
else
#endif /* IDETAPE_DEBUG_BUGS */
- idetape_wait_for_request (&tape->last_stage->rq);
+ idetape_wait_for_request(drive, &tape->last_stage->rq);
abort:
- restore_flags (flags); /* all CPUs (overkill?) */
+ spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
}
static void idetape_pad_zeros (ide_drive_t *drive, int bcount)
@@ -2795,11 +2812,10 @@
* Wait until the first read-ahead request
* is serviced.
*/
- save_flags (flags); /* all CPUs (overkill?) */
- cli(); /* all CPUs (overkill?) */
+ spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags);
if (tape->active_stage == tape->first_stage)
- idetape_wait_for_request (tape->active_data_request);
- restore_flags (flags); /* all CPUs (overkill?) */
+ idetape_wait_for_request(drive, tape->active_data_request);
+ spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
if (tape->first_stage->rq.errors == IDETAPE_ERROR_FILEMARK)
count++;
@@ -3457,7 +3473,7 @@
return;
}
header = (idetape_mode_parameter_header_t *) pc.buffer;
- capabilities = (idetape_capabilities_page_t *) (header + 1);
+ capabilities = (idetape_capabilities_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl);
capabilities->max_speed = ntohs (capabilities->max_speed);
capabilities->ctl = ntohs (capabilities->ctl);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov