From: Bartlomiej Zolnierkiewicz 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: Bartlomiej Zolnierkiewicz Signed-off-by: Andrew Morton --- 25-akpm/drivers/ide/ide-taskfile.c | 195 ++----------------------------------- 1 files changed, 15 insertions(+), 180 deletions(-) diff -puN drivers/ide/ide-taskfile.c~ide_non_tf_pio drivers/ide/ide-taskfile.c --- 25/drivers/ide/ide-taskfile.c~ide_non_tf_pio 2004-06-30 10:40:39.859786952 -0700 +++ 25-akpm/drivers/ide/ide-taskfile.c 2004-06-30 10:40:39.865786040 -0700 @@ -303,176 +303,7 @@ static inline void task_buffer_multi_sec task_buffer_sectors(drive, rq, nsect, rw); } -/* - * 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, - */ -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 */ - +#ifdef CONFIG_IDE_TASKFILE_IO static void task_sectors(ide_drive_t *drive, struct request *rq, unsigned nsect, unsigned rw) { @@ -511,6 +342,10 @@ static void task_multi_sectors(ide_drive } else /* task request */ 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) { @@ -532,6 +367,7 @@ static u8 wait_drive_not_busy(ide_drive_ return stat; } +#ifdef CONFIG_IDE_TASKFILE_IO static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq, const char *s, u8 stat, unsigned cur_bad) { @@ -543,6 +379,9 @@ static ide_startstop_t task_error(ide_dr } 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). @@ -555,7 +394,7 @@ ide_startstop_t task_in_intr (ide_drive_ if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { if (stat & (ERR_STAT | DRQ_STAT)) 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); return ide_started; } @@ -589,7 +428,7 @@ ide_startstop_t task_mulin_intr (ide_dri if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { if (stat & (ERR_STAT | DRQ_STAT)) 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); return ide_started; } @@ -625,8 +464,7 @@ ide_startstop_t task_out_intr (ide_drive return task_error(drive, rq, __FUNCTION__, stat, 1); /* Deal with unexpected ATA data phase. */ - if ((!(stat & DATA_READY) && rq->nr_sectors) || - ((stat & DATA_READY) && !rq->nr_sectors)) + if (((stat & DRQ_STAT) == 0) ^ !rq->nr_sectors) return task_error(drive, rq, __FUNCTION__, stat, 1); if (!rq->nr_sectors) { @@ -635,8 +473,8 @@ ide_startstop_t task_out_intr (ide_drive } /* Still data left to transfer. */ - ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL); task_sectors(drive, rq, 1, IDE_PIO_OUT); + ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL); return ide_started; } @@ -677,8 +515,7 @@ ide_startstop_t task_mulout_intr (ide_dr return task_error(drive, rq, __FUNCTION__, stat, drive->mult_count); /* Deal with unexpected ATA data phase. */ - if ((!(stat & DATA_READY) && rq->nr_sectors) || - ((stat & DATA_READY) && !rq->nr_sectors)) + if (((stat & DRQ_STAT) == 0) ^ !rq->nr_sectors) return task_error(drive, rq, __FUNCTION__, stat, drive->mult_count); if (!rq->nr_sectors) { @@ -687,8 +524,8 @@ ide_startstop_t task_mulout_intr (ide_dr } /* Still data left to transfer. */ - ide_set_handler(drive, &task_mulout_intr, WAIT_WORSTCASE, NULL); task_multi_sectors(drive, rq, IDE_PIO_OUT); + ide_set_handler(drive, &task_mulout_intr, WAIT_WORSTCASE, NULL); return ide_started; } @@ -715,8 +552,6 @@ ide_startstop_t pre_task_mulout_intr (id } 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) { struct request rq; _