aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/libata-core.c149
1 files changed, 149 insertions, 0 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 09639e7aaa71..9269fd9b814f 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1538,6 +1538,152 @@ void ata_port_disable(struct ata_port *ap)
1538 ap->flags |= ATA_FLAG_PORT_DISABLED; 1538 ap->flags |= ATA_FLAG_PORT_DISABLED;
1539} 1539}
1540 1540
1541/*
1542 * This mode timing computation functionality is ported over from
1543 * drivers/ide/ide-timing.h and was originally written by Vojtech Pavlik
1544 */
1545/*
1546 * PIO 0-5, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds).
1547 * These were taken from ATA/ATAPI-6 standard, rev 0a, except
1548 * for PIO 5, which is a nonstandard extension and UDMA6, which
1549 * is currently supported only by Maxtor drives.
1550 */
1551
1552static const struct ata_timing ata_timing[] = {
1553
1554 { XFER_UDMA_6, 0, 0, 0, 0, 0, 0, 0, 15 },
1555 { XFER_UDMA_5, 0, 0, 0, 0, 0, 0, 0, 20 },
1556 { XFER_UDMA_4, 0, 0, 0, 0, 0, 0, 0, 30 },
1557 { XFER_UDMA_3, 0, 0, 0, 0, 0, 0, 0, 45 },
1558
1559 { XFER_UDMA_2, 0, 0, 0, 0, 0, 0, 0, 60 },
1560 { XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 80 },
1561 { XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 120 },
1562
1563/* { XFER_UDMA_SLOW, 0, 0, 0, 0, 0, 0, 0, 150 }, */
1564
1565 { XFER_MW_DMA_2, 25, 0, 0, 0, 70, 25, 120, 0 },
1566 { XFER_MW_DMA_1, 45, 0, 0, 0, 80, 50, 150, 0 },
1567 { XFER_MW_DMA_0, 60, 0, 0, 0, 215, 215, 480, 0 },
1568
1569 { XFER_SW_DMA_2, 60, 0, 0, 0, 120, 120, 240, 0 },
1570 { XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 480, 0 },
1571 { XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 960, 0 },
1572
1573/* { XFER_PIO_5, 20, 50, 30, 100, 50, 30, 100, 0 }, */
1574 { XFER_PIO_4, 25, 70, 25, 120, 70, 25, 120, 0 },
1575 { XFER_PIO_3, 30, 80, 70, 180, 80, 70, 180, 0 },
1576
1577 { XFER_PIO_2, 30, 290, 40, 330, 100, 90, 240, 0 },
1578 { XFER_PIO_1, 50, 290, 93, 383, 125, 100, 383, 0 },
1579 { XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0 },
1580
1581/* { XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 960, 0 }, */
1582
1583 { 0xFF }
1584};
1585
1586#define ENOUGH(v,unit) (((v)-1)/(unit)+1)
1587#define EZ(v,unit) ((v)?ENOUGH(v,unit):0)
1588
1589static void ata_timing_quantize(const struct ata_timing *t, struct ata_timing *q, int T, int UT)
1590{
1591 q->setup = EZ(t->setup * 1000, T);
1592 q->act8b = EZ(t->act8b * 1000, T);
1593 q->rec8b = EZ(t->rec8b * 1000, T);
1594 q->cyc8b = EZ(t->cyc8b * 1000, T);
1595 q->active = EZ(t->active * 1000, T);
1596 q->recover = EZ(t->recover * 1000, T);
1597 q->cycle = EZ(t->cycle * 1000, T);
1598 q->udma = EZ(t->udma * 1000, UT);
1599}
1600
1601void ata_timing_merge(const struct ata_timing *a, const struct ata_timing *b,
1602 struct ata_timing *m, unsigned int what)
1603{
1604 if (what & ATA_TIMING_SETUP ) m->setup = max(a->setup, b->setup);
1605 if (what & ATA_TIMING_ACT8B ) m->act8b = max(a->act8b, b->act8b);
1606 if (what & ATA_TIMING_REC8B ) m->rec8b = max(a->rec8b, b->rec8b);
1607 if (what & ATA_TIMING_CYC8B ) m->cyc8b = max(a->cyc8b, b->cyc8b);
1608 if (what & ATA_TIMING_ACTIVE ) m->active = max(a->active, b->active);
1609 if (what & ATA_TIMING_RECOVER) m->recover = max(a->recover, b->recover);
1610 if (what & ATA_TIMING_CYCLE ) m->cycle = max(a->cycle, b->cycle);
1611 if (what & ATA_TIMING_UDMA ) m->udma = max(a->udma, b->udma);
1612}
1613
1614static const struct ata_timing* ata_timing_find_mode(unsigned short speed)
1615{
1616 const struct ata_timing *t;
1617
1618 for (t = ata_timing; t->mode != speed; t++)
1619 if (t->mode != 0xFF)
1620 return NULL;
1621 return t;
1622}
1623
1624int ata_timing_compute(struct ata_device *adev, unsigned short speed,
1625 struct ata_timing *t, int T, int UT)
1626{
1627 const struct ata_timing *s;
1628 struct ata_timing p;
1629
1630 /*
1631 * Find the mode.
1632 */
1633
1634 if (!(s = ata_timing_find_mode(speed)))
1635 return -EINVAL;
1636
1637 /*
1638 * If the drive is an EIDE drive, it can tell us it needs extended
1639 * PIO/MW_DMA cycle timing.
1640 */
1641
1642 if (adev->id[ATA_ID_FIELD_VALID] & 2) { /* EIDE drive */
1643 memset(&p, 0, sizeof(p));
1644 if(speed >= XFER_PIO_0 && speed <= XFER_SW_DMA_0) {
1645 if (speed <= XFER_PIO_2) p.cycle = p.cyc8b = adev->id[ATA_ID_EIDE_PIO];
1646 else p.cycle = p.cyc8b = adev->id[ATA_ID_EIDE_PIO_IORDY];
1647 } else if(speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) {
1648 p.cycle = adev->id[ATA_ID_EIDE_DMA_MIN];
1649 }
1650 ata_timing_merge(&p, t, t, ATA_TIMING_CYCLE | ATA_TIMING_CYC8B);
1651 }
1652
1653 /*
1654 * Convert the timing to bus clock counts.
1655 */
1656
1657 ata_timing_quantize(s, t, T, UT);
1658
1659 /*
1660 * Even in DMA/UDMA modes we still use PIO access for IDENTIFY, S.M.A.R.T
1661 * and some other commands. We have to ensure that the DMA cycle timing is
1662 * slower/equal than the fastest PIO timing.
1663 */
1664
1665 if (speed > XFER_PIO_4) {
1666 ata_timing_compute(adev, adev->pio_mode, &p, T, UT);
1667 ata_timing_merge(&p, t, t, ATA_TIMING_ALL);
1668 }
1669
1670 /*
1671 * Lenghten active & recovery time so that cycle time is correct.
1672 */
1673
1674 if (t->act8b + t->rec8b < t->cyc8b) {
1675 t->act8b += (t->cyc8b - (t->act8b + t->rec8b)) / 2;
1676 t->rec8b = t->cyc8b - t->act8b;
1677 }
1678
1679 if (t->active + t->recover < t->cycle) {
1680 t->active += (t->cycle - (t->active + t->recover)) / 2;
1681 t->recover = t->cycle - t->active;
1682 }
1683
1684 return 0;
1685}
1686
1541static struct { 1687static struct {
1542 unsigned int shift; 1688 unsigned int shift;
1543 u8 base; 1689 u8 base;
@@ -4764,6 +4910,9 @@ EXPORT_SYMBOL_GPL(ata_dev_id_string);
4764EXPORT_SYMBOL_GPL(ata_dev_config); 4910EXPORT_SYMBOL_GPL(ata_dev_config);
4765EXPORT_SYMBOL_GPL(ata_scsi_simulate); 4911EXPORT_SYMBOL_GPL(ata_scsi_simulate);
4766 4912
4913EXPORT_SYMBOL_GPL(ata_timing_compute);
4914EXPORT_SYMBOL_GPL(ata_timing_merge);
4915
4767#ifdef CONFIG_PCI 4916#ifdef CONFIG_PCI
4768EXPORT_SYMBOL_GPL(pci_test_config_bits); 4917EXPORT_SYMBOL_GPL(pci_test_config_bits);
4769EXPORT_SYMBOL_GPL(ata_pci_host_stop); 4918EXPORT_SYMBOL_GPL(ata_pci_host_stop);