Re: [PATCH] 2.5.67-ac1 IDE - fix Taskfile IOCTLs

Bartlomiej Zolnierkiewicz (B.Zolnierkiewicz@elka.pw.edu.pl)
Fri, 18 Apr 2003 01:20:43 +0200 (MET DST)


tf-ioctls-2.diff:

# Taskfile and flagged Taskfile PIO handlers unification [1/2].
# Incremental to tf-ioctls-1 patch.
#
# Detailed changelog:
# - add request validity checking present in flagged PIO handlers
# to execute_drive_cmd(), so we now check also not flagged Taskfile
# and we abort bad requests early
# - add flagged_wait_drive_ready() for wating for non-busy drive status
# - add check for DATA_READY to task_out_intr() and task_mulout_intr()
#
# Bartlomiej Zolnierkiewicz <bzolnier@elka.pw.edu.pl>

diff -uNr linux-2.5.67-ac1-tf1/drivers/ide/ide-io.c linux/drivers/ide/ide-io.c
--- linux-2.5.67-ac1-tf1/drivers/ide/ide-io.c Thu Apr 17 20:03:36 2003
+++ linux/drivers/ide/ide-io.c Thu Apr 17 21:49:49 2003
@@ -496,7 +496,23 @@

if (!args)
goto done;
-
+
+ /* Some validity checking. */
+ if (!rq->hard_nr_sectors &&
+ (args->command_type != IDE_DRIVE_TASK_NO_DATA &&
+ args->command_type != IDE_DRIVE_TASK_SET_XFER)) {
+ printk(KERN_ERR "%s: %s: no data to transfer\n",
+ drive->name, __FUNCTION__);
+ goto abort;
+ }
+ if (!drive->mult_count &&
+ (args->data_phase == TASKFILE_MULTI_IN ||
+ args->data_phase == TASKFILE_MULTI_OUT)) {
+ printk(KERN_ERR "%s: %s: multimode not set\n",
+ drive->name, __FUNCTION__);
+ goto abort;
+ }
+
if (args->tf_out_flags.all != 0)
return flagged_taskfile(drive, args);
return do_rw_taskfile(drive, args);
@@ -559,6 +575,7 @@
#ifdef DEBUG
printk("%s: DRIVE_CMD (null)\n", drive->name);
#endif
+abort:
ide_end_drive_cmd(drive,
hwif->INB(IDE_STATUS_REG),
hwif->INB(IDE_ERROR_REG));
diff -uNr linux-2.5.67-ac1-tf1/drivers/ide/ide-taskfile.c linux/drivers/ide/ide-taskfile.c
--- linux-2.5.67-ac1-tf1/drivers/ide/ide-taskfile.c Thu Apr 17 20:10:59 2003
+++ linux/drivers/ide/ide-taskfile.c Thu Apr 17 21:17:43 2003
@@ -355,6 +355,20 @@

EXPORT_SYMBOL(task_no_data_intr);

+static u8 flagged_wait_drive_ready(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = HWIF(drive);
+ int retries = 5;
+ u8 stat;
+ /*
+ * (ks) Last sector was transfered, wait until drive is ready.
+ * This can take up to 10 usec. We willl wait max 50 us.
+ */
+ while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--)
+ udelay(10);
+ return stat;
+}
+
#define PIO_IN 0
#define PIO_OUT 1

