]> git.proxmox.com Git - mirror_ubuntu-kernels.git/blobdiff - drivers/ide/ide-tape.c
ide: add ide_queue_pc_tail() helper
[mirror_ubuntu-kernels.git] / drivers / ide / ide-tape.c
index 83014abf330f5eb9749182d25cff83692d0a7ab0..88cb9455426752083e5a2e3e4c2228dea1472613 100644 (file)
@@ -56,8 +56,6 @@ enum {
        DBG_CHRDEV =            (1 << 2),
        /* all remaining procedures */
        DBG_PROCS =             (1 << 3),
-       /* buffer alloc info (pc_stack & rq_stack) */
-       DBG_PCRQ_STACK =        (1 << 4),
 };
 
 /* define to see debug info */
@@ -82,19 +80,6 @@ enum {
  */
 #define IDETAPE_MAX_PC_RETRIES         3
 
-/*
- * With each packet command, we allocate a buffer of IDETAPE_PC_BUFFER_SIZE
- * bytes. This is used for several packet commands (Not for READ/WRITE commands)
- */
-#define IDETAPE_PC_BUFFER_SIZE         256
-
-/*
- *     In various places in the driver, we need to allocate storage
- *     for packet commands and requests, which will remain valid while
- *     we leave the driver to wait for an interrupt or a timeout event.
- */
-#define IDETAPE_PC_STACK               (10 + IDETAPE_MAX_PC_RETRIES)
-
 /*
  * Some drives (for example, Seagate STT3401A Travan) require a very long
  * timeout, because they don't return an interrupt or clear their busy bit
@@ -174,20 +159,6 @@ struct idetape_bh {
 #define IDETAPE_LU_RETENSION_MASK      2
 #define IDETAPE_LU_EOT_MASK            4
 
-/*
- * Special requests for our block device strategy routine.
- *
- * In order to service a character device command, we add special requests to
- * the tail of our block device request queue and wait for their completion.
- */
-
-enum {
-       REQ_IDETAPE_PC1         = (1 << 0), /* packet command (first stage) */
-       REQ_IDETAPE_PC2         = (1 << 1), /* packet command (second stage) */
-       REQ_IDETAPE_READ        = (1 << 2),
-       REQ_IDETAPE_WRITE       = (1 << 3),
-};
-
 /* Error codes returned in rq->errors to the higher part of the driver. */
 #define IDETAPE_ERROR_GENERAL          101
 #define IDETAPE_ERROR_FILEMARK         102
@@ -208,13 +179,6 @@ typedef struct ide_tape_obj {
        struct kref     kref;
 
        /*
-        *      Since a typical character device operation requires more
-        *      than one packet command, we provide here enough memory
-        *      for the maximum of interconnected packet commands.
-        *      The packet commands are stored in the circular array pc_stack.
-        *      pc_stack_index points to the last used entry, and warps around
-        *      to the start when we get to the last array entry.
-        *
         *      pc points to the current processed packet command.
         *
         *      failed_pc points to the last failed packet command, or contains
@@ -226,13 +190,11 @@ typedef struct ide_tape_obj {
        struct ide_atapi_pc *pc;
        /* Last failed packet command */
        struct ide_atapi_pc *failed_pc;
-       /* Packet command stack */
-       struct ide_atapi_pc pc_stack[IDETAPE_PC_STACK];
-       /* Next free packet command storage space */
-       int pc_stack_index;
-       struct request rq_stack[IDETAPE_PC_STACK];
-       /* We implement a circular array */
-       int rq_stack_index;
+       /* used by REQ_IDETAPE_{READ,WRITE} requests */
+       struct ide_atapi_pc queued_pc;
+
+       struct ide_atapi_pc request_sense_pc;
+       struct request request_sense_rq;
 
        /*
         * DSC polling variables.
@@ -452,47 +414,6 @@ static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc)
        pc->bh = bh;
 }
 
-/*
- *     idetape_next_pc_storage returns a pointer to a place in which we can
- *     safely store a packet command, even though we intend to leave the
- *     driver. A storage space for a maximum of IDETAPE_PC_STACK packet
- *     commands is allocated at initialization time.
- */
-static struct ide_atapi_pc *idetape_next_pc_storage(ide_drive_t *drive)
-{
-       idetape_tape_t *tape = drive->driver_data;
-
-       debug_log(DBG_PCRQ_STACK, "pc_stack_index=%d\n", tape->pc_stack_index);
-
-       if (tape->pc_stack_index == IDETAPE_PC_STACK)
-               tape->pc_stack_index = 0;
-       return (&tape->pc_stack[tape->pc_stack_index++]);
-}
-
-/*
- *     idetape_next_rq_storage is used along with idetape_next_pc_storage.
- *     Since we queue packet commands in the request queue, we need to
- *     allocate a request, along with the allocation of a packet command.
- */
-
-/**************************************************************
- *                                                            *
- *  This should get fixed to use kmalloc(.., GFP_ATOMIC)      *
- *  followed later on by kfree().   -ml                       *
- *                                                            *
- **************************************************************/
-
-static struct request *idetape_next_rq_storage(ide_drive_t *drive)
-{
-       idetape_tape_t *tape = drive->driver_data;
-
-       debug_log(DBG_PCRQ_STACK, "rq_stack_index=%d\n", tape->rq_stack_index);
-
-       if (tape->rq_stack_index == IDETAPE_PC_STACK)
-               tape->rq_stack_index = 0;
-       return (&tape->rq_stack[tape->rq_stack_index++]);
-}
-
 /*
  * called on each failed packet command retry to analyze the request sense. We
  * currently do not utilize this information.
@@ -669,56 +590,14 @@ static void ide_tape_callback(ide_drive_t *drive)
        idetape_end_request(drive, uptodate, 0);
 }
 
-static void idetape_init_pc(struct ide_atapi_pc *pc)
-{
-       memset(pc->c, 0, 12);
-       pc->retries = 0;
-       pc->flags = 0;
-       pc->req_xfer = 0;
-       pc->buf = pc->pc_buf;
-       pc->buf_size = IDETAPE_PC_BUFFER_SIZE;
-       pc->bh = NULL;
-       pc->b_data = NULL;
-}
-
 static void idetape_create_request_sense_cmd(struct ide_atapi_pc *pc)
 {
-       idetape_init_pc(pc);
+       ide_init_pc(pc);
        pc->c[0] = REQUEST_SENSE;
        pc->c[4] = 20;
        pc->req_xfer = 20;
 }
 
-/*
- * Generate a new packet command request in front of the request queue, before
- * the current request, so that it will be processed immediately, on the next
- * pass through the driver. The function below is called from the request
- * handling part of the driver (the "bottom" part). Safe storage for the request
- * should be allocated with ide_tape_next_{pc,rq}_storage() prior to that.
- *
- * Memory for those requests is pre-allocated at initialization time, and is
- * limited to IDETAPE_PC_STACK requests. We assume that we have enough space for
- * the maximum possible number of inter-dependent packet commands.
- *
- * The higher level of the driver - The ioctl handler and the character device
- * handling functions should queue request to the lower level part and wait for
- * their completion using idetape_queue_pc_tail or idetape_queue_rw_tail.
- */
-static void idetape_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc,
-                                 struct request *rq)
-{
-       struct ide_tape_obj *tape = drive->driver_data;
-
-       blk_rq_init(NULL, rq);
-       rq->cmd_type = REQ_TYPE_SPECIAL;
-       rq->cmd_flags |= REQ_PREEMPT;
-       rq->buffer = (char *) pc;
-       rq->rq_disk = tape->disk;
-       memcpy(rq->cmd, pc->c, 12);
-       rq->cmd[13] = REQ_IDETAPE_PC1;
-       ide_do_drive_cmd(drive, rq);
-}
-
 /*
  *     idetape_retry_pc is called when an error was detected during the
  *     last packet command. We queue a request sense packet command in
@@ -726,15 +605,14 @@ static void idetape_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc,
  */
 static void idetape_retry_pc(ide_drive_t *drive)
 {
-       struct ide_atapi_pc *pc;
-       struct request *rq;
+       struct ide_tape_obj *tape = drive->driver_data;
+       struct request *rq = &tape->request_sense_rq;
+       struct ide_atapi_pc *pc = &tape->request_sense_pc;
 
        (void)ide_read_error(drive);
-       pc = idetape_next_pc_storage(drive);
-       rq = idetape_next_rq_storage(drive);
        idetape_create_request_sense_cmd(pc);
        set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
-       idetape_queue_pc_head(drive, pc, rq);
+       ide_queue_pc_head(drive, tape->disk, pc, rq);
 }
 
 /*
@@ -763,13 +641,15 @@ static void ide_tape_handle_dsc(ide_drive_t *drive)
        idetape_postpone_request(drive);
 }
 
-static void ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
+static int ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
                                unsigned int bcount, int write)
 {
        if (write)
                idetape_output_buffers(drive, pc, bcount);
        else
                idetape_input_buffers(drive, pc, bcount);
+
+       return bcount;
 }
 
 /*
@@ -884,7 +764,7 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
 /* A mode sense command is used to "sense" tape parameters. */
 static void idetape_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code)
 {
-       idetape_init_pc(pc);
+       ide_init_pc(pc);
        pc->c[0] = MODE_SENSE;
        if (page_code != IDETAPE_BLOCK_DESCRIPTOR)
                /* DBD = 1 - Don't return block descriptors */
@@ -943,7 +823,7 @@ static void ide_tape_create_rw_cmd(idetape_tape_t *tape,
        struct idetape_bh *bh = (struct idetape_bh *)rq->special;
        unsigned int length = rq->current_nr_sectors;
 
-       idetape_init_pc(pc);
+       ide_init_pc(pc);
        put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
        pc->c[1] = 1;
        pc->bh = bh;
@@ -1041,12 +921,12 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
                return ide_stopped;
        }
        if (rq->cmd[13] & REQ_IDETAPE_READ) {
-               pc = idetape_next_pc_storage(drive);
+               pc = &tape->queued_pc;
                ide_tape_create_rw_cmd(tape, pc, rq, READ_6);
                goto out;
        }
        if (rq->cmd[13] & REQ_IDETAPE_WRITE) {
-               pc = idetape_next_pc_storage(drive);
+               pc = &tape->queued_pc;
                ide_tape_create_rw_cmd(tape, pc, rq, WRITE_6);
                goto out;
        }
@@ -1233,7 +1113,7 @@ static void idetape_init_merge_buffer(idetape_tape_t *tape)
 static void idetape_create_write_filemark_cmd(ide_drive_t *drive,
                struct ide_atapi_pc *pc, int write_filemark)
 {
-       idetape_init_pc(pc);
+       ide_init_pc(pc);
        pc->c[0] = WRITE_FILEMARKS;
        pc->c[4] = write_filemark;
        pc->flags |= PC_FLAG_WAIT_FOR_DSC;
@@ -1241,43 +1121,14 @@ static void idetape_create_write_filemark_cmd(ide_drive_t *drive,
 
 static void idetape_create_test_unit_ready_cmd(struct ide_atapi_pc *pc)
 {
-       idetape_init_pc(pc);
+       ide_init_pc(pc);
        pc->c[0] = TEST_UNIT_READY;
 }
 
-/*
- * We add a special packet command request to the tail of the request queue, and
- * wait for it to be serviced. This is not to be called from within the request
- * handling part of the driver! We allocate here data on the stack and it is
- * valid until the request is finished. This is not the case for the bottom part
- * of the driver, where we are always leaving the functions to wait for an
- * interrupt or a timer event.
- *
- * From the bottom part of the driver, we should allocate safe memory using
- * idetape_next_pc_storage() and ide_tape_next_rq_storage(), and add the request
- * to the request list without waiting for it to be serviced! In that case, we
- * usually use idetape_queue_pc_head().
- */
-static int idetape_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc)
-{
-       struct ide_tape_obj *tape = drive->driver_data;
-       struct request *rq;
-       int error;
-
-       rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
-       rq->cmd_type = REQ_TYPE_SPECIAL;
-       rq->cmd[13] = REQ_IDETAPE_PC1;
-       rq->buffer = (char *)pc;
-       memcpy(rq->cmd, pc->c, 12);
-       error = blk_execute_rq(drive->queue, tape->disk, rq, 0);
-       blk_put_request(rq);
-       return error;
-}
-
 static void idetape_create_load_unload_cmd(ide_drive_t *drive,
                struct ide_atapi_pc *pc, int cmd)
 {
-       idetape_init_pc(pc);
+       ide_init_pc(pc);
        pc->c[0] = START_STOP;
        pc->c[4] = cmd;
        pc->flags |= PC_FLAG_WAIT_FOR_DSC;
@@ -1286,6 +1137,7 @@ static void idetape_create_load_unload_cmd(ide_drive_t *drive,
 static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
 {
        idetape_tape_t *tape = drive->driver_data;
+       struct gendisk *disk = tape->disk;
        struct ide_atapi_pc pc;
        int load_attempted = 0;
 
@@ -1294,7 +1146,7 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
        timeout += jiffies;
        while (time_before(jiffies, timeout)) {
                idetape_create_test_unit_ready_cmd(&pc);
-               if (!idetape_queue_pc_tail(drive, &pc))
+               if (!ide_queue_pc_tail(drive, disk, &pc))
                        return 0;
                if ((tape->sense_key == 2 && tape->asc == 4 && tape->ascq == 2)
                    || (tape->asc == 0x3A)) {
@@ -1303,7 +1155,7 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
                                return -ENOMEDIUM;
                        idetape_create_load_unload_cmd(drive, &pc,
                                                        IDETAPE_LU_LOAD_MASK);
-                       idetape_queue_pc_tail(drive, &pc);
+                       ide_queue_pc_tail(drive, disk, &pc);
                        load_attempted = 1;
                /* not about to be ready */
                } else if (!(tape->sense_key == 2 && tape->asc == 4 &&
@@ -1316,11 +1168,12 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
 
 static int idetape_flush_tape_buffers(ide_drive_t *drive)
 {
+       struct ide_tape_obj *tape = drive->driver_data;
        struct ide_atapi_pc pc;
        int rc;
 
        idetape_create_write_filemark_cmd(drive, &pc, 0);
-       rc = idetape_queue_pc_tail(drive, &pc);
+       rc = ide_queue_pc_tail(drive, tape->disk, &pc);
        if (rc)
                return rc;
        idetape_wait_ready(drive, 60 * 5 * HZ);
@@ -1329,7 +1182,7 @@ static int idetape_flush_tape_buffers(ide_drive_t *drive)
 
 static void idetape_create_read_position_cmd(struct ide_atapi_pc *pc)
 {
-       idetape_init_pc(pc);
+       ide_init_pc(pc);
        pc->c[0] = READ_POSITION;
        pc->req_xfer = 20;
 }
@@ -1343,7 +1196,7 @@ static int idetape_read_position(ide_drive_t *drive)
        debug_log(DBG_PROCS, "Enter %s\n", __func__);
 
        idetape_create_read_position_cmd(&pc);
-       if (idetape_queue_pc_tail(drive, &pc))
+       if (ide_queue_pc_tail(drive, tape->disk, &pc))
                return -1;
        position = tape->first_frame;
        return position;
@@ -1353,7 +1206,7 @@ static void idetape_create_locate_cmd(ide_drive_t *drive,
                struct ide_atapi_pc *pc,
                unsigned int block, u8 partition, int skip)
 {
-       idetape_init_pc(pc);
+       ide_init_pc(pc);
        pc->c[0] = POSITION_TO_ELEMENT;
        pc->c[1] = 2;
        put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[3]);
@@ -1370,12 +1223,23 @@ static int idetape_create_prevent_cmd(ide_drive_t *drive,
        if (!(tape->caps[6] & 0x01))
                return 0;
 
-       idetape_init_pc(pc);
+       ide_init_pc(pc);
        pc->c[0] = ALLOW_MEDIUM_REMOVAL;
        pc->c[4] = prevent;
        return 1;
 }
 
+static int ide_tape_set_media_lock(ide_drive_t *drive, int on)
+{
+       struct ide_tape_obj *tape = drive->driver_data;
+       struct ide_atapi_pc pc;
+
+       if (!idetape_create_prevent_cmd(drive, &pc, on))
+               return 0;
+
+       return ide_queue_pc_tail(drive, tape->disk, &pc);
+}
+
 static void __ide_tape_discard_merge_buffer(ide_drive_t *drive)
 {
        idetape_tape_t *tape = drive->driver_data;
@@ -1403,6 +1267,7 @@ static int idetape_position_tape(ide_drive_t *drive, unsigned int block,
                u8 partition, int skip)
 {
        idetape_tape_t *tape = drive->driver_data;
+       struct gendisk *disk = tape->disk;
        int retval;
        struct ide_atapi_pc pc;
 
@@ -1410,12 +1275,12 @@ static int idetape_position_tape(ide_drive_t *drive, unsigned int block,
                __ide_tape_discard_merge_buffer(drive);
        idetape_wait_ready(drive, 60 * 5 * HZ);
        idetape_create_locate_cmd(drive, &pc, block, partition, skip);
-       retval = idetape_queue_pc_tail(drive, &pc);
+       retval = ide_queue_pc_tail(drive, disk, &pc);
        if (retval)
                return (retval);
 
        idetape_create_read_position_cmd(&pc);
-       return (idetape_queue_pc_tail(drive, &pc));
+       return ide_queue_pc_tail(drive, disk, &pc);
 }
 
 static void ide_tape_discard_merge_buffer(ide_drive_t *drive,
@@ -1475,7 +1340,7 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks,
 
 static void idetape_create_inquiry_cmd(struct ide_atapi_pc *pc)
 {
-       idetape_init_pc(pc);
+       ide_init_pc(pc);
        pc->c[0] = INQUIRY;
        pc->c[4] = 254;
        pc->req_xfer = 254;
@@ -1484,14 +1349,14 @@ static void idetape_create_inquiry_cmd(struct ide_atapi_pc *pc)
 static void idetape_create_rewind_cmd(ide_drive_t *drive,
                struct ide_atapi_pc *pc)
 {
-       idetape_init_pc(pc);
+       ide_init_pc(pc);
        pc->c[0] = REZERO_UNIT;
        pc->flags |= PC_FLAG_WAIT_FOR_DSC;
 }
 
 static void idetape_create_erase_cmd(struct ide_atapi_pc *pc)
 {
-       idetape_init_pc(pc);
+       ide_init_pc(pc);
        pc->c[0] = ERASE;
        pc->c[1] = 1;
        pc->flags |= PC_FLAG_WAIT_FOR_DSC;
@@ -1499,7 +1364,7 @@ static void idetape_create_erase_cmd(struct ide_atapi_pc *pc)
 
 static void idetape_create_space_cmd(struct ide_atapi_pc *pc, int count, u8 cmd)
 {
-       idetape_init_pc(pc);
+       ide_init_pc(pc);
        pc->c[0] = SPACE;
        put_unaligned(cpu_to_be32(count), (unsigned int *) &pc->c[1]);
        pc->c[1] = cmd;
@@ -1662,20 +1527,20 @@ static void idetape_pad_zeros(ide_drive_t *drive, int bcount)
  */
 static int idetape_rewind_tape(ide_drive_t *drive)
 {
+       struct ide_tape_obj *tape = drive->driver_data;
+       struct gendisk *disk = tape->disk;
        int retval;
        struct ide_atapi_pc pc;
-       idetape_tape_t *tape;
-       tape = drive->driver_data;
 
        debug_log(DBG_SENSE, "Enter %s\n", __func__);
 
        idetape_create_rewind_cmd(drive, &pc);
-       retval = idetape_queue_pc_tail(drive, &pc);
+       retval = ide_queue_pc_tail(drive, disk, &pc);
        if (retval)
                return retval;
 
        idetape_create_read_position_cmd(&pc);
-       retval = idetape_queue_pc_tail(drive, &pc);
+       retval = ide_queue_pc_tail(drive, disk, &pc);
        if (retval)
                return retval;
        return 0;
@@ -1718,6 +1583,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
                                        int mt_count)
 {
        idetape_tape_t *tape = drive->driver_data;
+       struct gendisk *disk = tape->disk;
        struct ide_atapi_pc pc;
        int retval, count = 0;
        int sprev = !!(tape->caps[4] & 0x20);
@@ -1742,7 +1608,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
        case MTBSF:
                idetape_create_space_cmd(&pc, mt_count - count,
                                         IDETAPE_SPACE_OVER_FILEMARK);
-               return idetape_queue_pc_tail(drive, &pc);
+               return ide_queue_pc_tail(drive, disk, &pc);
        case MTFSFM:
        case MTBSFM:
                if (!sprev)
@@ -1931,11 +1797,12 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
 
 static int idetape_write_filemark(ide_drive_t *drive)
 {
+       struct ide_tape_obj *tape = drive->driver_data;
        struct ide_atapi_pc pc;
 
        /* Write a filemark */
        idetape_create_write_filemark_cmd(drive, &pc, 1);
-       if (idetape_queue_pc_tail(drive, &pc)) {
+       if (ide_queue_pc_tail(drive, tape->disk, &pc)) {
                printk(KERN_ERR "ide-tape: Couldn't write a filemark\n");
                return -EIO;
        }
@@ -1958,6 +1825,7 @@ static int idetape_write_filemark(ide_drive_t *drive)
 static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
 {
        idetape_tape_t *tape = drive->driver_data;
+       struct gendisk *disk = tape->disk;
        struct ide_atapi_pc pc;
        int i, retval;
 
@@ -1996,7 +1864,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
                ide_tape_discard_merge_buffer(drive, 0);
                idetape_create_load_unload_cmd(drive, &pc,
                                               IDETAPE_LU_LOAD_MASK);
-               return idetape_queue_pc_tail(drive, &pc);
+               return ide_queue_pc_tail(drive, disk, &pc);
        case MTUNLOAD:
        case MTOFFL:
                /*
@@ -2004,14 +1872,13 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
                 * attempting to eject.
                 */
                if (tape->door_locked) {
-                       if (idetape_create_prevent_cmd(drive, &pc, 0))
-                               if (!idetape_queue_pc_tail(drive, &pc))
-                                       tape->door_locked = DOOR_UNLOCKED;
+                       if (!ide_tape_set_media_lock(drive, 0))
+                               tape->door_locked = DOOR_UNLOCKED;
                }
                ide_tape_discard_merge_buffer(drive, 0);
                idetape_create_load_unload_cmd(drive, &pc,
                                              !IDETAPE_LU_LOAD_MASK);
-               retval = idetape_queue_pc_tail(drive, &pc);
+               retval = ide_queue_pc_tail(drive, disk, &pc);
                if (!retval)
                        clear_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags);
                return retval;
@@ -2022,14 +1889,14 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
                ide_tape_discard_merge_buffer(drive, 0);
                idetape_create_load_unload_cmd(drive, &pc,
                        IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK);
-               return idetape_queue_pc_tail(drive, &pc);
+               return ide_queue_pc_tail(drive, disk, &pc);
        case MTEOM:
                idetape_create_space_cmd(&pc, 0, IDETAPE_SPACE_TO_EOD);
-               return idetape_queue_pc_tail(drive, &pc);
+               return ide_queue_pc_tail(drive, disk, &pc);
        case MTERASE:
                (void)idetape_rewind_tape(drive);
                idetape_create_erase_cmd(&pc);
-               return idetape_queue_pc_tail(drive, &pc);
+               return ide_queue_pc_tail(drive, disk, &pc);
        case MTSETBLK:
                if (mt_count) {
                        if (mt_count < tape->blk_size ||
@@ -2050,17 +1917,13 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
        case MTFSR:
        case MTBSR:
        case MTLOCK:
-               if (!idetape_create_prevent_cmd(drive, &pc, 1))
-                       return 0;
-               retval = idetape_queue_pc_tail(drive, &pc);
+               retval = ide_tape_set_media_lock(drive, 1);
                if (retval)
                        return retval;
                tape->door_locked = DOOR_EXPLICITLY_LOCKED;
                return 0;
        case MTUNLOCK:
-               if (!idetape_create_prevent_cmd(drive, &pc, 0))
-                       return 0;
-               retval = idetape_queue_pc_tail(drive, &pc);
+               retval = ide_tape_set_media_lock(drive, 0);
                if (retval)
                        return retval;
                tape->door_locked = DOOR_UNLOCKED;
@@ -2142,7 +2005,7 @@ static void ide_tape_get_bsize_from_bdesc(ide_drive_t *drive)
        struct ide_atapi_pc pc;
 
        idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_DESCRIPTOR);
-       if (idetape_queue_pc_tail(drive, &pc)) {
+       if (ide_queue_pc_tail(drive, tape->disk, &pc)) {
                printk(KERN_ERR "ide-tape: Can't get block descriptor\n");
                if (tape->blk_size == 0) {
                        printk(KERN_WARNING "ide-tape: Cannot deal with zero "
@@ -2162,7 +2025,6 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
        unsigned int minor = iminor(inode), i = minor & ~0xc0;
        ide_drive_t *drive;
        idetape_tape_t *tape;
-       struct ide_atapi_pc pc;
        int retval;
 
        if (i >= MAX_HWIFS * MAX_DRIVES)
@@ -2225,11 +2087,9 @@ static int idetape_chrdev_open(struct inode *inode, struct file *filp)
 
        /* Lock the tape drive door so user can't eject. */
        if (tape->chrdev_dir == IDETAPE_DIR_NONE) {
-               if (idetape_create_prevent_cmd(drive, &pc, 1)) {
-                       if (!idetape_queue_pc_tail(drive, &pc)) {
-                               if (tape->door_locked != DOOR_EXPLICITLY_LOCKED)
-                                       tape->door_locked = DOOR_LOCKED;
-                       }
+               if (!ide_tape_set_media_lock(drive, 1)) {
+                       if (tape->door_locked != DOOR_EXPLICITLY_LOCKED)
+                               tape->door_locked = DOOR_LOCKED;
                }
        }
        unlock_kernel();
@@ -2262,7 +2122,6 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp)
 {
        struct ide_tape_obj *tape = ide_tape_f(filp);
        ide_drive_t *drive = tape->drive;
-       struct ide_atapi_pc pc;
        unsigned int minor = iminor(inode);
 
        lock_kernel();
@@ -2281,10 +2140,8 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp)
                (void) idetape_rewind_tape(drive);
        if (tape->chrdev_dir == IDETAPE_DIR_NONE) {
                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;
-                       }
+                       if (!ide_tape_set_media_lock(drive, 0))
+                               tape->door_locked = DOOR_UNLOCKED;
                }
        }
        clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags);
@@ -2300,7 +2157,7 @@ static void idetape_get_inquiry_results(ide_drive_t *drive)
        char fw_rev[4], vendor_id[8], product_id[16];
 
        idetape_create_inquiry_cmd(&pc);
-       if (idetape_queue_pc_tail(drive, &pc)) {
+       if (ide_queue_pc_tail(drive, tape->disk, &pc)) {
                printk(KERN_ERR "ide-tape: %s: can't get INQUIRY results\n",
                                tape->name);
                return;
@@ -2329,7 +2186,7 @@ static void idetape_get_mode_sense_results(ide_drive_t *drive)
        u8 speed, max_speed;
 
        idetape_create_mode_sense_cmd(&pc, IDETAPE_CAPABILITIES_PAGE);
-       if (idetape_queue_pc_tail(drive, &pc)) {
+       if (ide_queue_pc_tail(drive, tape->disk, &pc)) {
                printk(KERN_ERR "ide-tape: Can't get tape parameters - assuming"
                                " some default values\n");
                tape->blk_size = 512;
@@ -2456,7 +2313,6 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
        tape->name[1] = 't';
        tape->name[2] = '0' + minor;
        tape->chrdev_dir = IDETAPE_DIR_NONE;
-       tape->pc = tape->pc_stack;
 
        *((u16 *)&gcw) = drive->id[ATA_ID_CONFIG];