aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-taskfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/ide-taskfile.c')
-rw-r--r--drivers/ide/ide-taskfile.c72
1 files changed, 31 insertions, 41 deletions
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 0c9d71485728..99d6ed434978 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -55,7 +55,7 @@ int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
55 55
56static ide_startstop_t task_no_data_intr(ide_drive_t *); 56static ide_startstop_t task_no_data_intr(ide_drive_t *);
57static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct ide_cmd *); 57static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct ide_cmd *);
58static ide_startstop_t task_in_intr(ide_drive_t *); 58static ide_startstop_t task_pio_intr(ide_drive_t *);
59 59
60ide_startstop_t do_rw_taskfile(ide_drive_t *drive, struct ide_cmd *orig_cmd) 60ide_startstop_t do_rw_taskfile(ide_drive_t *drive, struct ide_cmd *orig_cmd)
61{ 61{
@@ -92,7 +92,7 @@ ide_startstop_t do_rw_taskfile(ide_drive_t *drive, struct ide_cmd *orig_cmd)
92 ndelay(400); /* FIXME */ 92 ndelay(400); /* FIXME */
93 return pre_task_out_intr(drive, cmd); 93 return pre_task_out_intr(drive, cmd);
94 } 94 }
95 handler = task_in_intr; 95 handler = task_pio_intr;
96 /* fall-through */ 96 /* fall-through */
97 case ATA_PROT_NODATA: 97 case ATA_PROT_NODATA:
98 if (handler == NULL) 98 if (handler == NULL)
@@ -329,68 +329,57 @@ static ide_startstop_t task_in_unexpected(ide_drive_t *drive,
329 } 329 }
330 330
331 /* Assume it was a spurious irq */ 331 /* Assume it was a spurious irq */
332 ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL); 332 ide_set_handler(drive, &task_pio_intr, WAIT_WORSTCASE, NULL);
333
333 return ide_started; 334 return ide_started;
334} 335}
335 336
336/* 337/*
337 * Handler for command with PIO data-in phase (Read/Read Multiple). 338 * Handler for command with PIO data phase.
338 */ 339 */
339static ide_startstop_t task_in_intr(ide_drive_t *drive) 340static ide_startstop_t task_pio_intr(ide_drive_t *drive)
340{ 341{
341 ide_hwif_t *hwif = drive->hwif; 342 ide_hwif_t *hwif = drive->hwif;
342 struct ide_cmd *cmd = &drive->hwif->cmd; 343 struct ide_cmd *cmd = &drive->hwif->cmd;
343 u8 stat = hwif->tp_ops->read_status(hwif); 344 u8 stat = hwif->tp_ops->read_status(hwif);
345 u8 write = !!(cmd->tf_flags & IDE_TFLAG_WRITE);
344 346
345 /* Error? */ 347 if (write == 0) {
346 if (stat & ATA_ERR) 348 /* Error? */
347 return task_error(drive, cmd, __func__, stat); 349 if (stat & ATA_ERR)
348 350 return task_error(drive, cmd, __func__, stat);
349 /* Didn't want any data? Odd. */
350 if ((stat & ATA_DRQ) == 0)
351 return task_in_unexpected(drive, cmd, stat);
352 351
353 ide_pio_datablock(drive, cmd, 0); 352 /* Didn't want any data? Odd. */
353 if ((stat & ATA_DRQ) == 0)
354 return task_in_unexpected(drive, cmd, stat);
355 } else {
356 if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
357 return task_error(drive, cmd, __func__, stat);
354 358
355 /* Are we done? Check status and finish transfer. */ 359 /* Deal with unexpected ATA data phase. */
356 if (cmd->nleft == 0) { 360 if (((stat & ATA_DRQ) == 0) ^ (cmd->nleft == 0))
357 stat = wait_drive_not_busy(drive);
358 if (!OK_STAT(stat, 0, BAD_STAT))
359 return task_error(drive, cmd, __func__, stat); 361 return task_error(drive, cmd, __func__, stat);
362 }
363
364 if (write && cmd->nleft == 0) {
360 ide_finish_cmd(drive, cmd, stat); 365 ide_finish_cmd(drive, cmd, stat);
361 return ide_stopped; 366 return ide_stopped;
362 } 367 }
363 368
364 /* Still data left to transfer. */ 369 /* Still data left to transfer. */
365 ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL); 370 ide_pio_datablock(drive, cmd, write);
366
367 return ide_started;
368}
369
370/*
371 * Handler for command with PIO data-out phase (Write/Write Multiple).
372 */
373static ide_startstop_t task_out_intr (ide_drive_t *drive)
374{
375 ide_hwif_t *hwif = drive->hwif;
376 struct ide_cmd *cmd = &drive->hwif->cmd;
377 u8 stat = hwif->tp_ops->read_status(hwif);
378
379 if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
380 return task_error(drive, cmd, __func__, stat);
381 371
382 /* Deal with unexpected ATA data phase. */ 372 /* Are we done? Check status and finish transfer. */
383 if (((stat & ATA_DRQ) == 0) ^ (cmd->nleft == 0)) 373 if (write == 0 && cmd->nleft == 0) {
384 return task_error(drive, cmd, __func__, stat); 374 stat = wait_drive_not_busy(drive);
385 375 if (!OK_STAT(stat, 0, BAD_STAT))
386 if (cmd->nleft == 0) { 376 return task_error(drive, cmd, __func__, stat);
387 ide_finish_cmd(drive, cmd, stat); 377 ide_finish_cmd(drive, cmd, stat);
388 return ide_stopped; 378 return ide_stopped;
389 } 379 }
390 380
391 /* Still data left to transfer. */ 381 /* Still data left to transfer. */
392 ide_pio_datablock(drive, cmd, 1); 382 ide_set_handler(drive, &task_pio_intr, WAIT_WORSTCASE, NULL);
393 ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL);
394 383
395 return ide_started; 384 return ide_started;
396} 385}
@@ -412,7 +401,8 @@ static ide_startstop_t pre_task_out_intr(ide_drive_t *drive,
412 if ((drive->dev_flags & IDE_DFLAG_UNMASK) == 0) 401 if ((drive->dev_flags & IDE_DFLAG_UNMASK) == 0)
413 local_irq_disable(); 402 local_irq_disable();
414 403
415 ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL); 404 ide_set_handler(drive, &task_pio_intr, WAIT_WORSTCASE, NULL);
405
416 ide_pio_datablock(drive, cmd, 1); 406 ide_pio_datablock(drive, cmd, 1);
417 407
418 return ide_started; 408 return ide_started;