diff options
Diffstat (limited to 'drivers/scsi/libata-bmdma.c')
-rw-r--r-- | drivers/scsi/libata-bmdma.c | 238 |
1 files changed, 236 insertions, 2 deletions
diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c index 96b4d2160df8..95d81d86d8b7 100644 --- a/drivers/scsi/libata-bmdma.c +++ b/drivers/scsi/libata-bmdma.c | |||
@@ -418,6 +418,240 @@ u8 ata_altstatus(struct ata_port *ap) | |||
418 | return inb(ap->ioaddr.altstatus_addr); | 418 | return inb(ap->ioaddr.altstatus_addr); |
419 | } | 419 | } |
420 | 420 | ||
421 | /** | ||
422 | * ata_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction | ||
423 | * @qc: Info associated with this ATA transaction. | ||
424 | * | ||
425 | * LOCKING: | ||
426 | * spin_lock_irqsave(host_set lock) | ||
427 | */ | ||
428 | |||
429 | static void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc) | ||
430 | { | ||
431 | struct ata_port *ap = qc->ap; | ||
432 | unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); | ||
433 | u8 dmactl; | ||
434 | void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; | ||
435 | |||
436 | /* load PRD table addr. */ | ||
437 | mb(); /* make sure PRD table writes are visible to controller */ | ||
438 | writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS); | ||
439 | |||
440 | /* specify data direction, triple-check start bit is clear */ | ||
441 | dmactl = readb(mmio + ATA_DMA_CMD); | ||
442 | dmactl &= ~(ATA_DMA_WR | ATA_DMA_START); | ||
443 | if (!rw) | ||
444 | dmactl |= ATA_DMA_WR; | ||
445 | writeb(dmactl, mmio + ATA_DMA_CMD); | ||
446 | |||
447 | /* issue r/w command */ | ||
448 | ap->ops->exec_command(ap, &qc->tf); | ||
449 | } | ||
450 | |||
451 | /** | ||
452 | * ata_bmdma_start_mmio - Start a PCI IDE BMDMA transaction | ||
453 | * @qc: Info associated with this ATA transaction. | ||
454 | * | ||
455 | * LOCKING: | ||
456 | * spin_lock_irqsave(host_set lock) | ||
457 | */ | ||
458 | |||
459 | static void ata_bmdma_start_mmio (struct ata_queued_cmd *qc) | ||
460 | { | ||
461 | struct ata_port *ap = qc->ap; | ||
462 | void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; | ||
463 | u8 dmactl; | ||
464 | |||
465 | /* start host DMA transaction */ | ||
466 | dmactl = readb(mmio + ATA_DMA_CMD); | ||
467 | writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD); | ||
468 | |||
469 | /* Strictly, one may wish to issue a readb() here, to | ||
470 | * flush the mmio write. However, control also passes | ||
471 | * to the hardware at this point, and it will interrupt | ||
472 | * us when we are to resume control. So, in effect, | ||
473 | * we don't care when the mmio write flushes. | ||
474 | * Further, a read of the DMA status register _immediately_ | ||
475 | * following the write may not be what certain flaky hardware | ||
476 | * is expected, so I think it is best to not add a readb() | ||
477 | * without first all the MMIO ATA cards/mobos. | ||
478 | * Or maybe I'm just being paranoid. | ||
479 | */ | ||
480 | } | ||
481 | |||
482 | /** | ||
483 | * ata_bmdma_setup_pio - Set up PCI IDE BMDMA transaction (PIO) | ||
484 | * @qc: Info associated with this ATA transaction. | ||
485 | * | ||
486 | * LOCKING: | ||
487 | * spin_lock_irqsave(host_set lock) | ||
488 | */ | ||
489 | |||
490 | static void ata_bmdma_setup_pio (struct ata_queued_cmd *qc) | ||
491 | { | ||
492 | struct ata_port *ap = qc->ap; | ||
493 | unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); | ||
494 | u8 dmactl; | ||
495 | |||
496 | /* load PRD table addr. */ | ||
497 | outl(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS); | ||
498 | |||
499 | /* specify data direction, triple-check start bit is clear */ | ||
500 | dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); | ||
501 | dmactl &= ~(ATA_DMA_WR | ATA_DMA_START); | ||
502 | if (!rw) | ||
503 | dmactl |= ATA_DMA_WR; | ||
504 | outb(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD); | ||
505 | |||
506 | /* issue r/w command */ | ||
507 | ap->ops->exec_command(ap, &qc->tf); | ||
508 | } | ||
509 | |||
510 | /** | ||
511 | * ata_bmdma_start_pio - Start a PCI IDE BMDMA transaction (PIO) | ||
512 | * @qc: Info associated with this ATA transaction. | ||
513 | * | ||
514 | * LOCKING: | ||
515 | * spin_lock_irqsave(host_set lock) | ||
516 | */ | ||
517 | |||
518 | static void ata_bmdma_start_pio (struct ata_queued_cmd *qc) | ||
519 | { | ||
520 | struct ata_port *ap = qc->ap; | ||
521 | u8 dmactl; | ||
522 | |||
523 | /* start host DMA transaction */ | ||
524 | dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); | ||
525 | outb(dmactl | ATA_DMA_START, | ||
526 | ap->ioaddr.bmdma_addr + ATA_DMA_CMD); | ||
527 | } | ||
528 | |||
529 | |||
530 | /** | ||
531 | * ata_bmdma_start - Start a PCI IDE BMDMA transaction | ||
532 | * @qc: Info associated with this ATA transaction. | ||
533 | * | ||
534 | * Writes the ATA_DMA_START flag to the DMA command register. | ||
535 | * | ||
536 | * May be used as the bmdma_start() entry in ata_port_operations. | ||
537 | * | ||
538 | * LOCKING: | ||
539 | * spin_lock_irqsave(host_set lock) | ||
540 | */ | ||
541 | void ata_bmdma_start(struct ata_queued_cmd *qc) | ||
542 | { | ||
543 | if (qc->ap->flags & ATA_FLAG_MMIO) | ||
544 | ata_bmdma_start_mmio(qc); | ||
545 | else | ||
546 | ata_bmdma_start_pio(qc); | ||
547 | } | ||
548 | |||
549 | |||
550 | /** | ||
551 | * ata_bmdma_setup - Set up PCI IDE BMDMA transaction | ||
552 | * @qc: Info associated with this ATA transaction. | ||
553 | * | ||
554 | * Writes address of PRD table to device's PRD Table Address | ||
555 | * register, sets the DMA control register, and calls | ||
556 | * ops->exec_command() to start the transfer. | ||
557 | * | ||
558 | * May be used as the bmdma_setup() entry in ata_port_operations. | ||
559 | * | ||
560 | * LOCKING: | ||
561 | * spin_lock_irqsave(host_set lock) | ||
562 | */ | ||
563 | void ata_bmdma_setup(struct ata_queued_cmd *qc) | ||
564 | { | ||
565 | if (qc->ap->flags & ATA_FLAG_MMIO) | ||
566 | ata_bmdma_setup_mmio(qc); | ||
567 | else | ||
568 | ata_bmdma_setup_pio(qc); | ||
569 | } | ||
570 | |||
571 | |||
572 | /** | ||
573 | * ata_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt. | ||
574 | * @ap: Port associated with this ATA transaction. | ||
575 | * | ||
576 | * Clear interrupt and error flags in DMA status register. | ||
577 | * | ||
578 | * May be used as the irq_clear() entry in ata_port_operations. | ||
579 | * | ||
580 | * LOCKING: | ||
581 | * spin_lock_irqsave(host_set lock) | ||
582 | */ | ||
583 | |||
584 | void ata_bmdma_irq_clear(struct ata_port *ap) | ||
585 | { | ||
586 | if (!ap->ioaddr.bmdma_addr) | ||
587 | return; | ||
588 | |||
589 | if (ap->flags & ATA_FLAG_MMIO) { | ||
590 | void __iomem *mmio = | ||
591 | ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS; | ||
592 | writeb(readb(mmio), mmio); | ||
593 | } else { | ||
594 | unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; | ||
595 | outb(inb(addr), addr); | ||
596 | } | ||
597 | } | ||
598 | |||
599 | |||
600 | /** | ||
601 | * ata_bmdma_status - Read PCI IDE BMDMA status | ||
602 | * @ap: Port associated with this ATA transaction. | ||
603 | * | ||
604 | * Read and return BMDMA status register. | ||
605 | * | ||
606 | * May be used as the bmdma_status() entry in ata_port_operations. | ||
607 | * | ||
608 | * LOCKING: | ||
609 | * spin_lock_irqsave(host_set lock) | ||
610 | */ | ||
611 | |||
612 | u8 ata_bmdma_status(struct ata_port *ap) | ||
613 | { | ||
614 | u8 host_stat; | ||
615 | if (ap->flags & ATA_FLAG_MMIO) { | ||
616 | void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; | ||
617 | host_stat = readb(mmio + ATA_DMA_STATUS); | ||
618 | } else | ||
619 | host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); | ||
620 | return host_stat; | ||
621 | } | ||
622 | |||
623 | |||
624 | /** | ||
625 | * ata_bmdma_stop - Stop PCI IDE BMDMA transfer | ||
626 | * @qc: Command we are ending DMA for | ||
627 | * | ||
628 | * Clears the ATA_DMA_START flag in the dma control register | ||
629 | * | ||
630 | * May be used as the bmdma_stop() entry in ata_port_operations. | ||
631 | * | ||
632 | * LOCKING: | ||
633 | * spin_lock_irqsave(host_set lock) | ||
634 | */ | ||
635 | |||
636 | void ata_bmdma_stop(struct ata_queued_cmd *qc) | ||
637 | { | ||
638 | struct ata_port *ap = qc->ap; | ||
639 | if (ap->flags & ATA_FLAG_MMIO) { | ||
640 | void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; | ||
641 | |||
642 | /* clear start/stop bit */ | ||
643 | writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START, | ||
644 | mmio + ATA_DMA_CMD); | ||
645 | } else { | ||
646 | /* clear start/stop bit */ | ||
647 | outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START, | ||
648 | ap->ioaddr.bmdma_addr + ATA_DMA_CMD); | ||
649 | } | ||
650 | |||
651 | /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ | ||
652 | ata_altstatus(ap); /* dummy read */ | ||
653 | } | ||
654 | |||
421 | #ifdef CONFIG_PCI | 655 | #ifdef CONFIG_PCI |
422 | static struct ata_probe_ent * | 656 | static struct ata_probe_ent * |
423 | ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port) | 657 | ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port) |
@@ -707,7 +941,7 @@ err_out: | |||
707 | * @pdev: PCI device | 941 | * @pdev: PCI device |
708 | * | 942 | * |
709 | * Some PCI ATA devices report simplex mode but in fact can be told to | 943 | * Some PCI ATA devices report simplex mode but in fact can be told to |
710 | * enter non simplex mode. This implements the neccessary logic to | 944 | * enter non simplex mode. This implements the neccessary logic to |
711 | * perform the task on such devices. Calling it on other devices will | 945 | * perform the task on such devices. Calling it on other devices will |
712 | * have -undefined- behaviour. | 946 | * have -undefined- behaviour. |
713 | */ | 947 | */ |
@@ -732,7 +966,7 @@ unsigned long ata_pci_default_filter(const struct ata_port *ap, struct ata_devic | |||
732 | { | 966 | { |
733 | /* Filter out DMA modes if the device has been configured by | 967 | /* Filter out DMA modes if the device has been configured by |
734 | the BIOS as PIO only */ | 968 | the BIOS as PIO only */ |
735 | 969 | ||
736 | if (ap->ioaddr.bmdma_addr == 0) | 970 | if (ap->ioaddr.bmdma_addr == 0) |
737 | xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); | 971 | xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); |
738 | return xfer_mask; | 972 | return xfer_mask; |