Commit 2ed1dad2 authored by Bartlomiej Zolnierkiewicz's avatar Bartlomiej Zolnierkiewicz Committed by Linus Torvalds

[PATCH] ide: merge CONFIG_IDE_TASKFILE_IO=y|n PIO handlers together

This fixes a couple of CONFIG_IDE_TASKFILE_IO=n issues:
 - check status after last sector for PIO-in transfers
 - handle drive->unmask properly in PIO-out prehandlers
 - use rq->[hard]_nr_sectors where appropriate
Signed-off-by: default avatarBartlomiej Zolnierkiewicz <bzolnier@elka.pw.edu.pl>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 5c926216
...@@ -303,176 +303,7 @@ static inline void task_buffer_multi_sectors(ide_drive_t *drive, ...@@ -303,176 +303,7 @@ static inline void task_buffer_multi_sectors(ide_drive_t *drive,
task_buffer_sectors(drive, rq, nsect, rw); task_buffer_sectors(drive, rq, nsect, rw);
} }
/* #ifdef CONFIG_IDE_TASKFILE_IO
* old taskfile PIO handlers, to be killed as soon as possible.
*/
#ifndef CONFIG_IDE_TASKFILE_IO
/*
* Handler for command with PIO data-in phase, READ
*/
ide_startstop_t task_in_intr (ide_drive_t *drive)
{
struct request *rq = HWGROUP(drive)->rq;
ide_hwif_t *hwif = HWIF(drive);
u8 stat;
if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG),DATA_READY,BAD_R_STAT)) {
if (stat & (ERR_STAT|DRQ_STAT)) {
return DRIVER(drive)->error(drive, "task_in_intr", stat);
}
ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL);
return ide_started;
}
task_buffer_sectors(drive, rq, 1, IDE_PIO_IN);
/* FIXME: check drive status */
if (!rq->current_nr_sectors)
if (!DRIVER(drive)->end_request(drive, 1, 0))
return ide_stopped;
ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL);
return ide_started;
}
EXPORT_SYMBOL(task_in_intr);
/*
* Handler for command with Read Multiple
*/
ide_startstop_t task_mulin_intr (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
struct request *rq = HWGROUP(drive)->rq;
u8 stat;
if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG),DATA_READY,BAD_R_STAT)) {
if (stat & (ERR_STAT|DRQ_STAT)) {
return DRIVER(drive)->error(drive, "task_mulin_intr", stat);
}
/* no data yet, so wait for another interrupt */
ide_set_handler(drive, &task_mulin_intr, WAIT_WORSTCASE, NULL);
return ide_started;
}
task_buffer_multi_sectors(drive, rq, IDE_PIO_IN);
/* FIXME: check drive status */
if (!rq->current_nr_sectors) {
DRIVER(drive)->end_request(drive, 1, 0);
return ide_stopped;
}
ide_set_handler(drive, &task_mulin_intr, WAIT_WORSTCASE, NULL);
return ide_started;
}
EXPORT_SYMBOL(task_mulin_intr);
ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
{
ide_startstop_t startstop;
if (ide_wait_stat(&startstop, drive, DATA_READY,
drive->bad_wstat, WAIT_DRQ)) {
printk(KERN_ERR "%s: no DRQ after issuing WRITE%s\n",
drive->name,
drive->addressing ? "_EXT" : "");
return startstop;
}
/* For Write_sectors we need to stuff the first sector */
ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL);
task_buffer_sectors(drive, rq, 1, IDE_PIO_OUT);
return ide_started;
}
EXPORT_SYMBOL(pre_task_out_intr);
/*
* Handler for command with PIO data-out phase WRITE
*
* WOOHOO this is a CORRECT STATE DIAGRAM NOW, <andre@linux-ide.org>
*/
ide_startstop_t task_out_intr (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
struct request *rq = HWGROUP(drive)->rq;
u8 stat;
if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG), DRIVE_READY, drive->bad_wstat)) {
return DRIVER(drive)->error(drive, "task_out_intr", stat);
}
if (((stat & DRQ_STAT) == 0) ^ !rq->current_nr_sectors)
return DRIVER(drive)->error(drive, __FUNCTION__, stat);
/*
* Safe to update request for partial completions.
* We have a good STATUS CHECK!!!
*/
if (!rq->current_nr_sectors)
if (!DRIVER(drive)->end_request(drive, 1, 0))
return ide_stopped;
task_buffer_sectors(drive, rq, 1, IDE_PIO_OUT);
ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL);
return ide_started;
}
EXPORT_SYMBOL(task_out_intr);
ide_startstop_t pre_task_mulout_intr (ide_drive_t *drive, struct request *rq)
{
ide_startstop_t startstop;
if (ide_wait_stat(&startstop, drive, DATA_READY,
drive->bad_wstat, WAIT_DRQ)) {
printk(KERN_ERR "%s: no DRQ after issuing %s\n",
drive->name,
drive->addressing ? "MULTWRITE_EXT" : "MULTWRITE");
return startstop;
}
ide_set_handler(drive, &task_mulout_intr, WAIT_WORSTCASE, NULL);
task_buffer_multi_sectors(drive, rq, IDE_PIO_OUT);
return ide_started;
}
EXPORT_SYMBOL(pre_task_mulout_intr);
/*
* Handler for command write multiple
*/
ide_startstop_t task_mulout_intr (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
u8 stat = hwif->INB(IDE_STATUS_REG);
struct request *rq = HWGROUP(drive)->rq;
if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
return DRIVER(drive)->error(drive, __FUNCTION__, stat);
if (((stat & DRQ_STAT) == 0) ^ !rq->current_nr_sectors)
return DRIVER(drive)->error(drive, __FUNCTION__, stat);
/* Handle last IRQ, occurs after all data was sent. */
if (!rq->current_nr_sectors) {
DRIVER(drive)->end_request(drive, 1, 0);
return ide_stopped;
}
task_buffer_multi_sectors(drive, rq, IDE_PIO_OUT);
ide_set_handler(drive, &task_mulout_intr, WAIT_WORSTCASE, NULL);
return ide_started;
}
EXPORT_SYMBOL(task_mulout_intr);
#else /* !CONFIG_IDE_TASKFILE_IO */
static void task_sectors(ide_drive_t *drive, struct request *rq, static void task_sectors(ide_drive_t *drive, struct request *rq,
unsigned nsect, unsigned rw) unsigned nsect, unsigned rw)
{ {
...@@ -511,6 +342,10 @@ static void task_multi_sectors(ide_drive_t *drive, ...@@ -511,6 +342,10 @@ static void task_multi_sectors(ide_drive_t *drive,
} else /* task request */ } else /* task request */
task_buffer_multi_sectors(drive, rq, rw); task_buffer_multi_sectors(drive, rq, rw);
} }
#else
# define task_sectors(d, rq, nsect, rw) task_buffer_sectors(d, rq, nsect, rw)
# define task_multi_sectors(d, rq, rw) task_buffer_multi_sectors(d, rq, rw)
#endif /* CONFIG_IDE_TASKFILE_IO */
static u8 wait_drive_not_busy(ide_drive_t *drive) static u8 wait_drive_not_busy(ide_drive_t *drive)
{ {
...@@ -532,6 +367,7 @@ static u8 wait_drive_not_busy(ide_drive_t *drive) ...@@ -532,6 +367,7 @@ static u8 wait_drive_not_busy(ide_drive_t *drive)
return stat; return stat;
} }
#ifdef CONFIG_IDE_TASKFILE_IO
static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq, static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
const char *s, u8 stat, unsigned cur_bad) const char *s, u8 stat, unsigned cur_bad)
{ {
...@@ -543,6 +379,9 @@ static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq, ...@@ -543,6 +379,9 @@ static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
} }
return drive->driver->error(drive, s, stat); return drive->driver->error(drive, s, stat);
} }
#else
# define task_error(d, rq, s, stat, cur_bad) drive->driver->error(d, s, stat)
#endif
/* /*
* Handler for command with PIO data-in phase (Read). * Handler for command with PIO data-in phase (Read).
...@@ -555,7 +394,7 @@ ide_startstop_t task_in_intr (ide_drive_t *drive) ...@@ -555,7 +394,7 @@ ide_startstop_t task_in_intr (ide_drive_t *drive)
if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
if (stat & (ERR_STAT | DRQ_STAT)) if (stat & (ERR_STAT | DRQ_STAT))
return task_error(drive, rq, __FUNCTION__, stat, 0); return task_error(drive, rq, __FUNCTION__, stat, 0);
/* BUSY_STAT: No data yet, so wait for another IRQ. */ /* No data yet, so wait for another IRQ. */
ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL); ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL);
return ide_started; return ide_started;
} }
...@@ -589,7 +428,7 @@ ide_startstop_t task_mulin_intr (ide_drive_t *drive) ...@@ -589,7 +428,7 @@ ide_startstop_t task_mulin_intr (ide_drive_t *drive)
if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
if (stat & (ERR_STAT | DRQ_STAT)) if (stat & (ERR_STAT | DRQ_STAT))
return task_error(drive, rq, __FUNCTION__, stat, 0); return task_error(drive, rq, __FUNCTION__, stat, 0);
/* BUSY_STAT: No data yet, so wait for another IRQ. */ /* No data yet, so wait for another IRQ. */
ide_set_handler(drive, &task_mulin_intr, WAIT_WORSTCASE, NULL); ide_set_handler(drive, &task_mulin_intr, WAIT_WORSTCASE, NULL);
return ide_started; return ide_started;
} }
...@@ -625,8 +464,7 @@ ide_startstop_t task_out_intr (ide_drive_t *drive) ...@@ -625,8 +464,7 @@ ide_startstop_t task_out_intr (ide_drive_t *drive)
return task_error(drive, rq, __FUNCTION__, stat, 1); return task_error(drive, rq, __FUNCTION__, stat, 1);
/* Deal with unexpected ATA data phase. */ /* Deal with unexpected ATA data phase. */
if ((!(stat & DATA_READY) && rq->nr_sectors) || if (((stat & DRQ_STAT) == 0) ^ !rq->nr_sectors)
((stat & DATA_READY) && !rq->nr_sectors))
return task_error(drive, rq, __FUNCTION__, stat, 1); return task_error(drive, rq, __FUNCTION__, stat, 1);
if (!rq->nr_sectors) { if (!rq->nr_sectors) {
...@@ -635,8 +473,8 @@ ide_startstop_t task_out_intr (ide_drive_t *drive) ...@@ -635,8 +473,8 @@ ide_startstop_t task_out_intr (ide_drive_t *drive)
} }
/* Still data left to transfer. */ /* Still data left to transfer. */
ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL);
task_sectors(drive, rq, 1, IDE_PIO_OUT); task_sectors(drive, rq, 1, IDE_PIO_OUT);
ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL);
return ide_started; return ide_started;
} }
...@@ -677,8 +515,7 @@ ide_startstop_t task_mulout_intr (ide_drive_t *drive) ...@@ -677,8 +515,7 @@ ide_startstop_t task_mulout_intr (ide_drive_t *drive)
return task_error(drive, rq, __FUNCTION__, stat, drive->mult_count); return task_error(drive, rq, __FUNCTION__, stat, drive->mult_count);
/* Deal with unexpected ATA data phase. */ /* Deal with unexpected ATA data phase. */
if ((!(stat & DATA_READY) && rq->nr_sectors) || if (((stat & DRQ_STAT) == 0) ^ !rq->nr_sectors)
((stat & DATA_READY) && !rq->nr_sectors))
return task_error(drive, rq, __FUNCTION__, stat, drive->mult_count); return task_error(drive, rq, __FUNCTION__, stat, drive->mult_count);
if (!rq->nr_sectors) { if (!rq->nr_sectors) {
...@@ -687,8 +524,8 @@ ide_startstop_t task_mulout_intr (ide_drive_t *drive) ...@@ -687,8 +524,8 @@ ide_startstop_t task_mulout_intr (ide_drive_t *drive)
} }
/* Still data left to transfer. */ /* Still data left to transfer. */
ide_set_handler(drive, &task_mulout_intr, WAIT_WORSTCASE, NULL);
task_multi_sectors(drive, rq, IDE_PIO_OUT); task_multi_sectors(drive, rq, IDE_PIO_OUT);
ide_set_handler(drive, &task_mulout_intr, WAIT_WORSTCASE, NULL);
return ide_started; return ide_started;
} }
...@@ -715,8 +552,6 @@ ide_startstop_t pre_task_mulout_intr (ide_drive_t *drive, struct request *rq) ...@@ -715,8 +552,6 @@ ide_startstop_t pre_task_mulout_intr (ide_drive_t *drive, struct request *rq)
} }
EXPORT_SYMBOL(pre_task_mulout_intr); EXPORT_SYMBOL(pre_task_mulout_intr);
#endif /* !CONFIG_IDE_TASKFILE_IO */
int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_size, u8 *buf) int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_size, u8 *buf)
{ {
struct request rq; struct request rq;
......
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