diff options
Diffstat (limited to 'drivers/ide/ide-probe.c')
| -rw-r--r-- | drivers/ide/ide-probe.c | 164 |
1 files changed, 119 insertions, 45 deletions
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 875429728021..a4b65b321f51 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
| @@ -644,7 +644,7 @@ static int ide_register_port(ide_hwif_t *hwif) | |||
| 644 | ret = device_register(&hwif->gendev); | 644 | ret = device_register(&hwif->gendev); |
| 645 | if (ret < 0) { | 645 | if (ret < 0) { |
| 646 | printk(KERN_WARNING "IDE: %s: device_register error: %d\n", | 646 | printk(KERN_WARNING "IDE: %s: device_register error: %d\n", |
| 647 | __FUNCTION__, ret); | 647 | __func__, ret); |
| 648 | goto out; | 648 | goto out; |
| 649 | } | 649 | } |
| 650 | 650 | ||
| @@ -773,8 +773,7 @@ static int ide_probe_port(ide_hwif_t *hwif) | |||
| 773 | 773 | ||
| 774 | BUG_ON(hwif->present); | 774 | BUG_ON(hwif->present); |
| 775 | 775 | ||
| 776 | if (hwif->noprobe || | 776 | if (hwif->drives[0].noprobe && hwif->drives[1].noprobe) |
| 777 | (hwif->drives[0].noprobe && hwif->drives[1].noprobe)) | ||
| 778 | return -EACCES; | 777 | return -EACCES; |
| 779 | 778 | ||
| 780 | /* | 779 | /* |
| @@ -821,13 +820,14 @@ static int ide_probe_port(ide_hwif_t *hwif) | |||
| 821 | 820 | ||
| 822 | static void ide_port_tune_devices(ide_hwif_t *hwif) | 821 | static void ide_port_tune_devices(ide_hwif_t *hwif) |
| 823 | { | 822 | { |
| 823 | const struct ide_port_ops *port_ops = hwif->port_ops; | ||
| 824 | int unit; | 824 | int unit; |
| 825 | 825 | ||
| 826 | for (unit = 0; unit < MAX_DRIVES; unit++) { | 826 | for (unit = 0; unit < MAX_DRIVES; unit++) { |
| 827 | ide_drive_t *drive = &hwif->drives[unit]; | 827 | ide_drive_t *drive = &hwif->drives[unit]; |
| 828 | 828 | ||
| 829 | if (drive->present && hwif->quirkproc) | 829 | if (drive->present && port_ops && port_ops->quirkproc) |
| 830 | hwif->quirkproc(drive); | 830 | port_ops->quirkproc(drive); |
| 831 | } | 831 | } |
| 832 | 832 | ||
| 833 | for (unit = 0; unit < MAX_DRIVES; ++unit) { | 833 | for (unit = 0; unit < MAX_DRIVES; ++unit) { |
| @@ -843,7 +843,7 @@ static void ide_port_tune_devices(ide_hwif_t *hwif) | |||
| 843 | 843 | ||
| 844 | drive->nice1 = 1; | 844 | drive->nice1 = 1; |
| 845 | 845 | ||
| 846 | if (hwif->dma_host_set) | 846 | if (hwif->dma_ops) |
| 847 | ide_set_dma(drive); | 847 | ide_set_dma(drive); |
| 848 | } | 848 | } |
| 849 | } | 849 | } |
| @@ -1324,6 +1324,7 @@ static void hwif_register_devices(ide_hwif_t *hwif) | |||
| 1324 | 1324 | ||
| 1325 | static void ide_port_init_devices(ide_hwif_t *hwif) | 1325 | static void ide_port_init_devices(ide_hwif_t *hwif) |
| 1326 | { | 1326 | { |
| 1327 | const struct ide_port_ops *port_ops = hwif->port_ops; | ||
| 1327 | int i; | 1328 | int i; |
| 1328 | 1329 | ||
| 1329 | for (i = 0; i < MAX_DRIVES; i++) { | 1330 | for (i = 0; i < MAX_DRIVES; i++) { |
| @@ -1339,8 +1340,8 @@ static void ide_port_init_devices(ide_hwif_t *hwif) | |||
| 1339 | drive->autotune = 1; | 1340 | drive->autotune = 1; |
| 1340 | } | 1341 | } |
| 1341 | 1342 | ||
| 1342 | if (hwif->port_init_devs) | 1343 | if (port_ops && port_ops->port_init_devs) |
| 1343 | hwif->port_init_devs(hwif); | 1344 | port_ops->port_init_devs(hwif); |
| 1344 | } | 1345 | } |
| 1345 | 1346 | ||
| 1346 | static void ide_init_port(ide_hwif_t *hwif, unsigned int port, | 1347 | static void ide_init_port(ide_hwif_t *hwif, unsigned int port, |
| @@ -1355,9 +1356,6 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port, | |||
| 1355 | if (d->init_iops) | 1356 | if (d->init_iops) |
| 1356 | d->init_iops(hwif); | 1357 | d->init_iops(hwif); |
| 1357 | 1358 | ||
| 1358 | if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) | ||
| 1359 | ide_hwif_setup_dma(hwif, d); | ||
| 1360 | |||
| 1361 | if ((!hwif->irq && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || | 1359 | if ((!hwif->irq && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || |
| 1362 | (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) | 1360 | (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) |
| 1363 | hwif->irq = port ? 15 : 14; | 1361 | hwif->irq = port ? 15 : 14; |
| @@ -1365,16 +1363,36 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port, | |||
| 1365 | hwif->host_flags = d->host_flags; | 1363 | hwif->host_flags = d->host_flags; |
| 1366 | hwif->pio_mask = d->pio_mask; | 1364 | hwif->pio_mask = d->pio_mask; |
| 1367 | 1365 | ||
| 1368 | if ((d->host_flags & IDE_HFLAG_SERIALIZE) && hwif->mate) | 1366 | /* ->set_pio_mode for DTC2278 is currently limited to port 0 */ |
| 1369 | hwif->mate->serialized = hwif->serialized = 1; | 1367 | if (hwif->chipset != ide_dtc2278 || hwif->channel == 0) |
| 1368 | hwif->port_ops = d->port_ops; | ||
| 1369 | |||
| 1370 | if ((d->host_flags & IDE_HFLAG_SERIALIZE) || | ||
| 1371 | ((d->host_flags & IDE_HFLAG_SERIALIZE_DMA) && hwif->dma_base)) { | ||
| 1372 | if (hwif->mate) | ||
| 1373 | hwif->mate->serialized = hwif->serialized = 1; | ||
| 1374 | } | ||
| 1370 | 1375 | ||
| 1371 | hwif->swdma_mask = d->swdma_mask; | 1376 | hwif->swdma_mask = d->swdma_mask; |
| 1372 | hwif->mwdma_mask = d->mwdma_mask; | 1377 | hwif->mwdma_mask = d->mwdma_mask; |
| 1373 | hwif->ultra_mask = d->udma_mask; | 1378 | hwif->ultra_mask = d->udma_mask; |
| 1374 | 1379 | ||
| 1375 | /* reset DMA masks only for SFF-style DMA controllers */ | 1380 | if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) { |
| 1376 | if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0 && hwif->dma_base == 0) | 1381 | int rc; |
| 1377 | hwif->swdma_mask = hwif->mwdma_mask = hwif->ultra_mask = 0; | 1382 | |
| 1383 | if (d->init_dma) | ||
| 1384 | rc = d->init_dma(hwif, d); | ||
| 1385 | else | ||
| 1386 | rc = ide_hwif_setup_dma(hwif, d); | ||
| 1387 | |||
| 1388 | if (rc < 0) { | ||
| 1389 | printk(KERN_INFO "%s: DMA disabled\n", hwif->name); | ||
| 1390 | hwif->swdma_mask = 0; | ||
| 1391 | hwif->mwdma_mask = 0; | ||
| 1392 | hwif->ultra_mask = 0; | ||
| 1393 | } else if (d->dma_ops) | ||
| 1394 | hwif->dma_ops = d->dma_ops; | ||
| 1395 | } | ||
| 1378 | 1396 | ||
| 1379 | if (d->host_flags & IDE_HFLAG_RQSIZE_256) | 1397 | if (d->host_flags & IDE_HFLAG_RQSIZE_256) |
| 1380 | hwif->rqsize = 256; | 1398 | hwif->rqsize = 256; |
| @@ -1386,9 +1404,11 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port, | |||
| 1386 | 1404 | ||
| 1387 | static void ide_port_cable_detect(ide_hwif_t *hwif) | 1405 | static void ide_port_cable_detect(ide_hwif_t *hwif) |
| 1388 | { | 1406 | { |
| 1389 | if (hwif->cable_detect && (hwif->ultra_mask & 0x78)) { | 1407 | const struct ide_port_ops *port_ops = hwif->port_ops; |
| 1408 | |||
| 1409 | if (port_ops && port_ops->cable_detect && (hwif->ultra_mask & 0x78)) { | ||
| 1390 | if (hwif->cbl != ATA_CBL_PATA40_SHORT) | 1410 | if (hwif->cbl != ATA_CBL_PATA40_SHORT) |
| 1391 | hwif->cbl = hwif->cable_detect(hwif); | 1411 | hwif->cbl = port_ops->cable_detect(hwif); |
| 1392 | } | 1412 | } |
| 1393 | } | 1413 | } |
| 1394 | 1414 | ||
| @@ -1523,25 +1543,15 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d) | |||
| 1523 | 1543 | ||
| 1524 | hwif = &ide_hwifs[idx[i]]; | 1544 | hwif = &ide_hwifs[idx[i]]; |
| 1525 | 1545 | ||
| 1526 | if ((hwif->chipset != ide_4drives || !hwif->mate || | 1546 | if (ide_probe_port(hwif) == 0) |
| 1527 | !hwif->mate->present) && ide_hwif_request_regions(hwif)) { | 1547 | hwif->present = 1; |
| 1528 | printk(KERN_ERR "%s: ports already in use, " | ||
| 1529 | "skipping probe\n", hwif->name); | ||
| 1530 | continue; | ||
| 1531 | } | ||
| 1532 | |||
| 1533 | if (ide_probe_port(hwif) < 0) { | ||
| 1534 | ide_hwif_release_regions(hwif); | ||
| 1535 | continue; | ||
| 1536 | } | ||
| 1537 | |||
| 1538 | hwif->present = 1; | ||
| 1539 | 1548 | ||
| 1540 | if (hwif->chipset != ide_4drives || !hwif->mate || | 1549 | if (hwif->chipset != ide_4drives || !hwif->mate || |
| 1541 | !hwif->mate->present) | 1550 | !hwif->mate->present) |
| 1542 | ide_register_port(hwif); | 1551 | ide_register_port(hwif); |
| 1543 | 1552 | ||
| 1544 | ide_port_tune_devices(hwif); | 1553 | if (hwif->present) |
| 1554 | ide_port_tune_devices(hwif); | ||
| 1545 | } | 1555 | } |
| 1546 | 1556 | ||
| 1547 | for (i = 0; i < MAX_HWIFS; i++) { | 1557 | for (i = 0; i < MAX_HWIFS; i++) { |
| @@ -1550,9 +1560,6 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d) | |||
| 1550 | 1560 | ||
| 1551 | hwif = &ide_hwifs[idx[i]]; | 1561 | hwif = &ide_hwifs[idx[i]]; |
| 1552 | 1562 | ||
| 1553 | if (!hwif->present) | ||
| 1554 | continue; | ||
| 1555 | |||
| 1556 | if (hwif_init(hwif) == 0) { | 1563 | if (hwif_init(hwif) == 0) { |
| 1557 | printk(KERN_INFO "%s: failed to initialize IDE " | 1564 | printk(KERN_INFO "%s: failed to initialize IDE " |
| 1558 | "interface\n", hwif->name); | 1565 | "interface\n", hwif->name); |
| @@ -1561,10 +1568,13 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d) | |||
| 1561 | continue; | 1568 | continue; |
| 1562 | } | 1569 | } |
| 1563 | 1570 | ||
| 1564 | ide_port_setup_devices(hwif); | 1571 | if (hwif->present) |
| 1572 | ide_port_setup_devices(hwif); | ||
| 1565 | 1573 | ||
| 1566 | ide_acpi_init(hwif); | 1574 | ide_acpi_init(hwif); |
| 1567 | ide_acpi_port_init_devices(hwif); | 1575 | |
| 1576 | if (hwif->present) | ||
| 1577 | ide_acpi_port_init_devices(hwif); | ||
| 1568 | } | 1578 | } |
| 1569 | 1579 | ||
| 1570 | for (i = 0; i < MAX_HWIFS; i++) { | 1580 | for (i = 0; i < MAX_HWIFS; i++) { |
| @@ -1573,11 +1583,11 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d) | |||
| 1573 | 1583 | ||
| 1574 | hwif = &ide_hwifs[idx[i]]; | 1584 | hwif = &ide_hwifs[idx[i]]; |
| 1575 | 1585 | ||
| 1576 | if (hwif->present) { | 1586 | if (hwif->chipset == ide_unknown) |
| 1577 | if (hwif->chipset == ide_unknown) | 1587 | hwif->chipset = ide_generic; |
| 1578 | hwif->chipset = ide_generic; | 1588 | |
| 1589 | if (hwif->present) | ||
| 1579 | hwif_register_devices(hwif); | 1590 | hwif_register_devices(hwif); |
| 1580 | } | ||
| 1581 | } | 1591 | } |
| 1582 | 1592 | ||
| 1583 | for (i = 0; i < MAX_HWIFS; i++) { | 1593 | for (i = 0; i < MAX_HWIFS; i++) { |
| @@ -1586,11 +1596,11 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d) | |||
| 1586 | 1596 | ||
| 1587 | hwif = &ide_hwifs[idx[i]]; | 1597 | hwif = &ide_hwifs[idx[i]]; |
| 1588 | 1598 | ||
| 1589 | if (hwif->present) { | 1599 | ide_sysfs_register_port(hwif); |
| 1590 | ide_sysfs_register_port(hwif); | 1600 | ide_proc_register_port(hwif); |
| 1591 | ide_proc_register_port(hwif); | 1601 | |
| 1602 | if (hwif->present) | ||
| 1592 | ide_proc_port_register_devices(hwif); | 1603 | ide_proc_port_register_devices(hwif); |
| 1593 | } | ||
| 1594 | } | 1604 | } |
| 1595 | 1605 | ||
| 1596 | return rc; | 1606 | return rc; |
| @@ -1626,3 +1636,67 @@ void ide_port_scan(ide_hwif_t *hwif) | |||
| 1626 | ide_proc_port_register_devices(hwif); | 1636 | ide_proc_port_register_devices(hwif); |
| 1627 | } | 1637 | } |
| 1628 | EXPORT_SYMBOL_GPL(ide_port_scan); | 1638 | EXPORT_SYMBOL_GPL(ide_port_scan); |
| 1639 | |||
| 1640 | static void ide_legacy_init_one(u8 *idx, hw_regs_t *hw, u8 port_no, | ||
| 1641 | const struct ide_port_info *d, | ||
| 1642 | unsigned long config) | ||
| 1643 | { | ||
| 1644 | ide_hwif_t *hwif; | ||
| 1645 | unsigned long base, ctl; | ||
| 1646 | int irq; | ||
| 1647 | |||
| 1648 | if (port_no == 0) { | ||
| 1649 | base = 0x1f0; | ||
| 1650 | ctl = 0x3f6; | ||
| 1651 | irq = 14; | ||
| 1652 | } else { | ||
| 1653 | base = 0x170; | ||
| 1654 | ctl = 0x376; | ||
| 1655 | irq = 15; | ||
| 1656 | } | ||
| 1657 | |||
| 1658 | if (!request_region(base, 8, d->name)) { | ||
| 1659 | printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", | ||
| 1660 | d->name, base, base + 7); | ||
| 1661 | return; | ||
| 1662 | } | ||
| 1663 | |||
| 1664 | if (!request_region(ctl, 1, d->name)) { | ||
| 1665 | printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n", | ||
| 1666 | d->name, ctl); | ||
| 1667 | release_region(base, 8); | ||
| 1668 | return; | ||
| 1669 | } | ||
| 1670 | |||
| 1671 | ide_std_init_ports(hw, base, ctl); | ||
| 1672 | hw->irq = irq; | ||
| 1673 | |||
| 1674 | hwif = ide_find_port_slot(d); | ||
| 1675 | if (hwif) { | ||
| 1676 | ide_init_port_hw(hwif, hw); | ||
| 1677 | if (config) | ||
| 1678 | hwif->config_data = config; | ||
| 1679 | idx[port_no] = hwif->index; | ||
| 1680 | } | ||
| 1681 | } | ||
| 1682 | |||
| 1683 | int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config) | ||
| 1684 | { | ||
| 1685 | u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; | ||
| 1686 | hw_regs_t hw[2]; | ||
| 1687 | |||
| 1688 | memset(&hw, 0, sizeof(hw)); | ||
| 1689 | |||
| 1690 | if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0) | ||
| 1691 | ide_legacy_init_one(idx, &hw[0], 0, d, config); | ||
| 1692 | ide_legacy_init_one(idx, &hw[1], 1, d, config); | ||
| 1693 | |||
| 1694 | if (idx[0] == 0xff && idx[1] == 0xff && | ||
| 1695 | (d->host_flags & IDE_HFLAG_SINGLE)) | ||
| 1696 | return -ENOENT; | ||
| 1697 | |||
| 1698 | ide_device_add(idx, d); | ||
| 1699 | |||
| 1700 | return 0; | ||
| 1701 | } | ||
| 1702 | EXPORT_SYMBOL_GPL(ide_legacy_device_add); | ||