@@ -386,11 +400,12 @@
ide_startstop_t task_in_intr (ide_drive_t *drive)
{
struct request *rq = HWGROUP(drive)->rq;
+ ide_task_t *task = (ide_task_t *) rq->special;
u8 stat, good_stat;

good_stat = DATA_READY;
-check_status:
stat = HWIF(drive)->INB(IDE_STATUS_REG);
+check_status:
if (!OK_STAT(stat, good_stat, BAD_R_STAT)) {
if (stat & (ERR_STAT|DRQ_STAT))
return DRIVER(drive)->error(drive, __FUNCTION__, stat);
@@ -417,6 +432,11 @@

/* If it was the last datablock check status and finish transfer. */
if (!rq->nr_sectors) {
+ /* FIXME: Use for all requests? --bzolnier */
+ if (!blk_fs_request(rq) && task->tf_out_flags.all != 0)
+ stat = flagged_wait_drive_ready(drive);
+ else
+ stat = HWIF(drive)->INB(IDE_STATUS_REG);
good_stat = 0;
goto check_status;
}
@@ -435,13 +455,14 @@
ide_startstop_t task_mulin_intr (ide_drive_t *drive)
{
struct request *rq = HWGROUP(drive)->rq;
+ ide_task_t *task = (ide_task_t *) rq->special;
unsigned int msect = drive->mult_count;
unsigned int nsect;
u8 stat, good_stat;

good_stat = DATA_READY;
-check_status:
stat = HWIF(drive)->INB(IDE_STATUS_REG);
+check_status:
if (!OK_STAT(stat, good_stat, BAD_R_STAT)) {
if (stat & (ERR_STAT|DRQ_STAT))
return DRIVER(drive)->error(drive, __FUNCTION__, stat);
@@ -479,6 +500,11 @@

/* If it was the last datablock check status and finish transfer. */
if (!rq->nr_sectors) {
+ /* FIXME: Use for all requests? --bzolnier */
+ if (!blk_fs_request(rq) && task->tf_out_flags.all != 0)
+ stat = flagged_wait_drive_ready(drive);
+ else
+ stat = HWIF(drive)->INB(IDE_STATUS_REG);
good_stat = 0;
goto check_status;
}
@@ -513,6 +539,11 @@
}
}

+ /* Deal with unexpected ATA data phase. */
+ ok_stat = OK_STAT(stat, DATA_READY, drive->bad_wstat);
+ if (!ok_stat && rq->nr_sectors)
+ return DRIVER(drive)->error(drive, __FUNCTION__, stat);
+
/*
* Complete previously submitted bios (if any).
* Status was already verifyied.
@@ -577,6 +608,11 @@
}
}

+ /* Deal with unexpected ATA data phase. */
+ ok_stat = OK_STAT(stat, DATA_READY, drive->bad_wstat);
+ if (!ok_stat && rq->nr_sectors)
+ return DRIVER(drive)->error(drive, __FUNCTION__, stat);
+
/*
* Complete previously submitted bios (if any).
* Status was already verifyied.
@@ -1619,7 +1655,6 @@
u8 stat = hwif->INB(IDE_STATUS_REG);
struct request *rq = HWGROUP(drive)->rq;
char *pBuf = NULL;
- int retries = 5;

if (rq->current_nr_sectors == 0)
return DRIVER(drive)->error(drive, "flagged_task_in_intr (no data requested)", stat);
@@ -1650,12 +1685,7 @@
ide_set_handler(drive, &flagged_task_in_intr, WAIT_WORSTCASE, NULL);
return ide_started;
}
- /*
- * (ks) Last sector was transfered, wait until drive is ready.
- * This can take up to 10 usec. We willl wait max 50 us.
- */
- while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--)
- udelay(10);
+ stat = flagged_wait_drive_ready(drive);
ide_end_drive_cmd (drive, stat, hwif->INB(IDE_ERROR_REG));

return ide_stopped;
@@ -1667,7 +1697,6 @@
u8 stat = hwif->INB(IDE_STATUS_REG);
struct request *rq = HWGROUP(drive)->rq;
char *pBuf = NULL;
- int retries = 5;
unsigned int msect, nsect;

if (rq->current_nr_sectors == 0)
@@ -1707,13 +1736,7 @@
ide_set_handler(drive, &flagged_task_mulin_intr, WAIT_WORSTCASE, NULL);
return ide_started;
}
-
- /*
- * (ks) Last sector was transfered, wait until drive is ready.
- * This can take up to 10 usec. We willl wait max 50 us.
- */
- while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--)
- udelay(10);
+ stat = flagged_wait_drive_ready(drive);
ide_end_drive_cmd (drive, stat, hwif->INB(IDE_ERROR_REG));

return ide_stopped;

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/