aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-probe.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/ide-probe.c')
-rw-r--r--drivers/ide/ide-probe.c94
1 files changed, 69 insertions, 25 deletions
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index c588066295db..84a89561ec0f 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -1477,7 +1477,7 @@ static int ide_sysfs_register_port(ide_hwif_t *hwif)
1477 * Return the new hwif. If we are out of free slots return NULL. 1477 * Return the new hwif. If we are out of free slots return NULL.
1478 */ 1478 */
1479 1479
1480ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d) 1480static ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d)
1481{ 1481{
1482 ide_hwif_t *hwif; 1482 ide_hwif_t *hwif;
1483 int i; 1483 int i;
@@ -1523,14 +1523,63 @@ out_found:
1523 ide_init_port_data(hwif, i); 1523 ide_init_port_data(hwif, i);
1524 return hwif; 1524 return hwif;
1525} 1525}
1526EXPORT_SYMBOL_GPL(ide_find_port_slot);
1527 1526
1528int ide_device_add_all(u8 *idx, const struct ide_port_info *d, hw_regs_t **hws) 1527struct ide_host *ide_host_alloc_all(const struct ide_port_info *d,
1528 hw_regs_t **hws)
1529{
1530 struct ide_host *host;
1531 int i;
1532
1533 host = kzalloc(sizeof(*host), GFP_KERNEL);
1534 if (host == NULL)
1535 return NULL;
1536
1537 for (i = 0; i < MAX_HWIFS; i++) {
1538 ide_hwif_t *hwif;
1539
1540 if (hws[i] == NULL)
1541 continue;
1542
1543 hwif = ide_find_port_slot(d);
1544 if (hwif) {
1545 hwif->chipset = hws[i]->chipset;
1546
1547 host->ports[i] = hwif;
1548 host->n_ports++;
1549 }
1550 }
1551
1552 if (host->n_ports == 0) {
1553 kfree(host);
1554 return NULL;
1555 }
1556
1557 return host;
1558}
1559EXPORT_SYMBOL_GPL(ide_host_alloc_all);
1560
1561struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws)
1562{
1563 hw_regs_t *hws_all[MAX_HWIFS];
1564 int i;
1565
1566 for (i = 0; i < MAX_HWIFS; i++)
1567 hws_all[i] = (i < 4) ? hws[i] : NULL;
1568
1569 return ide_host_alloc_all(d, hws_all);
1570}
1571EXPORT_SYMBOL_GPL(ide_host_alloc);
1572
1573int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
1574 hw_regs_t **hws)
1529{ 1575{
1530 ide_hwif_t *hwif, *mate = NULL; 1576 ide_hwif_t *hwif, *mate = NULL;
1577 u8 idx[MAX_HWIFS];
1531 int i, rc = 0; 1578 int i, rc = 0;
1532 1579
1533 for (i = 0; i < MAX_HWIFS; i++) { 1580 for (i = 0; i < MAX_HWIFS; i++) {
1581 idx[i] = host->ports[i] ? host->ports[i]->index : 0xff;
1582
1534 if (idx[i] == 0xff) { 1583 if (idx[i] == 0xff) {
1535 mate = NULL; 1584 mate = NULL;
1536 continue; 1585 continue;
@@ -1626,22 +1675,20 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d, hw_regs_t **hws)
1626 1675
1627 return rc; 1676 return rc;
1628} 1677}
1629EXPORT_SYMBOL_GPL(ide_device_add_all); 1678EXPORT_SYMBOL_GPL(ide_host_register);
1630 1679
1631int ide_device_add(u8 *idx, const struct ide_port_info *d, hw_regs_t **hws) 1680void ide_host_remove(struct ide_host *host)
1632{ 1681{
1633 hw_regs_t *hws_all[MAX_HWIFS];
1634 u8 idx_all[MAX_HWIFS];
1635 int i; 1682 int i;
1636 1683
1637 for (i = 0; i < MAX_HWIFS; i++) { 1684 for (i = 0; i < MAX_HWIFS; i++) {
1638 hws_all[i] = (i < 4) ? hws[i] : NULL; 1685 if (host->ports[i])
1639 idx_all[i] = (i < 4) ? idx[i] : 0xff; 1686 ide_unregister(host->ports[i]);
1640 } 1687 }
1641 1688
1642 return ide_device_add_all(idx_all, d, hws_all); 1689 kfree(host);
1643} 1690}
1644EXPORT_SYMBOL_GPL(ide_device_add); 1691EXPORT_SYMBOL_GPL(ide_host_remove);
1645 1692
1646void ide_port_scan(ide_hwif_t *hwif) 1693void ide_port_scan(ide_hwif_t *hwif)
1647{ 1694{
@@ -1662,11 +1709,10 @@ void ide_port_scan(ide_hwif_t *hwif)
1662} 1709}
1663EXPORT_SYMBOL_GPL(ide_port_scan); 1710EXPORT_SYMBOL_GPL(ide_port_scan);
1664 1711
1665static void ide_legacy_init_one(u8 *idx, hw_regs_t **hws, hw_regs_t *hw, 1712static void ide_legacy_init_one(hw_regs_t **hws, hw_regs_t *hw,
1666 u8 port_no, const struct ide_port_info *d, 1713 u8 port_no, const struct ide_port_info *d,
1667 unsigned long config) 1714 unsigned long config)
1668{ 1715{
1669 ide_hwif_t *hwif;
1670 unsigned long base, ctl; 1716 unsigned long base, ctl;
1671 int irq; 1717 int irq;
1672 1718
@@ -1698,31 +1744,29 @@ static void ide_legacy_init_one(u8 *idx, hw_regs_t **hws, hw_regs_t *hw,
1698 hw->chipset = d->chipset; 1744 hw->chipset = d->chipset;
1699 hw->config = config; 1745 hw->config = config;
1700 1746
1701 hwif = ide_find_port_slot(d); 1747 hws[port_no] = hw;
1702 if (hwif) {
1703 hwif->chipset = hw->chipset;
1704
1705 hws[port_no] = hw;
1706 idx[port_no] = hwif->index;
1707 }
1708} 1748}
1709 1749
1710int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config) 1750int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config)
1711{ 1751{
1712 u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; 1752 struct ide_host *host;
1713 hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL }; 1753 hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL };
1714 1754
1715 memset(&hw, 0, sizeof(hw)); 1755 memset(&hw, 0, sizeof(hw));
1716 1756
1717 if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0) 1757 if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0)
1718 ide_legacy_init_one(idx, hws, &hw[0], 0, d, config); 1758 ide_legacy_init_one(hws, &hw[0], 0, d, config);
1719 ide_legacy_init_one(idx, hws, &hw[1], 1, d, config); 1759 ide_legacy_init_one(hws, &hw[1], 1, d, config);
1720 1760
1721 if (idx[0] == 0xff && idx[1] == 0xff && 1761 if (hws[0] == NULL && hws[1] == NULL &&
1722 (d->host_flags & IDE_HFLAG_SINGLE)) 1762 (d->host_flags & IDE_HFLAG_SINGLE))
1723 return -ENOENT; 1763 return -ENOENT;
1724 1764
1725 ide_device_add(idx, d, hws); 1765 host = ide_host_alloc(d, hws);
1766 if (host == NULL)
1767 return -ENOMEM;
1768
1769 ide_host_register(host, d, hws);
1726 1770
1727 return 0; 1771 return 0;
1728} 1772}