Staging: rt2860: convert to netdev_ops
[safe/jmp/linux-2.6] / drivers / ide / ide-tape.c
index a148de6..cb942a9 100644 (file)
@@ -152,11 +152,6 @@ struct idetape_bh {
 #define IDETAPE_LU_RETENSION_MASK      2
 #define IDETAPE_LU_EOT_MASK            4
 
-/* Error codes returned in rq->errors to the higher part of the driver. */
-#define IDETAPE_ERROR_GENERAL          101
-#define IDETAPE_ERROR_FILEMARK         102
-#define IDETAPE_ERROR_EOD              103
-
 /* Structures related to the SELECT SENSE / MODE SENSE packet commands. */
 #define IDETAPE_BLOCK_DESCRIPTOR       0
 #define IDETAPE_CAPABILITIES_PAGE      0x2a
@@ -166,19 +161,11 @@ struct idetape_bh {
  * to an interrupt or a timer event is stored in the struct defined below.
  */
 typedef struct ide_tape_obj {
-       ide_drive_t     *drive;
-       ide_driver_t    *driver;
-       struct gendisk  *disk;
-       struct kref     kref;
+       ide_drive_t             *drive;
+       struct ide_driver       *driver;
+       struct gendisk          *disk;
+       struct device           dev;
 
-       /*
-        *      failed_pc points to the last failed packet command, or contains
-        *      NULL if we do not need to retry any packet command. This is
-        *      required since an additional packet command is needed before the
-        *      retry, to get detailed information on what went wrong.
-        */
-       /* Last failed packet command */
-       struct ide_atapi_pc *failed_pc;
        /* used by REQ_IDETAPE_{READ,WRITE} requests */
        struct ide_atapi_pc queued_pc;
 
@@ -245,9 +232,6 @@ typedef struct ide_tape_obj {
        /* Wasted space in each stage */
        int excess_bh_size;
 
-       /* protects the ide-tape queue */
-       spinlock_t lock;
-
        /* Measures average tape speed */
        unsigned long avg_time;
        int avg_size;
@@ -267,24 +251,19 @@ static DEFINE_MUTEX(idetape_ref_mutex);
 
 static struct class *idetape_sysfs_class;
 
-#define to_ide_tape(obj) container_of(obj, struct ide_tape_obj, kref)
-
-#define ide_tape_g(disk) \
-       container_of((disk)->private_data, struct ide_tape_obj, driver)
-
-static void ide_tape_release(struct kref *);
+static void ide_tape_release(struct device *);
 
 static struct ide_tape_obj *ide_tape_get(struct gendisk *disk)
 {
        struct ide_tape_obj *tape = NULL;
 
        mutex_lock(&idetape_ref_mutex);
-       tape = ide_tape_g(disk);
+       tape = ide_drv_g(disk, ide_tape_obj);
        if (tape) {
                if (ide_device_get(tape->drive))
                        tape = NULL;
                else
-                       kref_get(&tape->kref);
+                       get_device(&tape->dev);
        }
        mutex_unlock(&idetape_ref_mutex);
        return tape;
@@ -295,7 +274,7 @@ static void ide_tape_put(struct ide_tape_obj *tape)
        ide_drive_t *drive = tape->drive;
 
        mutex_lock(&idetape_ref_mutex);
-       kref_put(&tape->kref, ide_tape_release);
+       put_device(&tape->dev);
        ide_device_put(drive);
        mutex_unlock(&idetape_ref_mutex);
 }
@@ -306,8 +285,6 @@ static void ide_tape_put(struct ide_tape_obj *tape)
  */
 static struct ide_tape_obj *idetape_devs[MAX_HWIFS * MAX_DRIVES];
 
-#define ide_tape_f(file) ((file)->private_data)
-
 static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i)
 {
        struct ide_tape_obj *tape = NULL;
@@ -315,24 +292,20 @@ static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i)
        mutex_lock(&idetape_ref_mutex);
        tape = idetape_devs[i];
        if (tape)
-               kref_get(&tape->kref);
+               get_device(&tape->dev);
        mutex_unlock(&idetape_ref_mutex);
        return tape;
 }
 
-static void idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
+static int idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
                                  unsigned int bcount)
 {
        struct idetape_bh *bh = pc->bh;
        int count;
 
        while (bcount) {
-               if (bh == NULL) {
-                       printk(KERN_ERR "ide-tape: bh == NULL in "
-                               "idetape_input_buffers\n");
-                       ide_pad_transfer(drive, 0, bcount);
-                       return;
-               }
+               if (bh == NULL)
+                       break;
                count = min(
                        (unsigned int)(bh->b_size - atomic_read(&bh->b_count)),
                        bcount);
@@ -346,21 +319,21 @@ static void idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
                                atomic_set(&bh->b_count, 0);
                }
        }
+
        pc->bh = bh;
+
+       return bcount;
 }
 
