ide: merge all TASKFILE_NO_DATA data phase handlers into taskfile_no_intr()

* Add 'struct task_s' to ide_hwif_t and init it to the current command
  in do_rw_taskfile().

* Merge all TASKFILE_NO_DATA data phase handlers into taskfile_no_intr().
Signed-off-by: default avatarBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
parent 0e3d84a5
...@@ -53,9 +53,6 @@ int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf) ...@@ -53,9 +53,6 @@ int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
} }
static ide_startstop_t task_no_data_intr(ide_drive_t *); static ide_startstop_t task_no_data_intr(ide_drive_t *);
static ide_startstop_t set_geometry_intr(ide_drive_t *);
static ide_startstop_t recal_intr(ide_drive_t *);
static ide_startstop_t set_multmode_intr(ide_drive_t *);
static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct request *); static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct request *);
static ide_startstop_t task_in_intr(ide_drive_t *); static ide_startstop_t task_in_intr(ide_drive_t *);
...@@ -79,6 +76,8 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) ...@@ -79,6 +76,8 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
if (task->tf_flags & IDE_TFLAG_FLAGGED) if (task->tf_flags & IDE_TFLAG_FLAGGED)
task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS; task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS;
memcpy(&hwif->task, task, sizeof(*task));
if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) { if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) {
ide_tf_dump(drive->name, tf); ide_tf_dump(drive->name, tf);
tp_ops->set_irq(hwif, 1); tp_ops->set_irq(hwif, 1);
...@@ -99,19 +98,6 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) ...@@ -99,19 +98,6 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
case TASKFILE_NO_DATA: case TASKFILE_NO_DATA:
if (handler == NULL) if (handler == NULL)
handler = task_no_data_intr; handler = task_no_data_intr;
if (task->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) {
switch (tf->command) {
case ATA_CMD_INIT_DEV_PARAMS:
handler = set_geometry_intr;
break;
case ATA_CMD_RESTORE:
handler = recal_intr;
break;
case ATA_CMD_SET_MULTI:
handler = set_multmode_intr;
break;
}
}
ide_execute_command(drive, tf->command, handler, ide_execute_command(drive, tf->command, handler,
WAIT_WORSTCASE, NULL); WAIT_WORSTCASE, NULL);
return ide_started; return ide_started;
...@@ -127,33 +113,15 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) ...@@ -127,33 +113,15 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
EXPORT_SYMBOL_GPL(do_rw_taskfile); EXPORT_SYMBOL_GPL(do_rw_taskfile);
/* /*
* set_multmode_intr() is invoked on completion of a ATA_CMD_SET_MULTI cmd. * Handler for commands without a data phase
*/
static ide_startstop_t set_multmode_intr(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
u8 stat;
local_irq_enable_in_hardirq();
stat = hwif->tp_ops->read_status(hwif);
if (OK_STAT(stat, ATA_DRDY, BAD_STAT))
drive->mult_count = drive->mult_req;
else {
drive->mult_req = drive->mult_count = 0;
drive->special.b.recalibrate = 1;
(void) ide_dump_status(drive, "set_multmode", stat);
}
return ide_stopped;
}
/*
* set_geometry_intr() is invoked on completion of a ATA_CMD_INIT_DEV_PARAMS cmd.
*/ */
static ide_startstop_t set_geometry_intr(ide_drive_t *drive) static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = drive->hwif;
int retries = 5; ide_task_t *task = &hwif->task;
struct ide_taskfile *tf = &task->tf;
int custom = (task->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) ? 1 : 0;
int retries = (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) ? 5 : 1;
u8 stat; u8 stat;
local_irq_enable_in_hardirq(); local_irq_enable_in_hardirq();
...@@ -165,50 +133,27 @@ static ide_startstop_t set_geometry_intr(ide_drive_t *drive) ...@@ -165,50 +133,27 @@ static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
udelay(10); udelay(10);
}; };
if (OK_STAT(stat, ATA_DRDY, BAD_STAT)) if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) {
if (custom && tf->command == ATA_CMD_SET_MULTI) {
drive->mult_req = drive->mult_count = 0;
drive->special.b.recalibrate = 1;
(void)ide_dump_status(drive, __func__, stat);
return ide_stopped; return ide_stopped;
} else if (custom && tf->command == ATA_CMD_INIT_DEV_PARAMS) {
if (stat & (ATA_ERR | ATA_DRQ)) if ((stat & (ATA_ERR | ATA_DRQ)) == 0) {
return ide_error(drive, "set_geometry_intr", stat); ide_set_handler(drive, &task_no_data_intr,
WAIT_WORSTCASE, NULL);
ide_set_handler(drive, &set_geometry_intr, WAIT_WORSTCASE, NULL);
return ide_started; return ide_started;
} }
}
/*
* recal_intr() is invoked on completion of a ATA_CMD_RESTORE (recalibrate) cmd.
*/
static ide_startstop_t recal_intr(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
u8 stat;
local_irq_enable_in_hardirq();
stat = hwif->tp_ops->read_status(hwif);
if (!OK_STAT(stat, ATA_DRDY, BAD_STAT))
return ide_error(drive, "recal_intr", stat);
return ide_stopped;
}
/*
* Handler for commands without a data phase
*/
static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
ide_task_t *args = hwif->hwgroup->rq->special;
u8 stat;
local_irq_enable_in_hardirq();
stat = hwif->tp_ops->read_status(hwif);
if (!OK_STAT(stat, ATA_DRDY, BAD_STAT))
return ide_error(drive, "task_no_data_intr", stat); return ide_error(drive, "task_no_data_intr", stat);
/* calls ide_end_drive_cmd */ /* calls ide_end_drive_cmd */
}
if (args) if (!custom)
ide_end_drive_cmd(drive, stat, ide_read_error(drive)); ide_end_drive_cmd(drive, stat, ide_read_error(drive));
else if (tf->command == ATA_CMD_SET_MULTI)
drive->mult_count = drive->mult_req;
return ide_stopped; return ide_stopped;
} }
......
...@@ -282,6 +282,110 @@ typedef enum { ...@@ -282,6 +282,110 @@ typedef enum {
ide_started, /* a drive operation was started, handler was set */ ide_started, /* a drive operation was started, handler was set */
} ide_startstop_t; } 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 */ /* ATAPI packet command flags */
enum { enum {
/* set when an error is considered normal - no retry (ide-tape) */ /* set when an error is considered normal - no retry (ide-tape) */
...@@ -567,7 +671,6 @@ typedef struct ide_drive_s ide_drive_t; ...@@ -567,7 +671,6 @@ typedef struct ide_drive_s ide_drive_t;
#define ide_drv_g(disk, cont_type) \ #define ide_drv_g(disk, cont_type) \
container_of((disk)->private_data, struct cont_type, driver) container_of((disk)->private_data, struct cont_type, driver)
struct ide_task_s;
struct ide_port_info; struct ide_port_info;
struct ide_tp_ops { struct ide_tp_ops {
...@@ -694,6 +797,8 @@ typedef struct hwif_s { ...@@ -694,6 +797,8 @@ typedef struct hwif_s {
/* data phase of the active command (currently only valid for PIO/DMA) */ /* data phase of the active command (currently only valid for PIO/DMA) */
int data_phase; int data_phase;
struct ide_task_s task; /* current command */
unsigned int nsect; unsigned int nsect;
unsigned int nleft; unsigned int nleft;
struct scatterlist *cursg; struct scatterlist *cursg;
...@@ -1059,110 +1164,6 @@ extern void ide_do_drive_cmd(ide_drive_t *, struct request *); ...@@ -1059,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); 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_tf_dump(const char *, struct ide_taskfile *);
void ide_exec_command(ide_hwif_t *, u8); void ide_exec_command(ide_hwif_t *, u8);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment