18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci#include <linux/kernel.h>
38c2ecf20Sopenharmony_ci#include <linux/export.h>
48c2ecf20Sopenharmony_ci#include <linux/ide.h>
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_cistatic void ide_legacy_init_one(struct ide_hw **hws, struct ide_hw *hw,
78c2ecf20Sopenharmony_ci				u8 port_no, const struct ide_port_info *d,
88c2ecf20Sopenharmony_ci				unsigned long config)
98c2ecf20Sopenharmony_ci{
108c2ecf20Sopenharmony_ci	unsigned long base, ctl;
118c2ecf20Sopenharmony_ci	int irq;
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci	if (port_no == 0) {
148c2ecf20Sopenharmony_ci		base = 0x1f0;
158c2ecf20Sopenharmony_ci		ctl  = 0x3f6;
168c2ecf20Sopenharmony_ci		irq  = 14;
178c2ecf20Sopenharmony_ci	} else {
188c2ecf20Sopenharmony_ci		base = 0x170;
198c2ecf20Sopenharmony_ci		ctl  = 0x376;
208c2ecf20Sopenharmony_ci		irq  = 15;
218c2ecf20Sopenharmony_ci	}
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci	if (!request_region(base, 8, d->name)) {
248c2ecf20Sopenharmony_ci		printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
258c2ecf20Sopenharmony_ci				d->name, base, base + 7);
268c2ecf20Sopenharmony_ci		return;
278c2ecf20Sopenharmony_ci	}
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci	if (!request_region(ctl, 1, d->name)) {
308c2ecf20Sopenharmony_ci		printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
318c2ecf20Sopenharmony_ci				d->name, ctl);
328c2ecf20Sopenharmony_ci		release_region(base, 8);
338c2ecf20Sopenharmony_ci		return;
348c2ecf20Sopenharmony_ci	}
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	ide_std_init_ports(hw, base, ctl);
378c2ecf20Sopenharmony_ci	hw->irq = irq;
388c2ecf20Sopenharmony_ci	hw->config = config;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	hws[port_no] = hw;
418c2ecf20Sopenharmony_ci}
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ciint ide_legacy_device_add(const struct ide_port_info *d, unsigned long config)
448c2ecf20Sopenharmony_ci{
458c2ecf20Sopenharmony_ci	struct ide_hw hw[2], *hws[] = { NULL, NULL };
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	memset(&hw, 0, sizeof(hw));
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0)
508c2ecf20Sopenharmony_ci		ide_legacy_init_one(hws, &hw[0], 0, d, config);
518c2ecf20Sopenharmony_ci	ide_legacy_init_one(hws, &hw[1], 1, d, config);
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	if (hws[0] == NULL && hws[1] == NULL &&
548c2ecf20Sopenharmony_ci	    (d->host_flags & IDE_HFLAG_SINGLE))
558c2ecf20Sopenharmony_ci		return -ENOENT;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	return ide_host_add(d, hws, 2, NULL);
588c2ecf20Sopenharmony_ci}
598c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ide_legacy_device_add);
60