/*
 * pnpacpi -- PnP ACPI driver
 *
 * Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr>
 * Copyright (c) 2004 Li Shaohua <shaohua.li@intel.com>
 * 
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
#include <linux/acpi.h>
#include <linux/pnp.h>
#include <acpi/acpi_bus.h>
#include "pnpacpi.h"

static int num = 0;

/* We need only to blacklist devices that have already an acpi driver that
 * can't use pnp layer. We don't need to blacklist device that are directly
 * used by the kernel (PCI root, ...), as it is harmless and there were
 * already present in pnpbios. But there is an exception for devices that
 * have irqs (PIC, Timer) because we call acpi_register_gsi.
 * Finaly only devices that have a CRS method need to be in this list.
 */
static char __initdata excluded_id_list[] =
	"PNP0C09," /* EC */
	"PNP0C0F," /* Link device */
	"PNP0000," /* PIC */
	"PNP0100," /* Timer */
	;
static inline int is_exclusive_device(struct acpi_device *dev)
{
	return (!acpi_match_ids(dev, excluded_id_list));
}

/*
 * Compatible Device IDs
 */
#define TEST_HEX(c) \
	if (!(('0' <= (c) && (c) <= '9') || ('A' <= (c) && (c) <= 'F'))) \
		return 0
#define TEST_ALPHA(c) \
	if (!('@' <= (c) || (c) <= 'Z')) \
		return 0
static int __init ispnpidacpi(char *id)
{
	TEST_ALPHA(id[0]);
	TEST_ALPHA(id[1]);
	TEST_ALPHA(id[2]);
	TEST_HEX(id[3]);
	TEST_HEX(id[4]);
	TEST_HEX(id[5]);
	TEST_HEX(id[6]);
	if (id[7] != '\0')
		return 0;
	return 1;
}

static void __init pnpidacpi_to_pnpid(char *id, char *str)
{
	str[0] = id[0];
	str[1] = id[1];
	str[2] = id[2];
	str[3] = tolower(id[3]);
	str[4] = tolower(id[4]);
	str[5] = tolower(id[5]);
	str[6] = tolower(id[6]);
	str[7] = '\0';
}

static int pnpacpi_get_resources(struct pnp_dev * dev, struct pnp_resource_table * res)
{
	acpi_status status;
	status = pnpacpi_parse_allocated_resource((acpi_handle)dev->data, 
		&dev->res);
	return ACPI_FAILURE(status) ? -ENODEV : 0;
}

static int pnpacpi_set_resources(struct pnp_dev * dev, struct pnp_resource_table * res)
{
	acpi_handle handle = dev->data;
	struct acpi_buffer buffer;
	int ret = 0;
	acpi_status status;

	ret = pnpacpi_build_resource_template(handle, &buffer);
	if (ret)
		return ret;
	ret = pnpacpi_encode_resources(res, &buffer);
	if (ret) {
		kfree(buffer.pointer);
		return ret;
	}
	status = acpi_set_current_resources(handle, &buffer);
	if (ACPI_FAILURE(status))
		ret = -EINVAL;
	kfree(buffer.pointer);
	return ret;
}

static int pnpacpi_disable_resources(struct pnp_dev *dev)
{
	acpi_status status;
	
	/* acpi_unregister_gsi(pnp_irq(dev, 0)); */
	status = acpi_evaluate_object((acpi_handle)dev->data, 
		"_DIS", NULL, NULL);
	return ACPI_FAILURE(status) ? -ENODEV : 0;
}

static struct pnp_protocol pnpacpi_protocol = {
	.name	= "Plug and Play ACPI",
	.get	= pnpacpi_get_resources,
	.set	= pnpacpi_set_resources,
	.disable = pnpacpi_disable_resources,
};

