]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - include/linux/ide.h
ide: merge all TASKFILE_NO_DATA data phase handlers into taskfile_no_intr()
[linux-2.6-omap-h63xx.git] / include / linux / ide.h
index a9d82d6e6bdd68e05e0e6eb016a619d6526f6ece..14d489c2e5a909095b64a627d4a1d7e347248553 100644 (file)
@@ -48,12 +48,6 @@ typedef unsigned char        byte;   /* used everywhere */
 #define ERROR_RESET    3       /* Reset controller every 4th retry */
 #define ERROR_RECAL    1       /* Recalibrate every 2nd retry */
 
-/*
- * state flags
- */
-
-#define DMA_PIO_RETRY  1       /* retrying in PIO */
-
 #define HWIF(drive)            ((ide_hwif_t *)((drive)->hwif))
 #define HWGROUP(drive)         ((ide_hwgroup_t *)(HWIF(drive)->hwgroup))
 
@@ -268,8 +262,6 @@ static inline int __ide_default_irq(unsigned long base)
  * set_geometry        : respecify drive geometry
  * recalibrate : seek to cyl 0
  * set_multmode        : set multmode count
- * set_tune    : tune interface for drive
- * serviced    : service command
  * reserved    : unused
  */
 typedef union {
@@ -278,42 +270,10 @@ typedef union {
                unsigned set_geometry   : 1;
                unsigned recalibrate    : 1;
                unsigned set_multmode   : 1;
-               unsigned set_tune       : 1;
-               unsigned serviced       : 1;
-               unsigned reserved       : 3;
+               unsigned reserved       : 5;
        } b;
 } special_t;
 
-/*
- * ATA-IDE Select Register, aka Device-Head
- *
- * head                : always zeros here
- * unit                : drive select number: 0/1
- * bit5                : always 1
- * lba         : using LBA instead of CHS
- * bit7                : always 1
- */
-typedef union {
-       unsigned all                    : 8;
-       struct {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-               unsigned head           : 4;
-               unsigned unit           : 1;
-               unsigned bit5           : 1;
-               unsigned lba            : 1;
-               unsigned bit7           : 1;
-#elif defined(__BIG_ENDIAN_BITFIELD)
-               unsigned bit7           : 1;
-               unsigned lba            : 1;
-               unsigned bit5           : 1;
-               unsigned unit           : 1;
-               unsigned head           : 4;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
-       } b;
-} select_t, ata_select_t;
-
 /*
  * Status returned from various ide_ functions
  */
@@ -322,6 +282,175 @@ typedef enum {
        ide_started,    /* a drive operation was started, handler was set */
 } ide_startstop_t;
 
