diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-08-23 00:59:54 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-08-23 00:59:54 -0400 |
commit | 443d089703ffa585aea1af47c68f1be5d0ec3115 (patch) | |
tree | 14e88928b28697db68d2a87857be451e6f7a4ab9 /drivers/scsi | |
parent | 972dcafb6d743a6c7611a2e4681ed814e30d6230 (diff) | |
parent | 563a6e1fb0af58433beec1ab418e1fafbd100b56 (diff) |
/spare/repo/libata-dev branch 'upstream-fixes'
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/libata-core.c | 139 |
1 files changed, 133 insertions, 6 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 6e56af23957b..3544f5d020c6 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -2519,6 +2519,20 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) | |||
2519 | #endif /* __BIG_ENDIAN */ | 2519 | #endif /* __BIG_ENDIAN */ |
2520 | } | 2520 | } |
2521 | 2521 | ||
2522 | /** | ||
2523 | * ata_mmio_data_xfer - Transfer data by MMIO | ||
2524 | * @ap: port to read/write | ||
2525 | * @buf: data buffer | ||
2526 | * @buflen: buffer length | ||
2527 | * @do_write: read/write | ||
2528 | * | ||
2529 | * Transfer data from/to the device data register by MMIO. | ||
2530 | * | ||
2531 | * LOCKING: | ||
2532 | * Inherited from caller. | ||
2533 | * | ||
2534 | */ | ||
2535 | |||
2522 | static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf, | 2536 | static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf, |
2523 | unsigned int buflen, int write_data) | 2537 | unsigned int buflen, int write_data) |
2524 | { | 2538 | { |
@@ -2527,6 +2541,7 @@ static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf, | |||
2527 | u16 *buf16 = (u16 *) buf; | 2541 | u16 *buf16 = (u16 *) buf; |
2528 | void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr; | 2542 | void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr; |
2529 | 2543 | ||
2544 | /* Transfer multiple of 2 bytes */ | ||
2530 | if (write_data) { | 2545 | if (write_data) { |
2531 | for (i = 0; i < words; i++) | 2546 | for (i = 0; i < words; i++) |
2532 | writew(le16_to_cpu(buf16[i]), mmio); | 2547 | writew(le16_to_cpu(buf16[i]), mmio); |
@@ -2534,19 +2549,76 @@ static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf, | |||
2534 | for (i = 0; i < words; i++) | 2549 | for (i = 0; i < words; i++) |
2535 | buf16[i] = cpu_to_le16(readw(mmio)); | 2550 | buf16[i] = cpu_to_le16(readw(mmio)); |
2536 | } | 2551 | } |
2552 | |||
2553 | /* Transfer trailing 1 byte, if any. */ | ||
2554 | if (unlikely(buflen & 0x01)) { | ||
2555 | u16 align_buf[1] = { 0 }; | ||
2556 | unsigned char *trailing_buf = buf + buflen - 1; | ||
2557 | |||
2558 | if (write_data) { | ||
2559 | memcpy(align_buf, trailing_buf, 1); | ||
2560 | writew(le16_to_cpu(align_buf[0]), mmio); | ||
2561 | } else { | ||
2562 | align_buf[0] = cpu_to_le16(readw(mmio)); | ||
2563 | memcpy(trailing_buf, align_buf, 1); | ||
2564 | } | ||
2565 | } | ||
2537 | } | 2566 | } |
2538 | 2567 | ||
2568 | /** | ||
2569 | * ata_pio_data_xfer - Transfer data by PIO | ||
2570 | * @ap: port to read/write | ||
2571 | * @buf: data buffer | ||
2572 | * @buflen: buffer length | ||
2573 | * @do_write: read/write | ||
2574 | * | ||
2575 | * Transfer data from/to the device data register by PIO. | ||
2576 | * | ||
2577 | * LOCKING: | ||
2578 | * Inherited from caller. | ||
2579 | * | ||
2580 | */ | ||
2581 | |||
2539 | static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf, | 2582 | static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf, |
2540 | unsigned int buflen, int write_data) | 2583 | unsigned int buflen, int write_data) |
2541 | { | 2584 | { |
2542 | unsigned int dwords = buflen >> 1; | 2585 | unsigned int words = buflen >> 1; |
2543 | 2586 | ||
2587 | /* Transfer multiple of 2 bytes */ | ||
2544 | if (write_data) | 2588 | if (write_data) |
2545 | outsw(ap->ioaddr.data_addr, buf, dwords); | 2589 | outsw(ap->ioaddr.data_addr, buf, words); |
2546 | else | 2590 | else |
2547 | insw(ap->ioaddr.data_addr, buf, dwords); | 2591 | insw(ap->ioaddr.data_addr, buf, words); |
2592 | |||
2593 | /* Transfer trailing 1 byte, if any. */ | ||
2594 | if (unlikely(buflen & 0x01)) { | ||
2595 | u16 align_buf[1] = { 0 }; | ||
2596 | unsigned char *trailing_buf = buf + buflen - 1; | ||
2597 | |||
2598 | if (write_data) { | ||
2599 | memcpy(align_buf, trailing_buf, 1); | ||
2600 | outw(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr); | ||
2601 | } else { | ||
2602 | align_buf[0] = cpu_to_le16(inw(ap->ioaddr.data_addr)); | ||
2603 | memcpy(trailing_buf, align_buf, 1); | ||
2604 | } | ||
2605 | } | ||
2548 | } | 2606 | } |
2549 | 2607 | ||
2608 | /** | ||
2609 | * ata_data_xfer - Transfer data from/to the data register. | ||
2610 | * @ap: port to read/write | ||
2611 | * @buf: data buffer | ||
2612 | * @buflen: buffer length | ||
2613 | * @do_write: read/write | ||
2614 | * | ||
2615 | * Transfer data from/to the device data register. | ||
2616 | * | ||
2617 | * LOCKING: | ||
2618 | * Inherited from caller. | ||
2619 | * | ||
2620 | */ | ||
2621 | |||
2550 | static void ata_data_xfer(struct ata_port *ap, unsigned char *buf, | 2622 | static void ata_data_xfer(struct ata_port *ap, unsigned char *buf, |
2551 | unsigned int buflen, int do_write) | 2623 | unsigned int buflen, int do_write) |
2552 | { | 2624 | { |
@@ -2556,6 +2628,16 @@ static void ata_data_xfer(struct ata_port *ap, unsigned char *buf, | |||
2556 | ata_pio_data_xfer(ap, buf, buflen, do_write); | 2628 | ata_pio_data_xfer(ap, buf, buflen, do_write); |
2557 | } | 2629 | } |
2558 | 2630 | ||
2631 | /** | ||
2632 | * ata_pio_sector - Transfer ATA_SECT_SIZE (512 bytes) of data. | ||
2633 | * @qc: Command on going | ||
2634 | * | ||
2635 | * Transfer ATA_SECT_SIZE of data from/to the ATA device. | ||
2636 | * | ||
2637 | * LOCKING: | ||
2638 | * Inherited from caller. | ||
2639 | */ | ||
2640 | |||
2559 | static void ata_pio_sector(struct ata_queued_cmd *qc) | 2641 | static void ata_pio_sector(struct ata_queued_cmd *qc) |
2560 | { | 2642 | { |
2561 | int do_write = (qc->tf.flags & ATA_TFLAG_WRITE); | 2643 | int do_write = (qc->tf.flags & ATA_TFLAG_WRITE); |
@@ -2594,6 +2676,18 @@ static void ata_pio_sector(struct ata_queued_cmd *qc) | |||
2594 | kunmap(page); | 2676 | kunmap(page); |
2595 | } | 2677 | } |
2596 | 2678 | ||
2679 | /** | ||
2680 | * __atapi_pio_bytes - Transfer data from/to the ATAPI device. | ||
2681 | * @qc: Command on going | ||
2682 | * @bytes: number of bytes | ||
2683 | * | ||
2684 | * Transfer Transfer data from/to the ATAPI device. | ||
2685 | * | ||
2686 | * LOCKING: | ||
2687 | * Inherited from caller. | ||
2688 | * | ||
2689 | */ | ||
2690 | |||
2597 | static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes) | 2691 | static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes) |
2598 | { | 2692 | { |
2599 | int do_write = (qc->tf.flags & ATA_TFLAG_WRITE); | 2693 | int do_write = (qc->tf.flags & ATA_TFLAG_WRITE); |
@@ -2603,10 +2697,33 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes) | |||
2603 | unsigned char *buf; | 2697 | unsigned char *buf; |
2604 | unsigned int offset, count; | 2698 | unsigned int offset, count; |
2605 | 2699 | ||
2606 | if (qc->curbytes == qc->nbytes - bytes) | 2700 | if (qc->curbytes + bytes >= qc->nbytes) |
2607 | ap->pio_task_state = PIO_ST_LAST; | 2701 | ap->pio_task_state = PIO_ST_LAST; |
2608 | 2702 | ||
2609 | next_sg: | 2703 | next_sg: |
2704 | if (unlikely(qc->cursg >= qc->n_elem)) { | ||
2705 | /* | ||
2706 | * The end of qc->sg is reached and the device expects | ||
2707 | * more data to transfer. In order not to overrun qc->sg | ||
2708 | * and fulfill length specified in the byte count register, | ||
2709 | * - for read case, discard trailing data from the device | ||
2710 | * - for write case, padding zero data to the device | ||
2711 | */ | ||
2712 | u16 pad_buf[1] = { 0 }; | ||
2713 | unsigned int words = bytes >> 1; | ||
2714 | unsigned int i; | ||
2715 | |||
2716 | if (words) /* warning if bytes > 1 */ | ||
2717 | printk(KERN_WARNING "ata%u: %u bytes trailing data\n", | ||
2718 | ap->id, bytes); | ||
2719 | |||
2720 | for (i = 0; i < words; i++) | ||
2721 | ata_data_xfer(ap, (unsigned char*)pad_buf, 2, do_write); | ||
2722 | |||
2723 | ap->pio_task_state = PIO_ST_LAST; | ||
2724 | return; | ||
2725 | } | ||
2726 | |||
2610 | sg = &qc->sg[qc->cursg]; | 2727 | sg = &qc->sg[qc->cursg]; |
2611 | 2728 | ||
2612 | page = sg->page; | 2729 | page = sg->page; |
@@ -2640,11 +2757,21 @@ next_sg: | |||
2640 | 2757 | ||
2641 | kunmap(page); | 2758 | kunmap(page); |
2642 | 2759 | ||
2643 | if (bytes) { | 2760 | if (bytes) |
2644 | goto next_sg; | 2761 | goto next_sg; |
2645 | } | ||
2646 | } | 2762 | } |
2647 | 2763 | ||
2764 | /** | ||
2765 | * atapi_pio_bytes - Transfer data from/to the ATAPI device. | ||
2766 | * @qc: Command on going | ||
2767 | * | ||
2768 | * Transfer Transfer data from/to the ATAPI device. | ||
2769 | * | ||
2770 | * LOCKING: | ||
2771 | * Inherited from caller. | ||
2772 | * | ||
2773 | */ | ||
2774 | |||
2648 | static void atapi_pio_bytes(struct ata_queued_cmd *qc) | 2775 | static void atapi_pio_bytes(struct ata_queued_cmd *qc) |
2649 | { | 2776 | { |
2650 | struct ata_port *ap = qc->ap; | 2777 | struct ata_port *ap = qc->ap; |