-static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
+static int idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
                                   unsigned int bcount)
 {
        struct idetape_bh *bh = pc->bh;
        int count;
 
        while (bcount) {
-               if (bh == NULL) {
-                       printk(KERN_ERR "ide-tape: bh == NULL in %s\n",
-                                       __func__);
-                       return;
-               }
+               if (bh == NULL)
+                       break;
                count = min((unsigned int)pc->b_count, (unsigned int)bcount);
                drive->hwif->tp_ops->output_data(drive, NULL, pc->b_data, count);
                bcount -= count;
@@ -375,6 +348,8 @@ static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
                        }
                }
        }
+
+       return bcount;
 }
 
 static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc)
@@ -407,7 +382,7 @@ static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc)
 static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
 {
        idetape_tape_t *tape = drive->driver_data;
-       struct ide_atapi_pc *pc = tape->failed_pc;
+       struct ide_atapi_pc *pc = drive->failed_pc;
 
        tape->sense_key = sense[2] & 0xF;
        tape->asc       = sense[12];
@@ -440,19 +415,19 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
                }
        }
        if (pc->c[0] == READ_6 && (sense[2] & 0x80)) {
-               pc->error = IDETAPE_ERROR_FILEMARK;
+               pc->error = IDE_DRV_ERROR_FILEMARK;
                pc->flags |= PC_FLAG_ABORT;
        }
        if (pc->c[0] == WRITE_6) {
                if ((sense[2] & 0x40) || (tape->sense_key == 0xd
                     && tape->asc == 0x0 && tape->ascq == 0x2)) {
-                       pc->error = IDETAPE_ERROR_EOD;
+                       pc->error = IDE_DRV_ERROR_EOD;
                        pc->flags |= PC_FLAG_ABORT;
                }
        }
        if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) {
                if (tape->sense_key == 8) {
-                       pc->error = IDETAPE_ERROR_EOD;
+                       pc->error = IDE_DRV_ERROR_EOD;
                        pc->flags |= PC_FLAG_ABORT;
                }
                if (!(pc->flags & PC_FLAG_ABORT) &&
@@ -484,52 +459,23 @@ static void ide_tape_kfree_buffer(idetape_tape_t *tape)
        }
 }
 
-static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
-{
-       struct request *rq = HWGROUP(drive)->rq;
-       idetape_tape_t *tape = drive->driver_data;
-       unsigned long flags;
-       int error;
-
-       debug_log(DBG_PROCS, "Enter %s\n", __func__);
-
-       switch (uptodate) {
-       case 0: error = IDETAPE_ERROR_GENERAL; break;
-       case 1: error = 0; break;
-       default: error = uptodate;
-       }
-       rq->errors = error;
-       if (error)
-               tape->failed_pc = NULL;
-
-       if (!blk_special_request(rq)) {
-               ide_end_request(drive, uptodate, nr_sects);
-               return 0;
-       }
-
-       spin_lock_irqsave(&tape->lock, flags);
-
-       ide_end_drive_cmd(drive, 0, 0);
-
-       spin_unlock_irqrestore(&tape->lock, flags);
-       return 0;
-}
-
 static void ide_tape_handle_dsc(ide_drive_t *);
 
