diff options
author | Felix Blyakher <felixb@sgi.com> | 2009-03-30 23:08:33 -0400 |
---|---|---|
committer | Felix Blyakher <felixb@sgi.com> | 2009-03-30 23:08:33 -0400 |
commit | 930861c4e6f13ce2e7d06cd1ef11441a065517d9 (patch) | |
tree | df6ff01f89768ff8d6fe6a64491be30e6e56c3e0 /drivers/ide/ide-atapi.c | |
parent | 8b112171734c791afaf43ccc8c6ec492e7006e44 (diff) | |
parent | 15f7176eb1cccec0a332541285ee752b935c1c85 (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.c | 116 |
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 | } |
298 | EXPORT_SYMBOL_GPL(ide_cd_get_xferlen); | 301 | EXPORT_SYMBOL_GPL(ide_cd_get_xferlen); |
299 | 302 | ||
303 | void 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 | } | ||
316 | EXPORT_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); |
453 | next_irq: | 484 | next_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 | ||
490 | static 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 | |||
459 | static u8 ide_read_ireason(ide_drive_t *drive) | 502 | static 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 | ||
471 | static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason) | 514 | static 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 | ||
587 | ide_startstop_t ide_issue_pc(ide_drive_t *drive) | 632 | ide_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 | } |
646 | EXPORT_SYMBOL_GPL(ide_issue_pc); | 702 | EXPORT_SYMBOL_GPL(ide_issue_pc); |