static int __init pnpacpi_add_device(struct acpi_device *device)
{
	acpi_handle temp = NULL;
	acpi_status status;
	struct pnp_id *dev_id;
	struct pnp_dev *dev;

	status = acpi_get_handle(device->handle, "_CRS", &temp);
	if (ACPI_FAILURE(status) || !ispnpidacpi(acpi_device_hid(device)) ||
		is_exclusive_device(device))
		return 0;

	pnp_dbg("ACPI device : hid %s", acpi_device_hid(device));
	dev =  kzalloc(sizeof(struct pnp_dev), GFP_KERNEL);
	if (!dev) {
		pnp_err("Out of memory");
		return -ENOMEM;
	}
	dev->data = device->handle;
	/* .enabled means if the device can decode the resources */
	dev->active = device->status.enabled;
	status = acpi_get_handle(device->handle, "_SRS", &temp);
	if (ACPI_SUCCESS(status))
		dev->capabilities |= PNP_CONFIGURABLE;
	dev->capabilities |= PNP_READ;
	if (device->flags.dynamic_status)
		dev->capabilities |= PNP_WRITE;
	if (device->flags.removable)
		dev->capabilities |= PNP_REMOVABLE;
	status = acpi_get_handle(device->handle, "_DIS", &temp);
	if (ACPI_SUCCESS(status))
		dev->capabilities |= PNP_DISABLE;

	dev->protocol = &pnpacpi_protocol;

	if (strlen(acpi_device_name(device)))
		strncpy(dev->name, acpi_device_name(device), sizeof(dev->name));
	else
		strncpy(dev->name, acpi_device_bid(device), sizeof(dev->name));

	dev->number = num;
	
	/* set the initial values for the PnP device */
	dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
	if (!dev_id)
		goto err;
	pnpidacpi_to_pnpid(acpi_device_hid(device), dev_id->id);
	pnp_add_id(dev_id, dev);

	if(dev->active) {
		/* parse allocated resource */
		status = pnpacpi_parse_allocated_resource(device->handle, &dev->res);
		if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
			pnp_err("PnPACPI: METHOD_NAME__CRS failure for %s", dev_id->id);
			goto err1;
		}
	}

	if(dev->capabilities & PNP_CONFIGURABLE) {
		status = pnpacpi_parse_resource_option_data(device->handle, 
			dev);
		if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
			pnp_err("PnPACPI: METHOD_NAME__PRS failure for %s", dev_id->id);
			goto err1;
		}
	}
	
	/* parse compatible ids */
	if (device->flags.compatible_ids) {
		struct acpi_compatible_id_list *cid_list = device->pnp.cid_list;
		int i;

		for (i = 0; i < cid_list->count; i++) {
			if (!ispnpidacpi(cid_list->id[i].value))
				continue;
			dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
			if (!dev_id)
				continue;

			pnpidacpi_to_pnpid(cid_list->id[i].value, dev_id->id);
			pnp_add_id(dev_id, dev);
		}
	}

	/* clear out the damaged flags */
	if (!dev->active)
		pnp_init_resource_table(&dev->res);
	pnp_add_device(dev);
	num ++;

	return AE_OK;
err1:
	kfree(dev_id);
err:
	kfree(dev);
	return -EINVAL;
}

static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle,
	u32 lvl, void *context, void **rv)
{
	struct acpi_device *device;

	if (!acpi_bus_get_device(handle, &device))
		pnpacpi_add_device(device);
	else
		return AE_CTRL_DEPTH;
	return AE_OK;
}

int pnpacpi_disabled __initdata;
static int __init pnpacpi_init(void)
{
	if (acpi_disabled || pnpacpi_disabled) {
		pnp_info("PnP ACPI: disabled");
		return 0;
	}
	pnp_info("PnP ACPI init");
	pnp_register_protocol(&pnpacpi_protocol);
	acpi_get_devices(NULL, pnpacpi_add_device_handler, NULL, NULL);
	pnp_info("PnP ACPI: found %d devices", num);
	return 0;
}
subsys_initcall(pnpacpi_init);

static int __init pnpacpi_setup(char *str)
{
	if (str == NULL)
		return 1;
	if (!strncmp(str, "off", 3))
		pnpacpi_disabled = 1;
	return 1;
}
__setup("pnpacpi=", pnpacpi_setup);

#if 0
EXPORT_SYMBOL(pnpacpi_protocol);
#endif
