18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * This file provides autodetection for ISA PnP IDE interfaces.
48c2ecf20Sopenharmony_ci * It was tested with "ESS ES1868 Plug and Play AudioDrive" IDE interface.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Copyright (C) 2000 Andrey Panin <pazke@donpac.ru>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/init.h>
108c2ecf20Sopenharmony_ci#include <linux/pnp.h>
118c2ecf20Sopenharmony_ci#include <linux/ide.h>
128c2ecf20Sopenharmony_ci#include <linux/module.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#define DRV_NAME "ide-pnp"
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci/* Add your devices here :)) */
178c2ecf20Sopenharmony_cistatic const struct pnp_device_id idepnp_devices[] = {
188c2ecf20Sopenharmony_ci	/* Generic ESDI/IDE/ATA compatible hard disk controller */
198c2ecf20Sopenharmony_ci	{.id = "PNP0600", .driver_data = 0},
208c2ecf20Sopenharmony_ci	{.id = ""}
218c2ecf20Sopenharmony_ci};
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_cistatic const struct ide_port_info ide_pnp_port_info = {
248c2ecf20Sopenharmony_ci	.host_flags		= IDE_HFLAG_NO_DMA,
258c2ecf20Sopenharmony_ci	.chipset		= ide_generic,
268c2ecf20Sopenharmony_ci};
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_cistatic int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
298c2ecf20Sopenharmony_ci{
308c2ecf20Sopenharmony_ci	struct ide_host *host;
318c2ecf20Sopenharmony_ci	unsigned long base, ctl;
328c2ecf20Sopenharmony_ci	int rc;
338c2ecf20Sopenharmony_ci	struct ide_hw hw, *hws[] = { &hw };
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	printk(KERN_INFO DRV_NAME ": generic PnP IDE interface\n");
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	if (!(pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && pnp_irq_valid(dev, 0)))
388c2ecf20Sopenharmony_ci		return -1;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	base = pnp_port_start(dev, 0);
418c2ecf20Sopenharmony_ci	ctl = pnp_port_start(dev, 1);
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	if (!request_region(base, 8, DRV_NAME)) {
448c2ecf20Sopenharmony_ci		printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
458c2ecf20Sopenharmony_ci				DRV_NAME, base, base + 7);
468c2ecf20Sopenharmony_ci		return -EBUSY;
478c2ecf20Sopenharmony_ci	}
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	if (!request_region(ctl, 1, DRV_NAME)) {
508c2ecf20Sopenharmony_ci		printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
518c2ecf20Sopenharmony_ci				DRV_NAME, ctl);
528c2ecf20Sopenharmony_ci		release_region(base, 8);
538c2ecf20Sopenharmony_ci		return -EBUSY;
548c2ecf20Sopenharmony_ci	}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	memset(&hw, 0, sizeof(hw));
578c2ecf20Sopenharmony_ci	ide_std_init_ports(&hw, base, ctl);
588c2ecf20Sopenharmony_ci	hw.irq = pnp_irq(dev, 0);
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	rc = ide_host_add(&ide_pnp_port_info, hws, 1, &host);
618c2ecf20Sopenharmony_ci	if (rc)
628c2ecf20Sopenharmony_ci		goto out;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	pnp_set_drvdata(dev, host);
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	return 0;
678c2ecf20Sopenharmony_ciout:
688c2ecf20Sopenharmony_ci	release_region(ctl, 1);
698c2ecf20Sopenharmony_ci	release_region(base, 8);
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	return rc;
728c2ecf20Sopenharmony_ci}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cistatic void idepnp_remove(struct pnp_dev *dev)
758c2ecf20Sopenharmony_ci{
768c2ecf20Sopenharmony_ci	struct ide_host *host = pnp_get_drvdata(dev);
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	ide_host_remove(host);
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	release_region(pnp_port_start(dev, 1), 1);
818c2ecf20Sopenharmony_ci	release_region(pnp_port_start(dev, 0), 8);
828c2ecf20Sopenharmony_ci}
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_cistatic struct pnp_driver idepnp_driver = {
858c2ecf20Sopenharmony_ci	.name		= "ide",
868c2ecf20Sopenharmony_ci	.id_table	= idepnp_devices,
878c2ecf20Sopenharmony_ci	.probe		= idepnp_probe,
888c2ecf20Sopenharmony_ci	.remove		= idepnp_remove,
898c2ecf20Sopenharmony_ci};
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cimodule_pnp_driver(idepnp_driver);
928c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
93