-static void ide_tape_callback(ide_drive_t *drive, int dsc)
+static int ide_tape_callback(ide_drive_t *drive, int dsc)
 {
        idetape_tape_t *tape = drive->driver_data;
        struct ide_atapi_pc *pc = drive->pc;
+       struct request *rq = drive->hwif->rq;
        int uptodate = pc->error ? 0 : 1;
+       int err = uptodate ? 0 : IDE_DRV_ERROR_GENERAL;
 
        debug_log(DBG_PROCS, "Enter %s\n", __func__);
 
        if (dsc)
                ide_tape_handle_dsc(drive);
 
-       if (tape->failed_pc == pc)
-               tape->failed_pc = NULL;
+       if (drive->failed_pc == pc)
+               drive->failed_pc = NULL;
 
        if (pc->c[0] == REQUEST_SENSE) {
                if (uptodate)
@@ -538,7 +484,6 @@ static void ide_tape_callback(ide_drive_t *drive, int dsc)
                        printk(KERN_ERR "ide-tape: Error in REQUEST SENSE "
                                        "itself - Aborting request!\n");
        } else if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) {
-               struct request *rq = drive->hwif->hwgroup->rq;
                int blocks = pc->xferred / tape->blk_size;
 
                tape->avg_size += blocks * tape->blk_size;
@@ -553,8 +498,10 @@ static void ide_tape_callback(ide_drive_t *drive, int dsc)
                tape->first_frame += blocks;
                rq->current_nr_sectors -= blocks;
 
-               if (pc->error)
-                       uptodate = pc->error;
+               if (pc->error) {
+                       uptodate = 0;
+                       err = pc->error;
+               }
        } else if (pc->c[0] == READ_POSITION && uptodate) {
                u8 *readpos = pc->buf;
 
@@ -568,6 +515,7 @@ static void ide_tape_callback(ide_drive_t *drive, int dsc)
                                         "to the tape\n");
                        clear_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags);
                        uptodate = 0;
+                       err = IDE_DRV_ERROR_GENERAL;
                } else {
                        debug_log(DBG_SENSE, "Block Location - %u\n",
                                        be32_to_cpup((__be32 *)&readpos[4]));
@@ -578,12 +526,14 @@ static void ide_tape_callback(ide_drive_t *drive, int dsc)
                }
        }
 
-       idetape_end_request(drive, uptodate, 0);
+       rq->errors = err;
+
+       return uptodate;
 }
 
 /*
  * Postpone the current request so that ide.c will be able to service requests
- * from another device on the same hwgroup while we are polling for DSC.
+ * from another device on the same port while we are polling for DSC.
  */
 static void idetape_postpone_request(ide_drive_t *drive)
 {
@@ -591,7 +541,8 @@ static void idetape_postpone_request(ide_drive_t *drive)
 
        debug_log(DBG_PROCS, "Enter %s\n", __func__);
 
-       tape->postponed_rq = HWGROUP(drive)->rq;
+       tape->postponed_rq = drive->hwif->rq;
+
        ide_stall_queue(drive, tape->dsc_poll_freq);
 }
 
@@ -610,12 +561,14 @@ static void ide_tape_handle_dsc(ide_drive_t *drive)
 static int ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
                                unsigned int bcount, int write)
 {
+       unsigned int bleft;
+
        if (write)
-               idetape_output_buffers(drive, pc, bcount);
+               bleft = idetape_output_buffers(drive, pc, bcount);
        else
-               idetape_input_buffers(drive, pc, bcount);
+               bleft = idetape_input_buffers(drive, pc, bcount);
 
-       return bcount;
+       return bcount - bleft;
 }
 
 /*
@@ -627,7 +580,7 @@ static int ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
  *
  * The handling will be done in three stages:
  *
- * 1. idetape_issue_pc will send the packet command to the drive, and will set
+ * 1. ide_tape_issue_pc will send the packet command to the drive, and will set
  * the interrupt handler to ide_pc_intr.
  *
  * 2. On each interrupt, ide_pc_intr will be called. This step will be
@@ -654,13 +607,10 @@ static int ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
  * again, the callback function will be called and then we will handle the next
  * request.
  */
-static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
-{
-       return ide_transfer_pc(drive, WAIT_TAPE_CMD, NULL);
-}
 
-static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
-               struct ide_atapi_pc *pc)
+static ide_startstop_t ide_tape_issue_pc(ide_drive_t *drive,
+                                        struct ide_cmd *cmd,
+                                        struct ide_atapi_pc *pc)
 {
        idetape_tape_t *tape = drive->driver_data;
 
@@ -670,8 +620,8 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
                        "Two request sense in serial were issued\n");
        }
 
-       if (tape->failed_pc == NULL && pc->c[0] != REQUEST_SENSE)
-               tape->failed_pc = pc;
+       if (drive->failed_pc == NULL && pc->c[0] != REQUEST_SENSE)
+               drive->failed_pc = pc;
 
        /* Set the current packet command */
        drive->pc = pc;
@@ -695,9 +645,9 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
                                                tape->ascq);
                        }
                        /* Giving up */
