ide: add struct ide_host (take 3)

* Add struct ide_host which keeps pointers to host's ports.

* Add ide_host_alloc[_all]() and ide_host_remove() helpers.

* Pass 'struct ide_host *host' instead of 'u8 *idx' to
  ide_device_add[_all]() and rename it to ide_host_register[_all]().

* Convert host drivers and core code to use struct ide_host.

* Remove no longer needed ide_find_port().

* Make ide_find_port_slot() static.

* Unexport ide_unregister().

v2:
* Add missing 'struct ide_host *host' to macide.c.

v3:
* Fix build problem in pmac.c (s/ide_alloc_host/ide_host_alloc/)
  (Noticed by Stephen Rothwell).
Signed-off-by: default avatarBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
parent 374e042c
......@@ -72,7 +72,7 @@ struct icside_state {
void __iomem *ioc_base;
unsigned int sel;
unsigned int type;
ide_hwif_t *hwif[2];
struct ide_host *host;
};
#define ICS_TYPE_A3IN 0
......@@ -442,10 +442,9 @@ static void icside_setup_ports(hw_regs_t *hw, void __iomem *base,
static int __init
icside_register_v5(struct icside_state *state, struct expansion_card *ec)
{
ide_hwif_t *hwif;
void __iomem *base;
struct ide_host *host;
hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
if (!base)
......@@ -465,17 +464,15 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec)
icside_setup_ports(&hw, base, &icside_cardinfo_v5, ec);
hwif = ide_find_port();
if (!hwif)
host = ide_host_alloc(NULL, hws);
if (host == NULL)
return -ENODEV;
state->hwif[0] = hwif;
state->host = host;
ecard_set_drvdata(ec, state);
idx[0] = hwif->index;
ide_device_add(idx, NULL, hws);
ide_host_register(host, NULL, hws);
return 0;
}
......@@ -492,12 +489,11 @@ static const struct ide_port_info icside_v6_port_info __initdata = {
static int __init
icside_register_v6(struct icside_state *state, struct expansion_card *ec)
{
ide_hwif_t *hwif, *mate;
void __iomem *ioc_base, *easi_base;
struct ide_host *host;
unsigned int sel = 0;
int ret;
hw_regs_t hw[2], *hws[] = { &hw[0], NULL, NULL, NULL };
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
struct ide_port_info d = icside_v6_port_info;
ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
......@@ -537,25 +533,11 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
icside_setup_ports(&hw[0], easi_base, &icside_cardinfo_v6_1, ec);
icside_setup_ports(&hw[1], easi_base, &icside_cardinfo_v6_2, ec);
/*
* Find and register the interfaces.
*/
hwif = ide_find_port();
if (hwif == NULL)
host = ide_host_alloc(&d, hws);
if (host == NULL)
return -ENODEV;
hwif->chipset = ide_acorn;
idx[0] = hwif->index;
mate = ide_find_port();
if (mate) {
hws[1] = &hw[1];
idx[1] = mate->index;
}
state->hwif[0] = hwif;
state->hwif[1] = mate;
state->host = host;
ecard_set_drvdata(ec, state);
......@@ -565,7 +547,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
d.dma_ops = NULL;
}
ide_device_add(idx, &d, hws);
ide_host_register(host, &d, hws);
return 0;
......
......@@ -28,10 +28,9 @@
static int __init ide_arm_init(void)
{
ide_hwif_t *hwif;
struct ide_host *host;
unsigned long base = IDE_ARM_IO, ctl = IDE_ARM_IO + 0x206;
hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
if (!request_region(base, 8, DRV_NAME)) {
printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
......@@ -51,12 +50,9 @@ static int __init ide_arm_init(void)
hw.irq = IDE_ARM_IRQ;
hw.chipset = ide_generic;
hwif = ide_find_port();
if (hwif) {
idx[0] = hwif->index;
ide_device_add(idx, NULL, hws);
}
host = ide_host_alloc(NULL, hws);
if (host)
ide_host_register(host, NULL, hws);
return 0;
}
......
......@@ -347,11 +347,10 @@ static int __devinit palm_bk3710_probe(struct platform_device *pdev)
{
struct clk *clk;
struct resource *mem, *irq;
ide_hwif_t *hwif;
struct ide_host *host;
unsigned long base, rate;
int i;
hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
clk = clk_get(NULL, "IDECLK");
if (IS_ERR(clk))
......@@ -393,15 +392,11 @@ static int __devinit palm_bk3710_probe(struct platform_device *pdev)
hw.irq = irq->start;
hw.chipset = ide_palm3710;
hwif = ide_find_port();
if (hwif == NULL)
host = ide_host_alloc(&palm_bk3710_port_info, hws);
if (host == NULL)
goto out;
i = hwif->index;
idx[0] = i;
ide_device_add(idx, &palm_bk3710_port_info, hws);
ide_host_register(host, &palm_bk3710_port_info, hws);
return 0;
out:
......
......@@ -32,11 +32,10 @@ static void rapide_setup_ports(hw_regs_t *hw, void __iomem *base,
static int __devinit
rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
{
ide_hwif_t *hwif;
void __iomem *base;
struct ide_host *host;
int ret;
hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
ret = ecard_request_resources(ec);
if (ret)
......@@ -53,17 +52,15 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
hw.chipset = ide_generic;
hw.dev = &ec->dev;
hwif = ide_find_port();
if (hwif == NULL) {
host = ide_host_alloc(&rapide_port_info, hws);
if (host == NULL) {
ret = -ENOENT;
goto release;
}
idx[0] = hwif->index;
ide_host_register(host, &rapide_port_info, hws);
ide_device_add(idx, &rapide_port_info, hws);
ecard_set_drvdata(ec, hwif);
ecard_set_drvdata(ec, host);
goto out;
release:
......@@ -74,11 +71,11 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
static void __devexit rapide_remove(struct expansion_card *ec)
{
ide_hwif_t *hwif = ecard_get_drvdata(ec);
struct ide_host *host = ecard_get_drvdata(ec);
ecard_set_drvdata(ec, NULL);
ide_unregister(hwif);
ide_host_remove(host);
ecard_release_resources(ec);
}
......
......@@ -191,10 +191,8 @@ static const struct ide_port_info h8300_port_info = {
static int __init h8300_ide_init(void)
{
ide_hwif_t *hwif;
int index;
struct ide_host *host;
hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
printk(KERN_INFO DRV_NAME ": H8/300 generic IDE interface\n");
......@@ -207,15 +205,11 @@ static int __init h8300_ide_init(void)
hw_setup(&hw);
hwif = ide_find_port_slot(&h8300_port_info);
if (hwif == NULL)
host = ide_host_alloc(&h8300_port_info, hws);
if (host == NULL)
return -ENOENT;
index = hwif->index;
idx[0] = index;
ide_device_add(idx, &h8300_port_info, hws);
ide_host_register(host, &h8300_port_info, hws);
return 0;
......
......@@ -28,27 +28,24 @@ MODULE_PARM_DESC(probe_mask, "probe mask for legacy ISA IDE ports");
static ssize_t store_add(struct class *cls, const char *buf, size_t n)
{
ide_hwif_t *hwif;
struct ide_host *host;
unsigned int base, ctl;
int irq;
hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
u8 idx[] = { 0xff, 0xff, 0xff, 0xff };
if (sscanf(buf, "%x:%x:%d", &base, &ctl, &irq) != 3)
return -EINVAL;
hwif = ide_find_port();
if (hwif == NULL)
return -ENOENT;
memset(&hw, 0, sizeof(hw));
ide_std_init_ports(&hw, base, ctl);
hw.irq = irq;
hw.chipset = ide_generic;
idx[0] = hwif->index;
host = ide_host_alloc(NULL, hws);
if (host == NULL)
return -ENOENT;
ide_device_add(idx, NULL, hws);
ide_host_register(host, NULL, hws);
return n;
};
......@@ -89,18 +86,16 @@ static int __init ide_generic_sysfs_init(void)
static int __init ide_generic_init(void)
{
hw_regs_t hw[MAX_HWIFS], *hws[MAX_HWIFS];
u8 idx[MAX_HWIFS];
struct ide_host *host;
int i;
printk(KERN_INFO DRV_NAME ": please use \"probe_mask=0x3f\" module "
"parameter for probing all legacy ISA IDE ports\n");
for (i = 0; i < MAX_HWIFS; i++) {
ide_hwif_t *hwif;
unsigned long io_addr = ide_default_io_base(i);
hws[i] = NULL;
idx[i] = 0xff;
if ((probe_mask & (1 << i)) && io_addr) {
if (!request_region(io_addr, 8, DRV_NAME)) {
......@@ -118,23 +113,18 @@ static int __init ide_generic_init(void)
continue;
}
hwif = ide_find_port();
if (hwif == NULL)
continue;
hwif->chipset = ide_generic;
memset(&hw[i], 0, sizeof(hw[i]));
ide_std_init_ports(&hw[i], io_addr, io_addr + 0x206);
hw[i].irq = ide_default_irq(io_addr);
hw[i].chipset = ide_generic;
hws[i] = &hw[i];
idx[i] = i;
}
}
ide_device_add_all(idx, NULL, hws);
host = ide_host_alloc_all(NULL, hws);
if (host)
ide_host_register(host, NULL, hws);
if (ide_generic_sysfs_init())
printk(KERN_ERR DRV_NAME ": failed to create ide_generic "
......
......@@ -29,7 +29,7 @@ static struct pnp_device_id idepnp_devices[] = {
static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
{
ide_hwif_t *hwif;
struct ide_host *host;
unsigned long base, ctl;
hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
......@@ -59,14 +59,11 @@ static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
hw.irq = pnp_irq(dev, 0);
hw.chipset = ide_generic;
hwif = ide_find_port();
if (hwif) {
u8 index = hwif->index;
u8 idx[4] = { index, 0xff, 0xff, 0xff };
host = ide_host_alloc(NULL, hws);
if (host) {
pnp_set_drvdata(dev, host);
pnp_set_drvdata(dev, hwif);
ide_device_add(idx, NULL, hws);
ide_host_register(host, NULL, hws);
return 0;
}
......@@ -79,9 +76,9 @@ static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
static void idepnp_remove(struct pnp_dev *dev)
{
ide_hwif_t *hwif = pnp_get_drvdata(dev);
struct ide_host *host = pnp_get_drvdata(dev);
ide_unregister(hwif);
ide_host_remove(host);
release_region(pnp_port_start(dev, 1), 1);
release_region(pnp_port_start(dev, 0), 8);
......
......@@ -1477,7 +1477,7 @@ static int ide_sysfs_register_port(ide_hwif_t *hwif)
* Return the new hwif. If we are out of free slots return NULL.
*/
ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d)
static ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d)
{
ide_hwif_t *hwif;
int i;
......@@ -1523,14 +1523,63 @@ out_found:
ide_init_port_data(hwif, i);
return hwif;
}
EXPORT_SYMBOL_GPL(ide_find_port_slot);
int ide_device_add_all(u8 *idx, const struct ide_port_info *d, hw_regs_t **hws)
struct ide_host *ide_host_alloc_all(const struct ide_port_info *d,
hw_regs_t **hws)
{
struct ide_host *host;
int i;
host = kzalloc(sizeof(*host), GFP_KERNEL);
if (host == NULL)
return NULL;
for (i = 0; i < MAX_HWIFS; i++) {
ide_hwif_t *hwif;
if (hws[i] == NULL)
continue;
hwif = ide_find_port_slot(d);
if (hwif) {
hwif->chipset = hws[i]->chipset;
host->ports[i] = hwif;
host->n_ports++;
}
}
if (host->n_ports == 0) {
kfree(host);
return NULL;
}
return host;
}
EXPORT_SYMBOL_GPL(ide_host_alloc_all);
struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws)
{
hw_regs_t *hws_all[MAX_HWIFS];
int i;
for (i = 0; i < MAX_HWIFS; i++)
hws_all[i] = (i < 4) ? hws[i] : NULL;
return ide_host_alloc_all(d, hws_all);
}
EXPORT_SYMBOL_GPL(ide_host_alloc);
int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
hw_regs_t **hws)
{
ide_hwif_t *hwif, *mate = NULL;
u8 idx[MAX_HWIFS];
int i, rc = 0;
for (i = 0; i < MAX_HWIFS; i++) {
idx[i] = host->ports[i] ? host->ports[i]->index : 0xff;
if (idx[i] == 0xff) {
mate = NULL;
continue;
......@@ -1626,22 +1675,20 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d, hw_regs_t **hws)
return rc;
}
EXPORT_SYMBOL_GPL(ide_device_add_all);
EXPORT_SYMBOL_GPL(ide_host_register);
int ide_device_add(u8 *idx, const struct ide_port_info *d, hw_regs_t **hws)
void ide_host_remove(struct ide_host *host)
{
hw_regs_t *hws_all[MAX_HWIFS];
u8 idx_all[MAX_HWIFS];
int i;
for (i = 0; i < MAX_HWIFS; i++) {
hws_all[i] = (i < 4) ? hws[i] : NULL;
idx_all[i] = (i < 4) ? idx[i] : 0xff;
if (host->ports[i])
ide_unregister(host->ports[i]);
}
return ide_device_add_all(idx_all, d, hws_all);
kfree(host);
}
EXPORT_SYMBOL_GPL(ide_device_add);
EXPORT_SYMBOL_GPL(ide_host_remove);
void ide_port_scan(ide_hwif_t *hwif)
{
......@@ -1662,11 +1709,10 @@ void ide_port_scan(ide_hwif_t *hwif)
}
EXPORT_SYMBOL_GPL(ide_port_scan);
static void ide_legacy_init_one(u8 *idx, hw_regs_t **hws, hw_regs_t *hw,
static void ide_legacy_init_one(hw_regs_t **hws, hw_regs_t *hw,
u8 port_no, const struct ide_port_info *d,
unsigned long config)
{
ide_hwif_t *hwif;
unsigned long base, ctl;
int irq;
......@@ -1698,31 +1744,29 @@ static void ide_legacy_init_one(u8 *idx, hw_regs_t **hws, hw_regs_t *hw,
hw->chipset = d->chipset;
hw->config = config;
hwif = ide_find_port_slot(d);
if (hwif) {
hwif->chipset = hw->chipset;
hws[port_no] = hw;
idx[port_no] = hwif->index;
}
hws[port_no] = hw;
}
int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config)
{
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
struct ide_host *host;
hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL };
memset(&hw, 0, sizeof(hw));
if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0)
ide_legacy_init_one(idx, hws, &hw[0], 0, d, config);
ide_legacy_init_one(idx, hws, &hw[1], 1, d, config);
ide_legacy_init_one(hws, &hw[0], 0, d, config);
ide_legacy_init_one(hws, &hw[1], 1, d, config);
if (idx[0] == 0xff && idx[1] == 0xff &&
if (hws[0] == NULL && hws[1] == NULL &&
(d->host_flags & IDE_HFLAG_SINGLE))
return -ENOENT;
ide_device_add(idx, d, hws);
host = ide_host_alloc(d, hws);
if (host == NULL)
return -ENOMEM;
ide_host_register(host, d, hws);
return 0;
}
......
......@@ -276,8 +276,6 @@ void ide_unregister(ide_hwif_t *hwif)
mutex_unlock(&ide_cfg_mtx);
}
EXPORT_SYMBOL(ide_unregister);
void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
{
memcpy(&hwif->io_ports, &hw->io_ports, sizeof(hwif->io_ports));
......
......@@ -150,18 +150,15 @@ static void __init buddha_setup_ports(hw_regs_t *hw, unsigned long base,
static int __init buddha_init(void)
{
ide_hwif_t *hwif;
int i;
struct zorro_dev *z = NULL;
struct ide_host *host;
u_long buddha_board = 0;
BuddhaType type;
int buddha_num_hwifs;
int buddha_num_hwifs, i;
while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
unsigned long board;
hw_regs_t hw[MAX_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) {
buddha_num_hwifs = BUDDHA_NUM_HWIFS;
......@@ -226,16 +223,12 @@ fail_base2:
buddha_setup_ports(&hw[i], base, ctl, irq_port,
ack_intr);
hwif = ide_find_port();
if (hwif) {
hwif->chipset = ide_generic;
hws[i] = &hw[i];
idx[i] = hwif->index;
}
hws[i] = &hw[i];
}
ide_device_add(idx, NULL, hws);
host = ide_host_alloc(NULL, hws);
if (host)
ide_host_register(host, NULL, hws);
}
return 0;
......
......@@ -112,7 +112,7 @@ static void __init falconide_setup_ports(hw_regs_t *hw)
static int __init falconide_init(void)
{
ide_hwif_t *hwif;
struct ide_host *host;
hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
if (!MACH_IS_ATARI || !ATARIHW_PRESENT(IDE))
......@@ -127,13 +127,10 @@ static int __init falconide_init(void)
falconide_setup_ports(&hw);
hwif = ide_find_port();
if (hwif) {
u8 index = hwif->index;
u8 idx[4] = { index, 0xff, 0xff, 0xff };
host = ide_host_alloc(&falconide_port_info, hws);
if (host) {
ide_get_lock(NULL, NULL);
ide_device_add(idx, &falconide_port_info, hws);
ide_host_register(host, &falconide_port_info, hws);
ide_release_lock();
}
......
......@@ -127,9 +127,9 @@ static int __init gayle_init(void)
unsigned long phys_base, res_start, res_n;
unsigned long base, ctrlport, irqport;
ide_ack_intr_t *ack_intr;
struct ide_host *host;
int a4000, i;
hw_regs_t hw[GAYLE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
if (!MACH_IS_AMIGA)
return -ENODEV;
......@@ -172,23 +172,17 @@ found:
return -EBUSY;
for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
ide_hwif_t *hwif;
base = (unsigned long)ZTWO_VADDR(phys_base + i * GAYLE_NEXT_PORT);
ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0;
gayle_setup_ports(&hw[i], base, ctrlport, irqport, ack_intr);
hwif = ide_find_port();
if (hwif) {
hwif->chipset = ide_generic;
hws[i] = &hw[i];
idx[i] = hwif->index;
}
hws[i] = &hw[i];
}
ide_device_add(idx, NULL, hws);
host = ide_host_alloc(NULL, hws);
if (host)
ide_host_register(host, NULL, hws);
return 0;
}
......
......@@ -28,10 +28,9 @@ static const struct ide_port_info ide_4drives_port_info = {
static int __init ide_4drives_init(void)
{
ide_hwif_t *hwif, *mate;
struct ide_host *host;
unsigned long base = 0x1f0, ctl = 0x3f6;
hw_regs_t hw, *hws[] = { NULL, NULL, NULL, NULL };
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
hw_regs_t hw, *hws[] = { &hw, &hw, NULL, NULL };
if (probe_4drives == 0)
return -ENODEV;
......@@ -55,21 +54,9 @@ static int __init ide_4drives_init(void)
hw.irq = 14;
hw.chipset = ide_4drives;
hwif = ide_find_port();
if (hwif) {
hwif->chipset = ide_4drives;
hws[0] = &hw;
idx[0] = hwif->index;
}
mate = ide_find_port();
if (mate) {
hws[1] = &hw;
idx[1] = mate->index;
}
ide_device_add(idx, &ide_4drives_port_info, hws);
host = ide_host_alloc(&ide_4drives_port_info, hws);
if (host)
ide_host_register(host, &ide_4drives_port_info, hws);
return 0;
}
......
......@@ -74,7 +74,7 @@ INT_MODULE_PARM(pc_debug, 0);
typedef struct ide_info_t {
struct pcmcia_device *p_dev;
ide_hwif_t *hwif;
struct ide_host *host;
int ndev;
dev_node_t node;
} ide_info_t;
......@@ -132,7 +132,7 @@ static int ide_probe(struct pcmcia_device *link)
static void ide_detach(struct pcmcia_device *link)
{
ide_info_t *info = link->priv;
ide_hwif_t *hwif = info->hwif;
ide_hwif_t *hwif = info->host->ports[0];
unsigned long data_addr, ctl_addr;
DEBUG(0, "ide_detach(0x%p)\n", link);
......@@ -157,13 +157,13 @@ static const struct ide_port_info idecs_port_info = {
.host_flags = IDE_HFLAG_NO_DMA,
};
static ide_hwif_t *idecs_register(unsigned long io, unsigned long ctl,
static struct ide_host *idecs_register(unsigned long io, unsigned long ctl,
unsigned long irq, struct pcmcia_device *handle)
{
struct ide_host *host;
ide_hwif_t *hwif;
int i;
hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
if (!request_region(io, 8, DRV_NAME)) {
printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
......@@ -184,26 +184,26 @@ static ide_hwif_t *idecs_register(unsigned long io, unsigned long ctl,
hw.chipset = ide_pci;
hw.dev = &handle->dev;
hwif = ide_find_port();
if (hwif == NULL)
host = ide_host_alloc(&idecs_port_info, hws);
if (host == NULL)
goto out_release;
idx[0] = hwif->index;
ide_host_register(host, &idecs_port_info, hws);
ide_device_add(idx, &idecs_port_info, hws);
hwif = host->ports[0];