return ide_started;
 }
 EXPORT_SYMBOL_GPL(ide_transfer_pc);
+
+ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_atapi_pc *pc,
+                            ide_handler_t *handler, unsigned int timeout,
+                            ide_expiry_t *expiry)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       u16 bcount;
+       u8 dma = 0;
+
+       /* We haven't transferred any data yet */
+       pc->xferred = 0;
+       pc->cur_pos = pc->buf;
+
+       /* Request to transfer the entire buffer at once */
+       if (drive->media == ide_tape && !drive->scsi)
+               bcount = pc->req_xfer;
+       else
+               bcount = min(pc->req_xfer, 63 * 1024);
+
+       if (pc->flags & PC_FLAG_DMA_ERROR) {
+               pc->flags &= ~PC_FLAG_DMA_ERROR;
+               ide_dma_off(drive);
+       }
+
+       if ((pc->flags & PC_FLAG_DMA_OK) && drive->using_dma) {
+               if (drive->scsi)
+                       hwif->sg_mapped = 1;
+               dma = !hwif->dma_ops->dma_setup(drive);
+               if (drive->scsi)
+                       hwif->sg_mapped = 0;
+       }
+
+       if (!dma)
+               pc->flags &= ~PC_FLAG_DMA_OK;
+
+       ide_pktcmd_tf_load(drive, drive->scsi ? 0 : IDE_TFLAG_OUT_DEVICE,
+                          bcount, dma);
+
+       /* Issue the packet command */
+       if (pc->flags & PC_FLAG_DRQ_INTERRUPT) {
+               ide_execute_command(drive, WIN_PACKETCMD, handler,
+                                   timeout, NULL);
+               return ide_started;
+       } else {
+               ide_execute_pkt_cmd(drive);
+               return (*handler)(drive);
+       }
+}
+EXPORT_SYMBOL_GPL(ide_issue_pc);
 
                struct ide_atapi_pc *pc)
 {
        idefloppy_floppy_t *floppy = drive->driver_data;
-       ide_hwif_t *hwif = drive->hwif;
-       u16 bcount;
-       u8 dma;
 
        if (floppy->failed_pc == NULL &&
            pc->c[0] != GPCMD_REQUEST_SENSE)
        debug_log("Retry number - %d\n", pc->retries);
 
        pc->retries++;
-       /* We haven't transferred any data yet */
-       pc->xferred = 0;
-       pc->cur_pos = pc->buf;
-       bcount = min(pc->req_xfer, 63 * 1024);
-
-       if (pc->flags & PC_FLAG_DMA_ERROR) {
-               pc->flags &= ~PC_FLAG_DMA_ERROR;
-               ide_dma_off(drive);
-       }
-       dma = 0;
 
-       if ((pc->flags & PC_FLAG_DMA_OK) && drive->using_dma)
-               dma = !hwif->dma_ops->dma_setup(drive);
-
-       if (!dma)
-               pc->flags &= ~PC_FLAG_DMA_OK;
-
-       ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_DEVICE, bcount, dma);
-
-       if (pc->flags & PC_FLAG_DRQ_INTERRUPT) {
-               /* Issue the packet command */
-               ide_execute_command(drive, WIN_PACKETCMD,
-                               &idefloppy_transfer_pc1,
-                               IDEFLOPPY_WAIT_CMD,
-                               NULL);
-               return ide_started;
-       } else {
-               /* Issue the packet command */
-               ide_execute_pkt_cmd(drive);
-               return idefloppy_transfer_pc1(drive);
-       }
+       return ide_issue_pc(drive, pc, idefloppy_transfer_pc1,
+                           IDEFLOPPY_WAIT_CMD, NULL);
 }
 
 static void idefloppy_create_prevent_cmd(struct ide_atapi_pc *pc, int prevent)
 
 static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
                struct ide_atapi_pc *pc)
 {
-       ide_hwif_t *hwif = drive->hwif;
        idetape_tape_t *tape = drive->driver_data;
-       int dma_ok = 0;
-       u16 bcount;
 
        if (tape->pc->c[0] == REQUEST_SENSE &&
            pc->c[0] == REQUEST_SENSE) {
        debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]);
 
        pc->retries++;
-       /* We haven't transferred any data yet */
-       pc->xferred = 0;
-       pc->cur_pos = pc->buf;
-       /* Request to transfer the entire buffer at once */
-       bcount = pc->req_xfer;
-
-       if (pc->flags & PC_FLAG_DMA_ERROR) {
-               pc->flags &= ~PC_FLAG_DMA_ERROR;
-               ide_dma_off(drive);
-       }
-       if ((pc->flags & PC_FLAG_DMA_OK) && drive->using_dma)
-               dma_ok = !hwif->dma_ops->dma_setup(drive);
-
-       if (!dma_ok)
-               pc->flags &= ~PC_FLAG_DMA_OK;
-
-       ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_DEVICE, bcount, dma_ok);
 
-       if (pc->flags & PC_FLAG_DRQ_INTERRUPT) {
-               ide_execute_command(drive, WIN_PACKETCMD, &idetape_transfer_pc,
-                                   IDETAPE_WAIT_CMD, NULL);
-               return ide_started;
-       } else {
-               ide_execute_pkt_cmd(drive);
-               return idetape_transfer_pc(drive);
-       }
+       return ide_issue_pc(drive, pc, idetape_transfer_pc,
+                           IDETAPE_WAIT_CMD, NULL);
 }
 
 /* A mode sense command is used to "sense" tape parameters. */
 
                struct ide_atapi_pc *pc)
 {
        idescsi_scsi_t *scsi = drive_to_idescsi(drive);
-       ide_hwif_t *hwif = drive->hwif;
-       u16 bcount;
-       u8 dma = 0;
 
        /* Set the current packet command */
        scsi->pc = pc;
-       /* We haven't transferred any data yet */
-       pc->xferred = 0;
-       pc->cur_pos = pc->buf;
-       /* Request to transfer the entire buffer at once */
-       bcount = min(pc->req_xfer, 63 * 1024);
-
-       if ((pc->flags & PC_FLAG_DMA_OK) && drive->using_dma) {
-               hwif->sg_mapped = 1;
-               dma = !hwif->dma_ops->dma_setup(drive);
-               hwif->sg_mapped = 0;
-       }
-
-       if (!dma)
-               pc->flags &= ~PC_FLAG_DMA_OK;
 
-       ide_pktcmd_tf_load(drive, 0, bcount, dma);
-
-       if (pc->flags & PC_FLAG_DRQ_INTERRUPT) {
-               ide_execute_command(drive, WIN_PACKETCMD, &idescsi_transfer_pc,
-                                   get_timeout(pc), idescsi_expiry);
-               return ide_started;
-       } else {
-               /* Issue the packet command */
-               ide_execute_pkt_cmd(drive);
-               return idescsi_transfer_pc(drive);
-       }
+       return ide_issue_pc(drive, pc, idescsi_transfer_pc,
+                           get_timeout(pc), idescsi_expiry);
 }
 
 /*
 
 
 ide_startstop_t ide_transfer_pc(ide_drive_t *, struct ide_atapi_pc *,
                                ide_handler_t *, unsigned int, ide_expiry_t *);
+ide_startstop_t ide_issue_pc(ide_drive_t *, struct ide_atapi_pc *,
+                            ide_handler_t *, unsigned int, ide_expiry_t *);
 
 ide_startstop_t do_rw_taskfile(ide_drive_t *, ide_task_t *);