+enum {
+       IDE_TFLAG_LBA48                 = (1 << 0),
+       IDE_TFLAG_FLAGGED               = (1 << 2),
+       IDE_TFLAG_OUT_DATA              = (1 << 3),
+       IDE_TFLAG_OUT_HOB_FEATURE       = (1 << 4),
+       IDE_TFLAG_OUT_HOB_NSECT         = (1 << 5),
+       IDE_TFLAG_OUT_HOB_LBAL          = (1 << 6),
+       IDE_TFLAG_OUT_HOB_LBAM          = (1 << 7),
+       IDE_TFLAG_OUT_HOB_LBAH          = (1 << 8),
+       IDE_TFLAG_OUT_HOB               = IDE_TFLAG_OUT_HOB_FEATURE |
+                                         IDE_TFLAG_OUT_HOB_NSECT |
+                                         IDE_TFLAG_OUT_HOB_LBAL |
+                                         IDE_TFLAG_OUT_HOB_LBAM |
+                                         IDE_TFLAG_OUT_HOB_LBAH,
+       IDE_TFLAG_OUT_FEATURE           = (1 << 9),
+       IDE_TFLAG_OUT_NSECT             = (1 << 10),
+       IDE_TFLAG_OUT_LBAL              = (1 << 11),
+       IDE_TFLAG_OUT_LBAM              = (1 << 12),
+       IDE_TFLAG_OUT_LBAH              = (1 << 13),
+       IDE_TFLAG_OUT_TF                = IDE_TFLAG_OUT_FEATURE |
+                                         IDE_TFLAG_OUT_NSECT |
+                                         IDE_TFLAG_OUT_LBAL |
+                                         IDE_TFLAG_OUT_LBAM |
+                                         IDE_TFLAG_OUT_LBAH,
+       IDE_TFLAG_OUT_DEVICE            = (1 << 14),
+       IDE_TFLAG_WRITE                 = (1 << 15),
+       IDE_TFLAG_FLAGGED_SET_IN_FLAGS  = (1 << 16),
+       IDE_TFLAG_IN_DATA               = (1 << 17),
+       IDE_TFLAG_CUSTOM_HANDLER        = (1 << 18),
+       IDE_TFLAG_DMA_PIO_FALLBACK      = (1 << 19),
+       IDE_TFLAG_IN_HOB_FEATURE        = (1 << 20),
+       IDE_TFLAG_IN_HOB_NSECT          = (1 << 21),
+       IDE_TFLAG_IN_HOB_LBAL           = (1 << 22),
+       IDE_TFLAG_IN_HOB_LBAM           = (1 << 23),
+       IDE_TFLAG_IN_HOB_LBAH           = (1 << 24),
+       IDE_TFLAG_IN_HOB_LBA            = IDE_TFLAG_IN_HOB_LBAL |
+                                         IDE_TFLAG_IN_HOB_LBAM |
+                                         IDE_TFLAG_IN_HOB_LBAH,
+       IDE_TFLAG_IN_HOB                = IDE_TFLAG_IN_HOB_FEATURE |
+                                         IDE_TFLAG_IN_HOB_NSECT |
+                                         IDE_TFLAG_IN_HOB_LBA,
+       IDE_TFLAG_IN_FEATURE            = (1 << 1),
+       IDE_TFLAG_IN_NSECT              = (1 << 25),
+       IDE_TFLAG_IN_LBAL               = (1 << 26),
+       IDE_TFLAG_IN_LBAM               = (1 << 27),
+       IDE_TFLAG_IN_LBAH               = (1 << 28),
+       IDE_TFLAG_IN_LBA                = IDE_TFLAG_IN_LBAL |
+                                         IDE_TFLAG_IN_LBAM |
+                                         IDE_TFLAG_IN_LBAH,
+       IDE_TFLAG_IN_TF                 = IDE_TFLAG_IN_NSECT |
+                                         IDE_TFLAG_IN_LBA,
+       IDE_TFLAG_IN_DEVICE             = (1 << 29),
+       IDE_TFLAG_HOB                   = IDE_TFLAG_OUT_HOB |
+                                         IDE_TFLAG_IN_HOB,
+       IDE_TFLAG_TF                    = IDE_TFLAG_OUT_TF |
+                                         IDE_TFLAG_IN_TF,
+       IDE_TFLAG_DEVICE                = IDE_TFLAG_OUT_DEVICE |
+                                         IDE_TFLAG_IN_DEVICE,
+       /* force 16-bit I/O operations */
+       IDE_TFLAG_IO_16BIT              = (1 << 30),
+       /* ide_task_t was allocated using kmalloc() */
+       IDE_TFLAG_DYN                   = (1 << 31),
+};
+
+struct ide_taskfile {
+       u8      hob_data;       /*  0: high data byte (for TASKFILE IOCTL) */
+
+       u8      hob_feature;    /*  1-5: additional data to support LBA48 */
+       u8      hob_nsect;
+       u8      hob_lbal;
+       u8      hob_lbam;
+       u8      hob_lbah;
+
+       u8      data;           /*  6: low data byte (for TASKFILE IOCTL) */
+
+       union {                 /*  7: */
+               u8 error;       /*   read:  error */
+               u8 feature;     /*  write: feature */
+       };
+
+       u8      nsect;          /*  8: number of sectors */
+       u8      lbal;           /*  9: LBA low */
+       u8      lbam;           /* 10: LBA mid */
+       u8      lbah;           /* 11: LBA high */
+
+       u8      device;         /* 12: device select */
+
+       union {                 /* 13: */
+               u8 status;      /*  read: status  */
+               u8 command;     /* write: command */
+       };
+};
+
+typedef struct ide_task_s {
+       union {
+               struct ide_taskfile     tf;
+               u8                      tf_array[14];
+       };
+       u32                     tf_flags;
+       int                     data_phase;
+       struct request          *rq;            /* copy of request */
+       void                    *special;       /* valid_t generally */
+} ide_task_t;
+
+/* ATAPI packet command flags */
+enum {
+       /* set when an error is considered normal - no retry (ide-tape) */
+       PC_FLAG_ABORT                   = (1 << 0),
+       PC_FLAG_SUPPRESS_ERROR          = (1 << 1),
+       PC_FLAG_WAIT_FOR_DSC            = (1 << 2),
+       PC_FLAG_DMA_OK                  = (1 << 3),
+       PC_FLAG_DMA_IN_PROGRESS         = (1 << 4),
+       PC_FLAG_DMA_ERROR               = (1 << 5),
+       PC_FLAG_WRITING                 = (1 << 6),
+       /* command timed out */
+       PC_FLAG_TIMEDOUT                = (1 << 7),
+};
+
+/*
+ * With each packet command, we allocate a buffer of IDE_PC_BUFFER_SIZE bytes.
+ * This is used for several packet commands (not for READ/WRITE commands).
+ */
+#define IDE_PC_BUFFER_SIZE     256
+
+struct ide_atapi_pc {
+       /* actual packet bytes */
+       u8 c[12];
+       /* incremented on each retry */
+       int retries;
+       int error;
+
+       /* bytes to transfer */
+       int req_xfer;
+       /* bytes actually transferred */
+       int xferred;
+
+       /* data buffer */
+       u8 *buf;
+       /* current buffer position */
+       u8 *cur_pos;
+       int buf_size;
+       /* missing/available data on the current buffer */
+       int b_count;
+
+       /* the corresponding request */
+       struct request *rq;
+
+       unsigned long flags;
+
+       /*
+        * those are more or less driver-specific and some of them are subject
+        * to change/removal later.
+        */
+       u8 pc_buf[IDE_PC_BUFFER_SIZE];
+
+       /* idetape only */
+       struct idetape_bh *bh;
+       char *b_data;
+
+       /* idescsi only for now */
+       struct scatterlist *sg;
+       unsigned int sg_cnt;
+
+       struct scsi_cmnd *scsi_cmd;
+       void (*done) (struct scsi_cmnd *);
+
+       unsigned long timeout;
+};
+
 struct ide_devset;
 struct ide_driver_s;
 