-                       pc->error = IDETAPE_ERROR_GENERAL;
+                       pc->error = IDE_DRV_ERROR_GENERAL;
                }
-               tape->failed_pc = NULL;
+               drive->failed_pc = NULL;
                drive->pc_callback(drive, 0);
                return ide_stopped;
        }
@@ -705,7 +655,7 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
 
        pc->retries++;
 
-       return ide_issue_pc(drive, idetape_transfer_pc, WAIT_TAPE_CMD, NULL);
+       return ide_issue_pc(drive, cmd);
 }
 
 /* A mode sense command is used to "sense" tape parameters. */
@@ -756,8 +706,8 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
                }
                pc->error = 0;
        } else {
-               pc->error = IDETAPE_ERROR_GENERAL;
-               tape->failed_pc = NULL;
+               pc->error = IDE_DRV_ERROR_GENERAL;
+               drive->failed_pc = NULL;
        }
        drive->pc_callback(drive, 0);
        return ide_stopped;
@@ -800,6 +750,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
        idetape_tape_t *tape = drive->driver_data;
        struct ide_atapi_pc *pc = NULL;
        struct request *postponed_rq = tape->postponed_rq;
+       struct ide_cmd cmd;
        u8 stat;
 
        debug_log(DBG_SENSE, "sector: %llu, nr_sectors: %lu,"
@@ -811,13 +762,15 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
                /* We do not support buffer cache originated requests. */
                printk(KERN_NOTICE "ide-tape: %s: Unsupported request in "
                        "request queue (%d)\n", drive->name, rq->cmd_type);
-               ide_end_request(drive, 0, 0);
+               if (blk_fs_request(rq) == 0 && rq->errors == 0)
+                       rq->errors = -EIO;
+               ide_complete_rq(drive, -EIO, ide_rq_bytes(rq));
                return ide_stopped;
        }
 
        /* Retry a failed packet command */
