aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-atapi.c
diff options
context:
space:
mode:
authorFelix Blyakher <felixb@sgi.com>2009-03-30 23:08:33 -0400
committerFelix Blyakher <felixb@sgi.com>2009-03-30 23:08:33 -0400
commit930861c4e6f13ce2e7d06cd1ef11441a065517d9 (patch)
treedf6ff01f89768ff8d6fe6a64491be30e6e56c3e0 /drivers/ide/ide-atapi.c
parent8b112171734c791afaf43ccc8c6ec492e7006e44 (diff)
parent15f7176eb1cccec0a332541285ee752b935c1c85 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers/ide/ide-atapi.c')
-rw-r--r--drivers/ide/ide-atapi.c116
1 files changed, 86 insertions, 30 deletions
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index e9d042dba0e0..2fb5d28a9be5 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -149,7 +149,10 @@ static void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk,
149 memcpy(rq->cmd, pc->c, 12); 149 memcpy(rq->cmd, pc->c, 12);
150 if (drive->media == ide_tape) 150 if (drive->media == ide_tape)
151 rq->cmd[13] = REQ_IDETAPE_PC1; 151 rq->cmd[13] = REQ_IDETAPE_PC1;
152 ide_do_drive_cmd(drive, rq); 152
153 drive->hwif->rq = NULL;
154
155 elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0);
153} 156}
154 157
155/* 158/*
@@ -297,6 +300,21 @@ int ide_cd_get_xferlen(struct request *rq)
297} 300}
298EXPORT_SYMBOL_GPL(ide_cd_get_xferlen); 301EXPORT_SYMBOL_GPL(ide_cd_get_xferlen);
299 302
303void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason)
304{
305 struct ide_cmd cmd;
306
307 memset(&cmd, 0, sizeof(cmd));
308 cmd.tf_flags = IDE_TFLAG_IN_LBAH | IDE_TFLAG_IN_LBAM |
309 IDE_TFLAG_IN_NSECT;
310
311 drive->hwif->tp_ops->tf_read(drive, &cmd);
312
313 *bcount = (cmd.tf.lbah << 8) | cmd.tf.lbam;
314 *ireason = cmd.tf.nsect & 3;
315}
316EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason);
317
300/* 318/*
301 * This is the usual interrupt handler which will be called during a packet 319 * This is the usual interrupt handler which will be called during a packet
302 * command. We will transfer some of the data (as requested by the drive) 320 * command. We will transfer some of the data (as requested by the drive)
@@ -318,11 +336,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
318 timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD 336 timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
319 : WAIT_TAPE_CMD; 337 : WAIT_TAPE_CMD;
320 338
321 if (pc->flags & PC_FLAG_TIMEDOUT) {
322 drive->pc_callback(drive, 0);
323 return ide_stopped;
324 }
325
326 /* Clear the interrupt */ 339 /* Clear the interrupt */
327 stat = tp_ops->read_status(hwif); 340 stat = tp_ops->read_status(hwif);
328 341
@@ -344,6 +357,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
344 357
345 /* No more interrupts */ 358 /* No more interrupts */
346 if ((stat & ATA_DRQ) == 0) { 359 if ((stat & ATA_DRQ) == 0) {
360 int uptodate;
361
347 debug_log("Packet command completed, %d bytes transferred\n", 362 debug_log("Packet command completed, %d bytes transferred\n",
348 pc->xferred); 363 pc->xferred);
349 364
@@ -382,7 +397,22 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
382 dsc = 1; 397 dsc = 1;
383 398
384 /* Command finished - Call the callback function */ 399 /* Command finished - Call the callback function */
385 drive->pc_callback(drive, dsc); 400 uptodate = drive->pc_callback(drive, dsc);
401
402 if (uptodate == 0)
403 drive->failed_pc = NULL;
404
405 if (blk_special_request(rq)) {
406 rq->errors = 0;
407 ide_complete_rq(drive, 0, blk_rq_bytes(rq));
408 } else {
409 if (blk_fs_request(rq) == 0 && uptodate <= 0) {
410 if (rq->errors == 0)
411 rq->errors = -EIO;
412 }
413 ide_complete_rq(drive, uptodate ? 0 : -EIO,
414 ide_rq_bytes(rq));
415 }
386 416
387 return ide_stopped; 417 return ide_stopped;
388 } 418 }
@@ -440,7 +470,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
440 470
441 /* FIXME: don't do partial completions */ 471 /* FIXME: don't do partial completions */
442 if (drive->media == ide_floppy) 472 if (drive->media == ide_floppy)
443 ide_end_request(drive, 1, done >> 9); 473 ide_complete_rq(drive, 0,
474 done ? done : ide_rq_bytes(rq));
444 } else 475 } else
445 xferfunc(drive, NULL, pc->cur_pos, bcount); 476 xferfunc(drive, NULL, pc->cur_pos, bcount);
446 477
@@ -452,20 +483,32 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
452 rq->cmd[0], bcount); 483 rq->cmd[0], bcount);
453next_irq: 484next_irq:
454 /* And set the interrupt handler again */ 485 /* And set the interrupt handler again */
455 ide_set_handler(drive, ide_pc_intr, timeout, NULL); 486 ide_set_handler(drive, ide_pc_intr, timeout);
456 return ide_started; 487 return ide_started;
457} 488}
458 489
490static void ide_init_packet_cmd(struct ide_cmd *cmd, u32 tf_flags,
491 u16 bcount, u8 dma)
492{
493 cmd->protocol = dma ? ATAPI_PROT_DMA : ATAPI_PROT_PIO;
494 cmd->tf_flags |= IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM |
495 IDE_TFLAG_OUT_FEATURE | tf_flags;
496 cmd->tf.command = ATA_CMD_PACKET;
497 cmd->tf.feature = dma; /* Use PIO/DMA */
498 cmd->tf.lbam = bcount & 0xff;
499 cmd->tf.lbah = (bcount >> 8) & 0xff;
500}
501
459static u8 ide_read_ireason(ide_drive_t *drive) 502static u8 ide_read_ireason(ide_drive_t *drive)
460{ 503{
461 ide_task_t task; 504 struct ide_cmd cmd;
462 505
463 memset(&task, 0, sizeof(task)); 506 memset(&cmd, 0, sizeof(cmd));
464 task.tf_flags = IDE_TFLAG_IN_NSECT; 507 cmd.tf_flags = IDE_TFLAG_IN_NSECT;
465 508
466 drive->hwif->tp_ops->tf_read(drive, &task); 509 drive->hwif->tp_ops->tf_read(drive, &cmd);
467 510
468 return task.tf.nsect & 3; 511 return cmd.tf.nsect & 3;
469} 512}
470 513
471static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason) 514static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason)
@@ -560,11 +603,13 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
560 } 603 }
561 } 604 }
562 605
606 hwif->expiry = expiry;
607
563 /* Set the interrupt routine */ 608 /* Set the interrupt routine */
564 ide_set_handler(drive, 609 ide_set_handler(drive,
565 (dev_is_idecd(drive) ? drive->irq_handler 610 (dev_is_idecd(drive) ? drive->irq_handler
566 : ide_pc_intr), 611 : ide_pc_intr),
567 timeout, expiry); 612 timeout);
568 613
569 /* Begin DMA, if necessary */ 614 /* Begin DMA, if necessary */
570 if (dev_is_idecd(drive)) { 615 if (dev_is_idecd(drive)) {
@@ -584,23 +629,30 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
584 return ide_started; 629 return ide_started;
585} 630}
586 631
587ide_startstop_t ide_issue_pc(ide_drive_t *drive) 632ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd)
588{ 633{
589 struct ide_atapi_pc *pc; 634 struct ide_atapi_pc *pc;
590 ide_hwif_t *hwif = drive->hwif; 635 ide_hwif_t *hwif = drive->hwif;
636 const struct ide_dma_ops *dma_ops = hwif->dma_ops;
591 ide_expiry_t *expiry = NULL; 637 ide_expiry_t *expiry = NULL;
638 struct request *rq = hwif->rq;
592 unsigned int timeout; 639 unsigned int timeout;
593 u32 tf_flags; 640 u32 tf_flags;
594 u16 bcount; 641 u16 bcount;
642 u8 drq_int = !!(drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT);
595 643
596 if (dev_is_idecd(drive)) { 644 if (dev_is_idecd(drive)) {
597 tf_flags = IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL; 645 tf_flags = IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL;
598 bcount = ide_cd_get_xferlen(hwif->rq); 646 bcount = ide_cd_get_xferlen(rq);
599 expiry = ide_cd_expiry; 647 expiry = ide_cd_expiry;
600 timeout = ATAPI_WAIT_PC; 648 timeout = ATAPI_WAIT_PC;
601 649
602 if (drive->dma) 650 if (drive->dma) {
603 drive->dma = !hwif->dma_ops->dma_setup(drive); 651 if (ide_build_sglist(drive, cmd))
652 drive->dma = !dma_ops->dma_setup(drive, cmd);
653 else
654 drive->dma = 0;
655 }
604 } else { 656 } else {
605 pc = drive->pc; 657 pc = drive->pc;
606 658
@@ -619,8 +671,12 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive)
619 } 671 }
620 672
621 if ((pc->flags & PC_FLAG_DMA_OK) && 673 if ((pc->flags & PC_FLAG_DMA_OK) &&
622 (drive->dev_flags & IDE_DFLAG_USING_DMA)) 674 (drive->dev_flags & IDE_DFLAG_USING_DMA)) {
623 drive->dma = !hwif->dma_ops->dma_setup(drive); 675 if (ide_build_sglist(drive, cmd))
676 drive->dma = !dma_ops->dma_setup(drive, cmd);
677 else
678 drive->dma = 0;
679 }
624 680
625 if (!drive->dma) 681 if (!drive->dma)
626 pc->flags &= ~PC_FLAG_DMA_OK; 682 pc->flags &= ~PC_FLAG_DMA_OK;
@@ -629,18 +685,18 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive)
629 : WAIT_TAPE_CMD; 685 : WAIT_TAPE_CMD;
630 } 686 }
631 687
632 ide_pktcmd_tf_load(drive, tf_flags, bcount, drive->dma); 688 ide_init_packet_cmd(cmd, tf_flags, bcount, drive->dma);
633 689
634 /* Issue the packet command */ 690 (void)do_rw_taskfile(drive, cmd);
635 if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) { 691
692 if (drq_int) {
636 if (drive->dma) 693 if (drive->dma)
637 drive->waiting_for_dma = 0; 694 drive->waiting_for_dma = 0;
638 ide_execute_command(drive, ATA_CMD_PACKET, ide_transfer_pc, 695 hwif->expiry = expiry;
639 timeout, expiry);
640 return ide_started;
641 } else {
642 ide_execute_pkt_cmd(drive);
643 return ide_transfer_pc(drive);
644 } 696 }
697
698 ide_execute_command(drive, cmd, ide_transfer_pc, timeout);
699
700 return drq_int ? ide_started : ide_transfer_pc(drive);
645} 701}
646EXPORT_SYMBOL_GPL(ide_issue_pc); 702EXPORT_SYMBOL_GPL(ide_issue_pc);