@@ -394,6 +523,58 @@ enum {
        IDE_AFLAG_NO_AUTOCLOSE          = (1 << 29),
 };
 
+/* device flags */
+enum {
+       /* restore settings after device reset */
+       IDE_DFLAG_KEEP_SETTINGS         = (1 << 0),
+       /* device is using DMA for read/write */
+       IDE_DFLAG_USING_DMA             = (1 << 1),
+       /* okay to unmask other IRQs */
+       IDE_DFLAG_UNMASK                = (1 << 2),
+       /* don't attempt flushes */
+       IDE_DFLAG_NOFLUSH               = (1 << 3),
+       /* DSC overlap */
+       IDE_DFLAG_DSC_OVERLAP           = (1 << 4),
+       /* give potential excess bandwidth */
+       IDE_DFLAG_NICE1                 = (1 << 5),
+       /* device is physically present */
+       IDE_DFLAG_PRESENT               = (1 << 6),
+       /* device ejected hint */
+       IDE_DFLAG_DEAD                  = (1 << 7),
+       /* id read from device (synthetic if not set) */
+       IDE_DFLAG_ID_READ               = (1 << 8),
+       IDE_DFLAG_NOPROBE               = (1 << 9),
+       /* need to do check_media_change() */
+       IDE_DFLAG_REMOVABLE             = (1 << 10),
+       /* needed for removable devices */
+       IDE_DFLAG_ATTACH                = (1 << 11),
+       IDE_DFLAG_FORCED_GEOM           = (1 << 12),
+       /* disallow setting unmask bit */
+       IDE_DFLAG_NO_UNMASK             = (1 << 13),
+       /* disallow enabling 32-bit I/O */
+       IDE_DFLAG_NO_IO_32BIT           = (1 << 14),
+       /* for removable only: door lock/unlock works */
+       IDE_DFLAG_DOORLOCKING           = (1 << 15),
+       /* disallow DMA */
+       IDE_DFLAG_NODMA                 = (1 << 16),
+       /* powermanagment told us not to do anything, so sleep nicely */
+       IDE_DFLAG_BLOCKED               = (1 << 17),
+       /* ide-scsi emulation */
+       IDE_DFLAG_SCSI                  = (1 << 18),
+       /* sleeping & sleep field valid */
+       IDE_DFLAG_SLEEPING              = (1 << 19),
+       IDE_DFLAG_POST_RESET            = (1 << 20),
+       IDE_DFLAG_UDMA33_WARNED         = (1 << 21),
+       IDE_DFLAG_LBA48                 = (1 << 22),
+       /* status of write cache */
+       IDE_DFLAG_WCACHE                = (1 << 23),
+       /* used for ignoring ATA_DF */
+       IDE_DFLAG_NOWERR                = (1 << 24),
+       /* retrying in PIO */
+       IDE_DFLAG_DMA_PIO_RETRY         = (1 << 25),
+       IDE_DFLAG_LBA                   = (1 << 26),
+};
+
 struct ide_drive_s {
        char            name[4];        /* drive name, such as "hda" */
         char            driver_req[10];        /* requests specific driver */
@@ -410,44 +591,19 @@ struct ide_drive_s {
 #endif
        struct hwif_s           *hwif;  /* actually (ide_hwif_t *) */
 
+       unsigned long dev_flags;
+
        unsigned long sleep;            /* sleep until this time */
        unsigned long service_start;    /* time we started last request */
        unsigned long service_time;     /* service time of last request */
        unsigned long timeout;          /* max time to wait for irq */
 
        special_t       special;        /* special action flags */
-       select_t        select;         /* basic drive/head select reg value */
 
+       u8      select;                 /* basic drive/head select reg value */
        u8      retry_pio;              /* retrying dma capable host in pio */
-       u8      state;                  /* retry state */
        u8      waiting_for_dma;        /* dma currently in progress */
 
-       unsigned keep_settings  : 1;    /* restore settings after drive reset */
-       unsigned using_dma      : 1;    /* disk is using dma for read/write */
-       unsigned unmask         : 1;    /* okay to unmask other irqs */
-       unsigned noflush        : 1;    /* don't attempt flushes */
-       unsigned dsc_overlap    : 1;    /* DSC overlap */
-       unsigned nice1          : 1;    /* give potential excess bandwidth */
-       unsigned present        : 1;    /* drive is physically present */
-       unsigned dead           : 1;    /* device ejected hint */
-       unsigned id_read        : 1;    /* 1=id read from disk 0 = synthetic */
-       unsigned noprobe        : 1;    /* from:  hdx=noprobe */
-       unsigned removable      : 1;    /* 1 if need to do check_media_change */
-       unsigned attach         : 1;    /* needed for removable devices */
-       unsigned forced_geom    : 1;    /* 1 if hdx=c,h,s was given at boot */
-       unsigned no_unmask      : 1;    /* disallow setting unmask bit */
-       unsigned no_io_32bit    : 1;    /* disallow enabling 32bit I/O */
-       unsigned doorlocking    : 1;    /* for removable only: door lock/unlock works */
-       unsigned nodma          : 1;    /* disallow DMA */
-       unsigned blocked        : 1;    /* 1=powermanagment told us not to do anything, so sleep nicely */
-       unsigned scsi           : 1;    /* 0=default, 1=ide-scsi emulation */
-       unsigned sleeping       : 1;    /* 1=sleeping & sleep field valid */
-       unsigned post_reset     : 1;
-       unsigned udma33_warned  : 1;
-       unsigned addressing     : 2;    /* 0=28-bit, 1=48-bit, 2=48-bit doing 28-bit */
-       unsigned wcache         : 1;    /* status of write cache */
-       unsigned nowerr         : 1;    /* used for ignoring ATA_DF */
-
         u8     quirk_list;     /* considered quirky, set for a specific host */
         u8     init_speed;     /* transfer rate set at boot */
         u8     current_speed;  /* current transfer rate set */
@@ -458,7 +614,6 @@ struct ide_drive_s {
        u8      ready_stat;     /* min status value for drive ready */
        u8      mult_count;     /* current multiple sector setting */
        u8      mult_req;       /* requested multiple sector setting */
-       u8      tune_req;       /* requested drive tuning setting */
        u8      io_32bit;       /* 0=16-bit, 1=32-bit, 2/3=32bit+sync */
        u8      bad_wstat;      /* used for ignoring ATA_DF */
        u8      head;           /* "real" number of heads */
@@ -466,6 +621,9 @@ struct ide_drive_s {
        u8      bios_head;      /* BIOS/fdisk/LILO number of heads */
        u8      bios_sect;      /* BIOS/fdisk/LILO sectors per track */
 
+       /* delay this long before sending packet command */
+       u8 pc_delay;
+
        unsigned int    bios_cyl;       /* BIOS/fdisk/LILO number of cyls */
        unsigned int    cyl;            /* "real" number of cyls */
        unsigned int    drive_data;     /* used by set_pio_mode/selectproc */
@@ -477,6 +635,9 @@ struct ide_drive_s {
 
        int             lun;            /* logical unit */
        int             crc_count;      /* crc counter to reduce drive speed */
+
+       unsigned long   debug_mask;     /* debugging levels switch */
+
 #ifdef CONFIG_BLK_DEV_IDEACPI
        struct ide_acpi_drive_link *acpidata;
 #endif
@@ -484,17 +645,32 @@ struct ide_drive_s {
        struct device   gendev;
        struct completion gendev_rel_comp;      /* to deal with device release() */
 
+       /* current packet command */
+       struct ide_atapi_pc *pc;
+
        /* callback for packet commands */
-       void (*pc_callback)(struct ide_drive_s *);
+       void (*pc_callback)(struct ide_drive_s *, int);
+
+       void (*pc_update_buffers)(struct ide_drive_s *, struct ide_atapi_pc *);
+       int  (*pc_io_buffers)(struct ide_drive_s *, struct ide_atapi_pc *,
+                             unsigned int, int);
 
        unsigned long atapi_flags;
+
+       struct ide_atapi_pc request_sense_pc;
+       struct request request_sense_rq;
 };
 
 typedef struct ide_drive_s ide_drive_t;
 
-#define to_ide_device(dev)container_of(dev, ide_drive_t, gendev)
+#define to_ide_device(dev)             container_of(dev, ide_drive_t, gendev)
+
+#define to_ide_drv(obj, cont_type)     \
+       container_of(obj, struct cont_type, kref)
+
+#define ide_drv_g(disk, cont_type)     \
+       container_of((disk)->private_data, struct cont_type, driver)
 
-struct ide_task_s;
 struct ide_port_info;
 
 struct ide_tp_ops {
@@ -621,6 +797,8 @@ typedef struct hwif_s {
        /* data phase of the active command (currently only valid for PIO/DMA) */
        int             data_phase;
 
+       struct ide_task_s task;         /* current command */
+
        unsigned int nsect;
        unsigned int nleft;
        struct scatterlist *cursg;
@@ -649,8 +827,6 @@ typedef struct hwif_s {
 
        void            *hwif_data;     /* extra hwif data */
 
-       unsigned dma;
-
 #ifdef CONFIG_BLK_DEV_IDEACPI
        struct ide_acpi_hwif_link *acpidata;
 #endif
@@ -739,6 +915,22 @@ static int set_##name(ide_drive_t *drive, int arg) \
        return 0; \
 }
 
+#define ide_devset_get_flag(name, flag) \
+static int get_##name(ide_drive_t *drive) \
+{ \
+       return !!(drive->dev_flags & flag); \
+}
+
+#define ide_devset_set_flag(name, flag) \
+static int set_##name(ide_drive_t *drive, int arg) \
+{ \
+       if (arg) \
+               drive->dev_flags |= flag; \
+       else \
+               drive->dev_flags &= ~flag; \
+       return 0; \
+}
+
 #define __IDE_DEVSET(_name, _flags, _get, _set) \
 const struct ide_devset ide_devset_##_name = \
        __DEVSET(_flags, _get, _set)
@@ -764,71 +956,6 @@ ide_decl_devset(pio_mode);
 ide_decl_devset(unmaskirq);
 ide_decl_devset(using_dma);
 
-/* ATAPI packet command flags */
-enum {
-       /* set when an error is considered normal - no retry (ide-tape) */
-       PC_FLAG_ABORT                   = (1 << 0),
-       PC_FLAG_SUPPRESS_ERROR          = (1 << 1),
-       PC_FLAG_WAIT_FOR_DSC            = (1 << 2),
-       PC_FLAG_DMA_OK                  = (1 << 3),
-       PC_FLAG_DMA_IN_PROGRESS         = (1 << 4),
-       PC_FLAG_DMA_ERROR               = (1 << 5),
-       PC_FLAG_WRITING                 = (1 << 6),
-       /* command timed out */
-       PC_FLAG_TIMEDOUT                = (1 << 7),
-};
-
-/*
- * With each packet command, we allocate a buffer of IDE_PC_BUFFER_SIZE bytes.
- * This is used for several packet commands (not for READ/WRITE commands).
- */
-#define IDE_PC_BUFFER_SIZE     256
-
-struct ide_atapi_pc {
-       /* actual packet bytes */
-       u8 c[12];
-       /* incremented on each retry */
-       int retries;
-       int error;
-
-       /* bytes to transfer */
-       int req_xfer;
-       /* bytes actually transferred */
-       int xferred;
-
-       /* data buffer */
-       u8 *buf;
-       /* current buffer position */
-       u8 *cur_pos;
-       int buf_size;
-       /* missing/available data on the current buffer */
-       int b_count;
-
-       /* the corresponding request */
-       struct request *rq;
-
-       unsigned long flags;
-
-       /*
-        * those are more or less driver-specific and some of them are subject
-        * to change/removal later.
-        */
-       u8 pc_buf[IDE_PC_BUFFER_SIZE];
-
-       /* idetape only */
-       struct idetape_bh *bh;
-       char *b_data;
-
-       /* idescsi only for now */
-       struct scatterlist *sg;
-       unsigned int sg_cnt;
-
-       struct scsi_cmnd *scsi_cmd;
-       void (*done) (struct scsi_cmnd *);
-
-       unsigned long timeout;
-};
-
 #ifdef CONFIG_IDE_PROC_FS
 /*
  * /proc/ide interface
@@ -839,6 +966,11 @@ ide_devset_get(_name, _field); \
 ide_devset_set(_name, _field); \
 IDE_DEVSET(_name, DS_SYNC, get_##_name, set_##_name)
 
+#define ide_devset_rw_flag(_name, _field) \
+ide_devset_get_flag(_name, _field); \
+ide_devset_set_flag(_name, _field); \
+IDE_DEVSET(_name, DS_SYNC, get_##_name, set_##_name)
+
 struct ide_proc_devset {
        const char              *name;
        const struct ide_devset *setting;
@@ -905,37 +1037,55 @@ static inline void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *
 #define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) return 0;
 #endif
 
+enum {
+       /* enter/exit functions */
+       IDE_DBG_FUNC =                  (1 << 0),
+       /* sense key/asc handling */
+       IDE_DBG_SENSE =                 (1 << 1),
+       /* packet commands handling */
+       IDE_DBG_PC =                    (1 << 2),
+       /* request handling */
+       IDE_DBG_RQ =                    (1 << 3),
+       /* driver probing/setup */
+       IDE_DBG_PROBE =                 (1 << 4),
+};
+
+/* DRV_NAME has to be defined in the driver before using the macro below */
+#define __ide_debug_log(lvl, fmt, args...)                     \
+{                                                              \
+       if (unlikely(drive->debug_mask & lvl))                  \
+               printk(KERN_INFO DRV_NAME ": " fmt, ## args);   \
+}
+
 /*
- * Power Management step value (rq->pm->pm_step).
+ * Power Management state machine (rq->pm->pm_step).
  *
- * The step value starts at 0 (ide_pm_state_start_suspend) for a
- * suspend operation or 1000 (ide_pm_state_start_resume) for a
- * resume operation.
- *
- * For each step, the core calls the subdriver start_power_step() first.
+ * For each step, the core calls ide_start_power_step() first.
  * This can return:
  *     - ide_stopped : In this case, the core calls us back again unless
  *                     step have been set to ide_power_state_completed.
  *     - ide_started : In this case, the channel is left busy until an
  *                     async event (interrupt) occurs.
- * Typically, start_power_step() will issue a taskfile request with
+ * Typically, ide_start_power_step() will issue a taskfile request with
  * do_rw_taskfile().
  *
- * Upon reception of the interrupt, the core will call complete_power_step()
+ * Upon reception of the interrupt, the core will call ide_complete_power_step()
  * with the error code if any. This routine should update the step value
  * and return. It should not start a new request. The core will call
- * start_power_step for the new step value, unless step have been set to
- * ide_power_state_completed.
- *
- * Subdrivers are expected to define their own additional power
- * steps from 1..999 for suspend and from 1001..1999 for resume,
- * other values are reserved for future use.
+ * ide_start_power_step() for the new step value, unless step have been
+ * set to IDE_PM_COMPLETED.
  */
-
 enum {
-       ide_pm_state_completed          = -1,
-       ide_pm_state_start_suspend      = 0,
-       ide_pm_state_start_resume       = 1000,
+       IDE_PM_START_SUSPEND,
+       IDE_PM_FLUSH_CACHE      = IDE_PM_START_SUSPEND,
+       IDE_PM_STANDBY,
+
+       IDE_PM_START_RESUME,
+       IDE_PM_RESTORE_PIO      = IDE_PM_START_RESUME,
+       IDE_PM_IDLE,
+       IDE_PM_RESTORE_DMA,
+
+       IDE_PM_COMPLETED,
 };
 
 /*
@@ -946,7 +1096,6 @@ enum {
  */
 struct ide_driver_s {
        const char                      *version;
-       u8                              media;
        ide_startstop_t (*do_request)(ide_drive_t *, struct request *, sector_t);
        int             (*end_request)(ide_drive_t *, int, int);
        ide_startstop_t (*error)(ide_drive_t *, struct request *rq, u8, u8);
@@ -1015,110 +1164,6 @@ extern void ide_do_drive_cmd(ide_drive_t *, struct request *);
 
 extern void ide_end_drive_cmd(ide_drive_t *, u8, u8);
 
-enum {
-       IDE_TFLAG_LBA48                 = (1 << 0),
-       IDE_TFLAG_FLAGGED               = (1 << 2),
-       IDE_TFLAG_OUT_DATA              = (1 << 3),
-       IDE_TFLAG_OUT_HOB_FEATURE       = (1 << 4),
-       IDE_TFLAG_OUT_HOB_NSECT         = (1 << 5),
-       IDE_TFLAG_OUT_HOB_LBAL          = (1 << 6),
-       IDE_TFLAG_OUT_HOB_LBAM          = (1 << 7),
-       IDE_TFLAG_OUT_HOB_LBAH          = (1 << 8),
-       IDE_TFLAG_OUT_HOB               = IDE_TFLAG_OUT_HOB_FEATURE |
-                                         IDE_TFLAG_OUT_HOB_NSECT |
-                                         IDE_TFLAG_OUT_HOB_LBAL |
-                                         IDE_TFLAG_OUT_HOB_LBAM |
-                                         IDE_TFLAG_OUT_HOB_LBAH,
-       IDE_TFLAG_OUT_FEATURE           = (1 << 9),
-       IDE_TFLAG_OUT_NSECT             = (1 << 10),
-       IDE_TFLAG_OUT_LBAL              = (1 << 11),
-       IDE_TFLAG_OUT_LBAM              = (1 << 12),
-       IDE_TFLAG_OUT_LBAH              = (1 << 13),
-       IDE_TFLAG_OUT_TF                = IDE_TFLAG_OUT_FEATURE |
-                                         IDE_TFLAG_OUT_NSECT |
-                                         IDE_TFLAG_OUT_LBAL |
-                                         IDE_TFLAG_OUT_LBAM |
-                                         IDE_TFLAG_OUT_LBAH,
-       IDE_TFLAG_OUT_DEVICE            = (1 << 14),
-       IDE_TFLAG_WRITE                 = (1 << 15),
-       IDE_TFLAG_FLAGGED_SET_IN_FLAGS  = (1 << 16),
-       IDE_TFLAG_IN_DATA               = (1 << 17),
-       IDE_TFLAG_CUSTOM_HANDLER        = (1 << 18),
-       IDE_TFLAG_DMA_PIO_FALLBACK      = (1 << 19),
-       IDE_TFLAG_IN_HOB_FEATURE        = (1 << 20),
-       IDE_TFLAG_IN_HOB_NSECT          = (1 << 21),
-       IDE_TFLAG_IN_HOB_LBAL           = (1 << 22),
-       IDE_TFLAG_IN_HOB_LBAM           = (1 << 23),
-       IDE_TFLAG_IN_HOB_LBAH           = (1 << 24),
-       IDE_TFLAG_IN_HOB_LBA            = IDE_TFLAG_IN_HOB_LBAL |
-                                         IDE_TFLAG_IN_HOB_LBAM |
-                                         IDE_TFLAG_IN_HOB_LBAH,
-       IDE_TFLAG_IN_HOB                = IDE_TFLAG_IN_HOB_FEATURE |
-                                         IDE_TFLAG_IN_HOB_NSECT |
-                                         IDE_TFLAG_IN_HOB_LBA,
-       IDE_TFLAG_IN_FEATURE            = (1 << 1),
-       IDE_TFLAG_IN_NSECT              = (1 << 25),
-       IDE_TFLAG_IN_LBAL               = (1 << 26),
-       IDE_TFLAG_IN_LBAM               = (1 << 27),
-       IDE_TFLAG_IN_LBAH               = (1 << 28),
-       IDE_TFLAG_IN_LBA                = IDE_TFLAG_IN_LBAL |
-                                         IDE_TFLAG_IN_LBAM |
-                                         IDE_TFLAG_IN_LBAH,
-       IDE_TFLAG_IN_TF                 = IDE_TFLAG_IN_NSECT |
-                                         IDE_TFLAG_IN_LBA,
-       IDE_TFLAG_IN_DEVICE             = (1 << 29),
-       IDE_TFLAG_HOB                   = IDE_TFLAG_OUT_HOB |
-                                         IDE_TFLAG_IN_HOB,
-       IDE_TFLAG_TF                    = IDE_TFLAG_OUT_TF |
-                                         IDE_TFLAG_IN_TF,
-       IDE_TFLAG_DEVICE                = IDE_TFLAG_OUT_DEVICE |
-                                         IDE_TFLAG_IN_DEVICE,
-       /* force 16-bit I/O operations */
-       IDE_TFLAG_IO_16BIT              = (1 << 30),
-       /* ide_task_t was allocated using kmalloc() */
-       IDE_TFLAG_DYN                   = (1 << 31),
-};
-
-struct ide_taskfile {
-       u8      hob_data;       /*  0: high data byte (for TASKFILE IOCTL) */
-
-       u8      hob_feature;    /*  1-5: additional data to support LBA48 */
-       u8      hob_nsect;
-       u8      hob_lbal;
-       u8      hob_lbam;
-       u8      hob_lbah;
-
-       u8      data;           /*  6: low data byte (for TASKFILE IOCTL) */
-
-       union {                 /*  7: */
-               u8 error;       /*   read:  error */
-               u8 feature;     /*  write: feature */
-       };
-
-       u8      nsect;          /*  8: number of sectors */
-       u8      lbal;           /*  9: LBA low */
-       u8      lbam;           /* 10: LBA mid */
-       u8      lbah;           /* 11: LBA high */
-
-       u8      device;         /* 12: device select */
-
-       union {                 /* 13: */
-               u8 status;      /*  read: status  */
-               u8 command;     /* write: command */
-       };
-};
-
-typedef struct ide_task_s {
-       union {
-               struct ide_taskfile     tf;
-               u8                      tf_array[14];
-       };
-       u32                     tf_flags;
-       int                     data_phase;
-       struct request          *rq;            /* copy of request */
-       void                    *special;       /* valid_t generally */
-} ide_task_t;
-
 void ide_tf_dump(const char *, struct ide_taskfile *);
 
 void ide_exec_command(ide_hwif_t *, u8);
@@ -1163,24 +1208,22 @@ enum {
        REQ_IDETAPE_WRITE       = (1 << 3),
 };
 
-void ide_queue_pc_head(ide_drive_t *, struct gendisk *, struct ide_atapi_pc *,
-                      struct request *);
 int ide_queue_pc_tail(ide_drive_t *, struct gendisk *, struct ide_atapi_pc *);
 
 int ide_do_test_unit_ready(ide_drive_t *, struct gendisk *);
 int ide_do_start_stop(ide_drive_t *, struct gendisk *, int);
 int ide_set_media_lock(ide_drive_t *, struct gendisk *, int);
+void ide_create_request_sense_cmd(ide_drive_t *, struct ide_atapi_pc *);
+void ide_retry_pc(ide_drive_t *, struct gendisk *);
+
+static inline unsigned long ide_scsi_get_timeout(struct ide_atapi_pc *pc)
+{
+       return max_t(unsigned long, WAIT_CMD, pc->timeout - jiffies);
+}
+
+int ide_scsi_expiry(ide_drive_t *);
 
-ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc,
-       ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry,
-       void (*update_buffers)(ide_drive_t *, struct ide_atapi_pc *),
-       void (*retry_pc)(ide_drive_t *), void (*dsc_handle)(ide_drive_t *),
-       int (*io_buffers)(ide_drive_t *, struct ide_atapi_pc *, unsigned int,
-                          int));
-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 ide_issue_pc(ide_drive_t *, unsigned int, ide_expiry_t *);
 
 ide_startstop_t do_rw_taskfile(ide_drive_t *, ide_task_t *);
 
@@ -1547,6 +1590,6 @@ static inline ide_drive_t *ide_get_pair_dev(ide_drive_t *drive)
 {
        ide_drive_t *peer = &drive->hwif->drives[(drive->dn ^ 1) & 1];
 
-       return peer->present ? peer : NULL;
+       return (peer->dev_flags & IDE_DFLAG_PRESENT) ? peer : NULL;
 }
 #endif /* _IDE_H */