-       if (tape->failed_pc && drive->pc->c[0] == REQUEST_SENSE) {
-               pc = tape->failed_pc;
+       if (drive->failed_pc && drive->pc->c[0] == REQUEST_SENSE) {
+               pc = drive->failed_pc;
                goto out;
        }
 
@@ -825,7 +778,9 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
                if (rq != postponed_rq) {
                        printk(KERN_ERR "ide-tape: ide-tape.c bug - "
                                        "Two DSC requests were queued\n");
-                       idetape_end_request(drive, 0, 0);
+                       drive->failed_pc = NULL;
+                       rq->errors = 0;
+                       ide_complete_rq(drive, 0, blk_rq_bytes(rq));
                        return ide_stopped;
                }
 
@@ -837,12 +792,13 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
         */
        stat = hwif->tp_ops->read_status(hwif);
 
-       if (!drive->dsc_overlap && !(rq->cmd[13] & REQ_IDETAPE_PC2))
+       if ((drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) == 0 &&
+           (rq->cmd[13] & REQ_IDETAPE_PC2) == 0)
                set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
 
-       if (drive->post_reset == 1) {
+       if (drive->dev_flags & IDE_DFLAG_POST_RESET) {
                set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
-               drive->post_reset = 0;
+               drive->dev_flags &= ~IDE_DFLAG_POST_RESET;
        }
 
        if (!test_and_clear_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags) &&
@@ -890,7 +846,14 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
        BUG();
 
 out:
-       return idetape_issue_pc(drive, pc);
+       memset(&cmd, 0, sizeof(cmd));
+
+       if (rq_data_dir(rq))
+               cmd.tf_flags |= IDE_TFLAG_WRITE;
+
+       cmd.rq = rq;
+
+       return ide_tape_issue_pc(drive, &cmd, pc);
 }
 
 /*
@@ -1235,7 +1198,7 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks,
 
        if (tape->merge_bh)
                idetape_init_merge_buffer(tape);
-       if (errors == IDETAPE_ERROR_GENERAL)
+       if (errors == IDE_DRV_ERROR_GENERAL)
                return -EIO;
        return ret;
 }
@@ -1365,7 +1328,7 @@ static int idetape_init_read(ide_drive_t *drive)
                 * No point in issuing this if DSC overlap isn't supported, some
                 * drives (Seagate STT3401A) will return an error.
                 */
-               if (drive->dsc_overlap) {
+               if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) {
                        bytes_read = idetape_queue_rw_tail(drive,
                                                        REQ_IDETAPE_READ, 0,
                                                        tape->merge_bh);
@@ -1546,7 +1509,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
 static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
                                   size_t count, loff_t *ppos)
 {
-       struct ide_tape_obj *tape = ide_tape_f(file);
+       struct ide_tape_obj *tape = file->private_data;
        ide_drive_t *drive = tape->drive;
        ssize_t bytes_read, temp, actually_read = 0, rc;
        ssize_t ret = 0;
@@ -1608,7 +1571,7 @@ finish:
 static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
                                     size_t count, loff_t *ppos)
 {
-       struct ide_tape_obj *tape = ide_tape_f(file);
+       struct ide_tape_obj *tape = file->private_data;
        ide_drive_t *drive = tape->drive;
        ssize_t actually_written = 0;
        ssize_t ret = 0;
@@ -1641,7 +1604,7 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
                 * point in issuing this if DSC overlap isn't supported, some
                 * drives (Seagate STT3401A) will return an error.
                 */
-               if (drive->dsc_overlap) {
+               if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) {
                        ssize_t retval = idetape_queue_rw_tail(drive,
                                                        REQ_IDETAPE_WRITE, 0,
                                                        tape->merge_bh);
@@ -1840,7 +1803,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
 static int idetape_chrdev_ioctl(struct inode *inode, struct file *file,
                                unsigned int cmd, unsigned long arg)
 {
-       struct ide_tape_obj *tape = ide_tape_f(file);
+       struct ide_tape_obj *tape = file->private_data;
        ide_drive_t *drive = tape->drive;
        struct mtop mtop;
        struct mtget mtget;
@@ -2017,7 +1980,7 @@ static void idetape_write_release(ide_drive_t *drive, unsigned int minor)
 
 static int idetape_chrdev_release(struct inode *inode, struct file *filp)
 {
-       struct ide_tape_obj *tape = ide_tape_f(filp);
+       struct ide_tape_obj *tape = filp->private_data;
        ide_drive_t *drive = tape->drive;
        unsigned int minor = iminor(inode);
 
@@ -2051,9 +2014,13 @@ static void idetape_get_inquiry_results(ide_drive_t *drive)
 {
        idetape_tape_t *tape = drive->driver_data;
        struct ide_atapi_pc pc;
+       u8 pc_buf[256];
        char fw_rev[4], vendor_id[8], product_id[16];
 
        idetape_create_inquiry_cmd(&pc);
+       pc.buf = &pc_buf[0];
+       pc.buf_size = sizeof(pc_buf);
+
        if (ide_queue_pc_tail(drive, tape->disk, &pc)) {
                printk(KERN_ERR "ide-tape: %s: can't get INQUIRY results\n",
                                tape->name);
@@ -2118,7 +2085,7 @@ static void idetape_get_mode_sense_results(ide_drive_t *drive)
 
        /* device lacks locking support according to capabilities page */
        if ((caps[6] & 1) == 0)
-               drive->atapi_flags |= IDE_AFLAG_NO_DOORLOCK;
+               drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
 
        if (caps[7] & 0x02)
                tape->blk_size = 512;
@@ -2156,7 +2123,7 @@ static int divf_tdsc(ide_drive_t *drive)  { return   HZ; }
 static int divf_buffer(ide_drive_t *drive)     { return    2; }
 static int divf_buffer_size(ide_drive_t *drive)        { return 1024; }
 
-ide_devset_rw_field(dsc_overlap, dsc_overlap);
+ide_devset_rw_flag(dsc_overlap, IDE_DFLAG_DSC_OVERLAP);
 
 ide_tape_devset_rw_field(debug_mask, debug_mask);
 ide_tape_devset_rw_field(tdsc, best_dsc_rw_freq);
@@ -2175,7 +2142,7 @@ static const struct ide_proc_devset idetape_settings[] = {
        __IDE_PROC_DEVSET(speed,        0, 0xffff, NULL, NULL),
        __IDE_PROC_DEVSET(tdsc,         IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX,
                                        mulf_tdsc, divf_tdsc),
-       { 0 },
+       { NULL },
 };
 #endif
 
@@ -2195,35 +2162,30 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
        unsigned long t;
        int speed;
        int buffer_size;
-       u8 gcw[2];
        u16 *ctl = (u16 *)&tape->caps[12];
 
        drive->pc_callback       = ide_tape_callback;
        drive->pc_update_buffers = idetape_update_buffers;
        drive->pc_io_buffers     = ide_tape_io_buffers;
 
-       spin_lock_init(&tape->lock);
-       drive->dsc_overlap = 1;
+       drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
+
        if (drive->hwif->host_flags & IDE_HFLAG_NO_DSC) {
                printk(KERN_INFO "ide-tape: %s: disabling DSC overlap\n",
                                 tape->name);
-               drive->dsc_overlap = 0;
+               drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
        }
+
        /* Seagate Travan drives do not support DSC overlap. */
        if (strstr((char *)&drive->id[ATA_ID_PROD], "Seagate STT3401"))
-               drive->dsc_overlap = 0;
+               drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
+
        tape->minor = minor;
        tape->name[0] = 'h';
        tape->name[1] = 't';
        tape->name[2] = '0' + minor;
        tape->chrdev_dir = IDETAPE_DIR_NONE;
 
-       *((u16 *)&gcw) = drive->id[ATA_ID_CONFIG];
-
-       /* Command packet DRQ type */
-       if (((gcw[0] & 0x60) >> 5) == 1)
-               set_bit(IDE_AFLAG_DRQ_INTERRUPT, &drive->atapi_flags);
-
        idetape_get_inquiry_results(drive);
        idetape_get_mode_sense_results(drive);
        ide_tape_get_bsize_from_bdesc(drive);
@@ -2258,7 +2220,7 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
                (*(u16 *)&tape->caps[16] * 512) / tape->buffer_size,
                tape->buffer_size / 1024,
                tape->best_dsc_rw_freq * 1000 / HZ,
-               drive->using_dma ? ", DMA":"");
+               (drive->dev_flags & IDE_DFLAG_USING_DMA) ? ", DMA" : "");
 
        ide_proc_register_driver(drive, tape->driver);
 }
@@ -2268,21 +2230,23 @@ static void ide_tape_remove(ide_drive_t *drive)
        idetape_tape_t *tape = drive->driver_data;
 
        ide_proc_unregister_driver(drive, tape->driver);
-
+       device_del(&tape->dev);
        ide_unregister_region(tape->disk);
 
-       ide_tape_put(tape);
+       mutex_lock(&idetape_ref_mutex);
+       put_device(&tape->dev);
+       mutex_unlock(&idetape_ref_mutex);
 }
 
-static void ide_tape_release(struct kref *kref)
+static void ide_tape_release(struct device *dev)
 {
-       struct ide_tape_obj *tape = to_ide_tape(kref);
+       struct ide_tape_obj *tape = to_ide_drv(dev, ide_tape_obj);
        ide_drive_t *drive = tape->drive;
        struct gendisk *g = tape->disk;
 
        BUG_ON(tape->merge_bh_size);
 
-       drive->dsc_overlap = 0;
+       drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
        drive->driver_data = NULL;
        device_destroy(idetape_sysfs_class, MKDEV(IDETAPE_MAJOR, tape->minor));
        device_destroy(idetape_sysfs_class,
@@ -2311,11 +2275,21 @@ static ide_proc_entry_t idetape_proc[] = {
        { "name",       S_IFREG|S_IRUGO,        proc_idetape_read_name, NULL },
        { NULL, 0, NULL, NULL }
 };
+
+static ide_proc_entry_t *ide_tape_proc_entries(ide_drive_t *drive)
+{
+       return idetape_proc;
+}
+
+static const struct ide_proc_devset *ide_tape_proc_devsets(ide_drive_t *drive)
+{
+       return idetape_settings;
+}
 #endif
 
 static int ide_tape_probe(ide_drive_t *);
 
-static ide_driver_t idetape_driver = {
+static struct ide_driver idetape_driver = {
        .gen_driver = {
                .owner          = THIS_MODULE,
                .name           = "ide-tape",
@@ -2324,13 +2298,10 @@ static ide_driver_t idetape_driver = {
        .probe                  = ide_tape_probe,
        .remove                 = ide_tape_remove,
        .version                = IDETAPE_VERSION,
-       .media                  = ide_tape,
        .do_request             = idetape_do_request,
-       .end_request            = idetape_end_request,
-       .error                  = __ide_error,
 #ifdef CONFIG_IDE_PROC_FS
-       .proc                   = idetape_proc,
-       .settings               = idetape_settings,
+       .proc_entries           = ide_tape_proc_entries,
+       .proc_devsets           = ide_tape_proc_devsets,
 #endif
 };
 
@@ -2344,35 +2315,30 @@ static const struct file_operations idetape_fops = {
        .release        = idetape_chrdev_release,
 };
 
-static int idetape_open(struct inode *inode, struct file *filp)
+static int idetape_open(struct block_device *bdev, fmode_t mode)
 {
-       struct gendisk *disk = inode->i_bdev->bd_disk;
-       struct ide_tape_obj *tape;
+       struct ide_tape_obj *tape = ide_tape_get(bdev->bd_disk);
 
-       tape = ide_tape_get(disk);
        if (!tape)
                return -ENXIO;
 
        return 0;
 }
 
-static int idetape_release(struct inode *inode, struct file *filp)
+static int idetape_release(struct gendisk *disk, fmode_t mode)
 {
-       struct gendisk *disk = inode->i_bdev->bd_disk;
-       struct ide_tape_obj *tape = ide_tape_g(disk);
+       struct ide_tape_obj *tape = ide_drv_g(disk, ide_tape_obj);
 
        ide_tape_put(tape);
-
        return 0;
 }
 
-static int idetape_ioctl(struct inode *inode, struct file *file,
+static int idetape_ioctl(struct block_device *bdev, fmode_t mode,
                        unsigned int cmd, unsigned long arg)
 {
-       struct block_device *bdev = inode->i_bdev;
-       struct ide_tape_obj *tape = ide_tape_g(bdev->bd_disk);
+       struct ide_tape_obj *tape = ide_drv_g(bdev->bd_disk, ide_tape_obj);
        ide_drive_t *drive = tape->drive;
-       int err = generic_ide_ioctl(drive, file, bdev, cmd, arg);
+       int err = generic_ide_ioctl(drive, bdev, cmd, arg);
        if (err == -EINVAL)
                err = idetape_blkdev_ioctl(drive, cmd, arg);
        return err;
@@ -2382,7 +2348,7 @@ static struct block_device_operations idetape_block_ops = {
        .owner          = THIS_MODULE,
        .open           = idetape_open,
        .release        = idetape_release,
-       .ioctl          = idetape_ioctl,
+       .locked_ioctl   = idetape_ioctl,
 };
 
 static int ide_tape_probe(ide_drive_t *drive)
@@ -2397,7 +2363,8 @@ static int ide_tape_probe(ide_drive_t *drive)
        if (drive->media != ide_tape)
                goto failed;
 
-       if (drive->id_read == 1 && !ide_check_atapi_device(drive, DRV_NAME)) {
+       if ((drive->dev_flags & IDE_DFLAG_ID_READ) &&
+           ide_check_atapi_device(drive, DRV_NAME) == 0) {
                printk(KERN_ERR "ide-tape: %s: not supported by this version of"
                                " the driver\n", drive->name);
                goto failed;
@@ -2415,7 +2382,12 @@ static int ide_tape_probe(ide_drive_t *drive)
 
        ide_init_disk(g, drive);
 
-       kref_init(&tape->kref);
+       tape->dev.parent = &drive->gendev;
+       tape->dev.release = ide_tape_release;
+       dev_set_name(&tape->dev, dev_name(&drive->gendev));
+
+       if (device_register(&tape->dev))
+               goto out_free_disk;
 
        tape->drive = drive;
        tape->driver = &idetape_driver;
@@ -2433,18 +2405,19 @@ static int ide_tape_probe(ide_drive_t *drive)
 
        idetape_setup(drive, tape, minor);
 
-       device_create_drvdata(idetape_sysfs_class, &drive->gendev,
-                             MKDEV(IDETAPE_MAJOR, minor), NULL,
-                             "%s", tape->name);
-       device_create_drvdata(idetape_sysfs_class, &drive->gendev,
-                             MKDEV(IDETAPE_MAJOR, minor + 128), NULL,
-                             "n%s", tape->name);
+       device_create(idetape_sysfs_class, &drive->gendev,
+                     MKDEV(IDETAPE_MAJOR, minor), NULL, "%s", tape->name);
+       device_create(idetape_sysfs_class, &drive->gendev,
+                     MKDEV(IDETAPE_MAJOR, minor + 128), NULL,
+                     "n%s", tape->name);
 
        g->fops = &idetape_block_ops;
        ide_register_region(g);
 
        return 0;
 
+out_free_disk:
+       put_disk(g);
 out_free_tape:
        kfree(tape);
 failed: