diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/ide-scsi.c | 51 | ||||
-rw-r--r-- | drivers/scsi/ide-scsi.h | 3 | ||||
-rw-r--r-- | drivers/scsi/st.c | 1 |
3 files changed, 42 insertions, 13 deletions
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index efd6568f1..ff3264da3 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -1,5 +1,5 @@ /* - * linux/drivers/scsi/ide-scsi.c Version 0.2 - ALPHA Jan 26, 1997 + * linux/drivers/scsi/ide-scsi.c Version 0.4 Dec 7, 1997 * * Copyright (C) 1996, 1997 Gadi Oxman <gadio@netvision.net.il> */ @@ -15,9 +15,13 @@ * of MODE_SENSE_6/MODE_SELECT_6 for cdroms. Thanks * to Janos Farkas for pointing this out. * Avoid using bitfields in structures for m68k. - * Added Scather/Gather and DMA support. + * Added Scatter/Gather and DMA support. + * Ver 0.4 Dec 7 97 Add support for ATAPI PD/CD drives. + * Use variable timeout for each command. */ +#define IDESCSI_VERSION "0.4" + #include <linux/module.h> #include <linux/types.h> #include <linux/string.h> @@ -49,11 +53,12 @@ typedef struct idescsi_pc_s { struct request *rq; /* The corresponding request */ byte *buffer; /* Data buffer */ byte *current_position; /* Pointer into the above buffer */ - struct scatterlist *sg; /* Scather gather table */ + struct scatterlist *sg; /* Scatter gather table */ int b_count; /* Bytes transferred from current entry */ Scsi_Cmnd *scsi_cmd; /* SCSI command */ void (*done)(Scsi_Cmnd *); /* Scsi completion routine */ unsigned int flags; /* Status/Action flags */ + unsigned long timeout; /* Command timeout */ } idescsi_pc_t; /* @@ -149,7 +154,7 @@ static inline void idescsi_transform_pc1 (ide_drive_t *drive, idescsi_pc_t *pc) int i; if (drive->media == ide_cdrom) { - if (c[0] == READ_6) { + if (c[0] == READ_6 || c[0] == WRITE_6) { c[8] = c[4]; c[5] = c[3]; c[4] = c[2]; c[3] = c[1] & 0x1f; c[2] = 0; c[1] &= 0xe0; c[0] = READ_10; @@ -226,6 +231,11 @@ static void idescsi_end_request (byte uptodate, ide_hwgroup_t *hwgroup) scsi->pc = NULL; } +static inline unsigned long get_timeout(idescsi_pc_t *pc) +{ + return IDE_MAX(WAIT_CMD, pc->timeout - jiffies); +} + /* * Our interrupt handler. */ @@ -247,7 +257,7 @@ static void idescsi_pc_intr (ide_drive_t *drive) printk ("ide-scsi: %s: DMA complete\n", drive->name); #endif /* IDESCSI_DEBUG_LOG */ pc->actually_transferred=pc->request_transfer; - (void) (HWIF(drive)->dmaproc(ide_dma_abort, drive)); + (void) (HWIF(drive)->dmaproc(ide_dma_end, drive)); } status = GET_STAT(); /* Clear the interrupt */ @@ -276,7 +286,7 @@ static void idescsi_pc_intr (ide_drive_t *drive) if (temp > pc->buffer_size) { printk (KERN_ERR "ide-scsi: The scsi wants to send us more data than expected - discarding data\n"); idescsi_discard_data (drive,bcount); - ide_set_handler (drive,&idescsi_pc_intr,WAIT_CMD); + ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc)); return; } #if IDESCSI_DEBUG_LOG @@ -298,12 +308,13 @@ static void idescsi_pc_intr (ide_drive_t *drive) pc->actually_transferred+=bcount; /* Update the current position */ pc->current_position+=bcount; - ide_set_handler (drive,&idescsi_pc_intr,WAIT_CMD); /* And set the interrupt handler again */ + ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc)); /* And set the interrupt handler again */ } static void idescsi_transfer_pc (ide_drive_t *drive) { idescsi_scsi_t *scsi = drive->driver_data; + idescsi_pc_t *pc = scsi->pc; byte ireason; if (ide_wait_stat (drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) { @@ -316,8 +327,8 @@ static void idescsi_transfer_pc (ide_drive_t *drive) ide_do_reset (drive); return; } - ide_set_handler (drive, &idescsi_pc_intr, WAIT_CMD); /* Set the interrupt routine */ - atapi_output_bytes (drive, scsi->pc->c, 12); /* Send the actual packet */ + ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc)); /* Set the interrupt routine */ + atapi_output_bytes (drive, scsi->pc->c, 12); /* Send the actual packet */ } /* @@ -349,7 +360,7 @@ static void idescsi_issue_pc (ide_drive_t *drive, idescsi_pc_t *pc) (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); } if (test_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags)) { - ide_set_handler (drive, &idescsi_transfer_pc, WAIT_CMD); + ide_set_handler (drive, &idescsi_transfer_pc, get_timeout(pc)); OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */ } else { OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); @@ -426,6 +437,8 @@ static ide_module_t idescsi_module = { * IDE subdriver functions, registered with ide.c */ static ide_driver_t idescsi_driver = { + "ide-scsi", /* name */ + IDESCSI_VERSION, /* version */ ide_scsi, /* media */ 0, /* busy */ 1, /* supports_dma */ @@ -439,7 +452,8 @@ static ide_driver_t idescsi_driver = { NULL, /* media_change */ NULL, /* pre_reset */ NULL, /* capacity */ - NULL /* special */ + NULL, /* special */ + NULL /* proc */ }; static struct proc_dir_entry idescsi_proc_dir = {PROC_SCSI_IDESCSI, 8, "ide-scsi", S_IFDIR | S_IRUGO | S_IXUGO, 2}; @@ -555,7 +569,7 @@ static inline struct buffer_head *idescsi_dma_bh (ide_drive_t *drive, idescsi_pc int segments = pc->scsi_cmd->use_sg; struct scatterlist *sg = pc->scsi_cmd->request_buffer; - if (!drive->using_dma || pc->request_transfer % 1024) + if (!drive->using_dma || !pc->request_transfer || pc->request_transfer % 1024) return NULL; if (idescsi_set_direction(pc)) return NULL; @@ -619,6 +633,7 @@ int idescsi_queue (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) pc->request_transfer = pc->buffer_size = cmd->request_bufflen; pc->scsi_cmd = cmd; pc->done = done; + pc->timeout = jiffies + cmd->timeout_per_command; idescsi_transform_pc1 (drive, pc); ide_init_drive_cmd (rq); @@ -645,6 +660,18 @@ int idescsi_reset (Scsi_Cmnd *cmd, unsigned int resetflags) return SCSI_RESET_PUNT; } +int idescsi_bios (Disk *disk, kdev_t dev, int *parm) +{ + ide_drive_t *drive = idescsi_drives[disk->device->id]; + + if (drive->cyl && drive->head && drive->sect) { + parm[0] = drive->head; + parm[1] = drive->sect; + parm[2] = drive->cyl; + } + return 0; +} + #ifdef MODULE Scsi_Host_Template idescsi_template = IDESCSI; diff --git a/drivers/scsi/ide-scsi.h b/drivers/scsi/ide-scsi.h index 44b524e73..2ccbc3c03 100644 --- a/drivers/scsi/ide-scsi.h +++ b/drivers/scsi/ide-scsi.h @@ -13,6 +13,7 @@ extern const char *idescsi_info (struct Scsi_Host *host); extern int idescsi_queue (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)); extern int idescsi_abort (Scsi_Cmnd *cmd); extern int idescsi_reset (Scsi_Cmnd *cmd, unsigned int resetflags); +extern int idescsi_bios (Disk *disk, kdev_t dev, int *parm); #define IDESCSI \ { NULL, /* next */ \ @@ -28,7 +29,7 @@ extern int idescsi_reset (Scsi_Cmnd *cmd, unsigned int resetflags); idescsi_abort, /* abort */ \ idescsi_reset, /* reset */ \ NULL, /* slave_attach */ \ - NULL, /* bios_param */ \ + idescsi_bios, /* bios_param */ \ 10, /* can_queue */ \ -1, /* this_id */ \ 256, /* sg_tablesize */ \ diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index b70522280..1d7ed45b4 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -580,6 +580,7 @@ scsi_tape_open(struct inode * inode, struct file * filp) STp->buffer = st_buffers[i]; (STp->buffer)->in_use = 1; (STp->buffer)->writing = 0; + (STp->buffer)->last_result_fatal = 0; flags = filp->f_flags; STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY); |