public inbox for linux-acpi@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC/patch] ACPI in linux PnP layer
@ 2004-09-08 11:00 castet.matthieu-GANU6spQydw
       [not found] ` <1094641221.413ee645d2cb6-/A4Sof3AOA+ksujEA26zIQ@public.gmane.org>
  0 siblings, 1 reply; 6+ messages in thread
From: castet.matthieu-GANU6spQydw @ 2004-09-08 11:00 UTC (permalink / raw)
  To: acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f

[-- Attachment #1: Type: text/plain, Size: 642 bytes --]

Hi,

I have started to plug acpi in PnP layer.
A first patch add the function acpi_driver_scan, that allow to call a function
for each acpi device.
I have to do that because acpi is load before PnP, and it can't add my function
in acpi_bus_add (driver/acpi/scan.c).

The second patch is the PnP acpi driver.
It parse possible and activated resources.
It use acpi_register_gsi to activate irq (is that need ???)

Also there are no disable/set acpi resource support, nor ADDRESS resource
support.

But it work well with drivers that work with pnpbios(parport, serial, ...).

What do you think of it ?
Any comment ?

Matthieu

[-- Attachment #2: acpi.patch --]
[-- Type: application/octet-stream, Size: 1058 bytes --]

diff -ruN --exclude='*.cmd' --exclude='*.o' --exclude='*.ko' linux.old/drivers/acpi/scan.c linux-2.6.9/drivers/acpi/scan.c
--- linux.old/drivers/acpi/scan.c	2004-09-04 14:16:37.000000000 +0200
+++ linux-2.6.9/drivers/acpi/scan.c	2004-09-04 14:39:47.000000000 +0200
@@ -8,6 +8,7 @@
 #include <acpi/acpi_drivers.h>
 #include <acpi/acinterp.h>	/* for acpi_ex_eisa_id_to_string() */
 
+#include <linux/module.h>
 
 #define _COMPONENT		ACPI_BUS_COMPONENT
 ACPI_MODULE_NAME		("scan")
@@ -1070,4 +1071,22 @@
 	return_VALUE(result);
 }
 
+int acpi_driver_scan(void (* handler)(struct acpi_device * dev))
+{
+	struct list_head * node, * next;
+	if (!handler)
+		 return_VALUE(-EINVAL);
+
+	spin_lock(&acpi_device_lock);
+	list_for_each_safe(node, next, &acpi_device_list) {
+		struct acpi_device * dev = container_of(node, struct acpi_device, g_list);
+		spin_unlock(&acpi_device_lock);
+		handler(dev);
+		spin_lock(&acpi_device_lock);
+	}
+	spin_unlock(&acpi_device_lock);
+	return_VALUE(0);
+}
+
 subsys_initcall(acpi_scan_init);
+EXPORT_SYMBOL(acpi_driver_scan);

[-- Attachment #3: pnpacpi.patch --]
[-- Type: application/octet-stream, Size: 19191 bytes --]

diff -ruN --exclude='*.cmd' --exclude='*.o' --exclude='*.ko' linux.old/drivers/pnp/Kconfig linux-2.6.9/drivers/pnp/Kconfig
--- linux.old/drivers/pnp/Kconfig	2004-06-16 07:19:23.000000000 +0200
+++ linux-2.6.9/drivers/pnp/Kconfig	2004-09-04 14:07:46.000000000 +0200
@@ -35,5 +35,7 @@
 
 source "drivers/pnp/pnpbios/Kconfig"
 
+source "drivers/pnp/pnpacpi/Kconfig"
+
 endmenu
 
diff -ruN --exclude='*.cmd' --exclude='*.o' --exclude='*.ko' linux.old/drivers/pnp/Makefile linux-2.6.9/drivers/pnp/Makefile
--- linux.old/drivers/pnp/Makefile	2004-06-16 07:18:38.000000000 +0200
+++ linux-2.6.9/drivers/pnp/Makefile	2004-09-04 14:12:57.000000000 +0200
@@ -6,3 +6,4 @@
 
 obj-$(CONFIG_PNPBIOS)		+= pnpbios/
 obj-$(CONFIG_ISAPNP)		+= isapnp/
+obj-$(CONFIG_PNPACPI)		+= pnpacpi/
diff -ruN --exclude='*.cmd' --exclude='*.o' --exclude='*.ko' linux.old/drivers/pnp/pnpacpi/core.c linux-2.6.9/drivers/pnp/pnpacpi/core.c
--- linux.old/drivers/pnp/pnpacpi/core.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.9/drivers/pnp/pnpacpi/core.c	2004-09-04 14:50:32.000000000 +0200
@@ -0,0 +1,608 @@
+/*
+ * pnpacpi -- PnP ACPI driver
+ *
+ * Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr>
+ * 
+ * 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
+ */
+
+/* TODO
+ * adress handling
+ * set/disble device
+ * code cleanning + memleak
+ * hotplug device
+ * remove device
+ */
+ 
+#include <acpi/acpi_bus.h>
+#include <linux/acpi.h>
+#include <linux/pnp.h>
+
+#define MAX_DEVICE 50
+static struct acpi_device * self [MAX_DEVICE] = {[0 ... (MAX_DEVICE-1)] = NULL};
+
+void *pnpacpi_kmalloc(size_t size, int f)
+{
+	void *p = kmalloc( size, f );
+	if ( p == NULL )
+		printk(KERN_ERR "PnPACPI: kmalloc() failed\n");
+	else
+		memset(p, 0, size);
+	return p;
+}
+/*
+ * Compatible Device IDs
+ */
+
+void 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';
+
+	return;
+}
+
+/*
+ * Allocated Resources
+ */
+
+static void
+pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, int irq)
+{
+	int i = 0;
+	while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) && i < PNP_MAX_IRQ) i++;
+	if (i < PNP_MAX_IRQ) {
+		res->irq_resource[i].flags = IORESOURCE_IRQ;  // Also clears _UNSET flag
+		if (irq == -1) {
+			res->irq_resource[i].flags |= IORESOURCE_DISABLED;
+			return;
+		}
+		res->irq_resource[i].start =
+		res->irq_resource[i].end = (unsigned long) irq;
+	}
+}
+
+static void
+pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, int dma)
+{
+	int i = 0;
+	while (!(res->dma_resource[i].flags & IORESOURCE_UNSET) && i < PNP_MAX_DMA) i++;
+	if (i < PNP_MAX_DMA) {
+		res->dma_resource[i].flags = IORESOURCE_DMA;  // Also clears _UNSET flag
+		if (dma == -1) {
+			res->dma_resource[i].flags |= IORESOURCE_DISABLED;
+			return;
+		}
+		res->dma_resource[i].start =
+		res->dma_resource[i].end = (unsigned long) dma;
+	}
+}
+
+static void
+pnpacpi_parse_allocated_ioresource(struct pnp_resource_table * res, int io, int len)
+{
+	int i = 0;
+	while (!(res->port_resource[i].flags & IORESOURCE_UNSET) && i < PNP_MAX_PORT) i++;
+	if (i < PNP_MAX_PORT) {
+		res->port_resource[i].flags = IORESOURCE_IO;  // Also clears _UNSET flag
+		if (len <= 0 || (io + len -1) >= 0x10003) {
+			res->port_resource[i].flags |= IORESOURCE_DISABLED;
+			return;
+		}
+		res->port_resource[i].start = (unsigned long) io;
+		res->port_resource[i].end = (unsigned long)(io + len - 1);
+	}
+}
+
+static void
+pnpacpi_parse_allocated_memresource(struct pnp_resource_table * res, int mem, int len)
+{
+	int i = 0;
+	while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) && i < PNP_MAX_MEM) i++;
+	if (i < PNP_MAX_MEM) {
+		res->mem_resource[i].flags = IORESOURCE_MEM;  // Also clears _UNSET flag
+		if (len <= 0) {
+			res->mem_resource[i].flags |= IORESOURCE_DISABLED;
+			return;
+		}
+		res->mem_resource[i].start = (unsigned long) mem;
+		res->mem_resource[i].end = (unsigned long)(mem + len - 1);
+	}
+}
+
+
+static acpi_status acpi_pnp_allocated_resource(struct acpi_resource *res, void *data)
+{
+	struct pnp_resource_table * res_table = (struct pnp_resource_table *)data;
+	//printk("res id %x\n",res->id);
+
+	switch (res->id) {
+	case ACPI_RSTYPE_IRQ:
+		if (res->data.irq.number_of_interrupts > 0)
+			pnpacpi_parse_allocated_irqresource(res_table, 
+				/* is it ok ?
+				 * produce IOAPIC[0]: Invalid reference to IRQ 0
+				 */
+				acpi_register_gsi(res->data.irq.interrupts[0],
+					res->data.irq.edge_level,
+					res->data.irq.active_high_low));
+		break;
+
+	case ACPI_RSTYPE_EXT_IRQ:
+		if (res->data.extended_irq.number_of_interrupts > 0)
+			pnpacpi_parse_allocated_irqresource(res_table, 
+				acpi_register_gsi(res->data.extended_irq.interrupts[0],
+					res->data.extended_irq.edge_level,
+					res->data.extended_irq.active_high_low));
+		break;
+	case ACPI_RSTYPE_DMA:
+		if (res->data.dma.number_of_channels > 0)
+			pnpacpi_parse_allocated_dmaresource(res_table, 
+					res->data.dma.channels[0]);
+		break;
+	case ACPI_RSTYPE_IO:
+		pnpacpi_parse_allocated_ioresource(res_table, 
+				res->data.io.min_base_address, 
+				res->data.io.range_length);
+		break;
+	case ACPI_RSTYPE_FIXED_IO:
+		pnpacpi_parse_allocated_ioresource(res_table, 
+				res->data.fixed_io.base_address, 
+				res->data.fixed_io.range_length);
+		break;
+	case ACPI_RSTYPE_MEM24:
+		pnpacpi_parse_allocated_memresource(res_table, 
+				res->data.memory24.min_base_address, 
+				res->data.memory24.range_length);
+		break;
+	case ACPI_RSTYPE_MEM32:
+		pnpacpi_parse_allocated_memresource(res_table, 
+				res->data.memory32.min_base_address, 
+				res->data.memory32.range_length);
+		break;
+	case ACPI_RSTYPE_FIXED_MEM32:
+		pnpacpi_parse_allocated_memresource(res_table, 
+				res->data.fixed_memory32.range_base_address, 
+				res->data.fixed_memory32.range_length);
+		break;
+#if 0
+	case ACPI_RSTYPE_ADDRESS16:
+		pnpacpi_parse_allocated_memresource(res_table, 
+				res->data.address16.min_address_range, 
+				res->data.address16.address_length);
+		break;
+	case ACPI_RSTYPE_ADDRESS32:
+		pnpacpi_parse_allocated_memresource(res_table, 
+				res->data.address32.min_address_range, 
+				res->data.address32.address_length);
+		break;
+	/*
+	case ACPI_RSTYPE_ADDRESS64:
+		pnpacpi_parse_allocated_memresource(res_table, 
+		res->data.address64.min_address_range, 
+		res->data.address64.address_length);
+		break;
+	*/
+#endif
+	default:
+		printk(KERN_WARNING "PnPACPI: Alloc type : %d not handle\n", 
+				res->id);
+	}
+			
+	return AE_OK;
+}
+
+static acpi_status acpi_pnp_parse_allocated_resource(struct acpi_device *device, struct pnp_resource_table * res)
+{
+	/* Blank the resource table values */
+	pnp_init_resource_table(res);
+
+	return acpi_walk_resources(device->handle, METHOD_NAME__CRS, acpi_pnp_allocated_resource, res);
+}
+
+
+static void pnpacpi_parse_dma_option(struct pnp_option *option, struct acpi_resource_dma *p)
+{
+	int i;
+	struct pnp_dma * dma;
+	dma = pnpacpi_kmalloc(sizeof(struct pnp_dma), GFP_KERNEL);
+	if (!dma)
+		return;
+
+	for(i=0; i<p->number_of_channels; i++)
+		dma->map |= 1<<p->channels[i];
+	dma->flags = 0;
+	if (p->bus_master)
+		dma->flags |= IORESOURCE_DMA_MASTER;
+	switch (p->type) {
+	case ACPI_COMPATIBILITY:
+		dma->flags |= IORESOURCE_DMA_COMPATIBLE;
+		break;
+	case ACPI_TYPE_A:
+		dma->flags |= IORESOURCE_DMA_TYPEA;
+		break;
+	case ACPI_TYPE_B:
+		dma->flags |= IORESOURCE_DMA_TYPEB;
+		break;
+	case ACPI_TYPE_F:
+		dma->flags |= IORESOURCE_DMA_TYPEF;
+		break;
+	}
+	switch (p->transfer) {
+	case ACPI_TRANSFER_8:
+		dma->flags |= IORESOURCE_DMA_8BIT;
+		break;
+	case ACPI_TRANSFER_8_16:
+		dma->flags |= IORESOURCE_DMA_8AND16BIT;
+		break;
+	case ACPI_TRANSFER_16:
+		dma->flags |= IORESOURCE_DMA_16BIT;
+		break;
+	}
+
+
+	pnp_register_dma_resource(option,dma);
+	return;
+}
+
+static int irq_flags(int edge_level, int active_high_low)
+{
+	int flag;
+	if (edge_level == ACPI_LEVEL_SENSITIVE) {
+		if(active_high_low == ACPI_ACTIVE_LOW)
+			flag = IORESOURCE_IRQ_LOWLEVEL;
+		else
+			flag = IORESOURCE_IRQ_HIGHLEVEL;
+	}
+	else {
+		if(active_high_low == ACPI_ACTIVE_LOW)
+			flag = IORESOURCE_IRQ_LOWEDGE;
+		else
+			flag = IORESOURCE_IRQ_HIGHEDGE;
+	}
+	return flag;
+}
+	
+static void pnpacpi_parse_irq_option(struct pnp_option *option, struct acpi_resource_irq *p)
+{
+	int i;
+	struct pnp_irq * irq;
+	irq = pnpacpi_kmalloc(sizeof(struct pnp_irq), GFP_KERNEL);
+	if (!irq)
+		return;
+
+	for(i=0; i<p->number_of_interrupts; i++)
+		irq->map |= 1<<p->interrupts[i];
+	irq->flags = irq_flags(p->edge_level, p->active_high_low);
+
+	pnp_register_irq_resource(option,irq);
+	return;
+}
+
+static void pnpacpi_parse_ext_irq_option(struct pnp_option *option, struct acpi_resource_ext_irq *p)
+{
+	int i;
+	struct pnp_irq * irq;
+	irq = pnpacpi_kmalloc(sizeof(struct pnp_irq), GFP_KERNEL);
+	if (!irq)
+		return;
+
+	for(i=0; i<p->number_of_interrupts; i++)
+		irq->map |= 1<<p->interrupts[i];
+	irq->flags = irq_flags(p->edge_level, p->active_high_low);
+
+	pnp_register_irq_resource(option,irq);
+	return;
+}
+
+static void
+pnpacpi_parse_port_option(struct pnp_option *option, struct acpi_resource_io *io)
+{
+	struct pnp_port * port;
+	port = pnpacpi_kmalloc(sizeof(struct pnp_port), GFP_KERNEL);
+	if (!port)
+		return;
+	port->min = io->min_base_address;
+	port->max = io->max_base_address;
+	port->align = io->alignment;
+	port->size = io->range_length;
+	port->flags = ACPI_DECODE_16 == io->io_decode ? PNP_PORT_FLAG_16BITADDR : 0;
+	pnp_register_port_resource(option,port);
+	return;
+}
+
+static void
+pnpacpi_parse_fixed_port_option(struct pnp_option *option, struct acpi_resource_fixed_io *io)
+{
+	struct pnp_port * port;
+	port = pnpacpi_kmalloc(sizeof(struct pnp_port), GFP_KERNEL);
+	if (!port)
+		return;
+	port->min = port->max = io->base_address;
+	port->size = io->range_length;
+	port->align = 0;
+	port->flags = PNP_PORT_FLAG_FIXED;
+	pnp_register_port_resource(option,port);
+	return;
+}
+
+static void
+pnpacpi_parse_mem24_option(struct pnp_option *option, struct acpi_resource_mem24 *p)
+{
+	struct pnp_mem * mem;
+	mem = pnpacpi_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+	if (!mem)
+		return;
+	mem->min = p->min_base_address;
+	mem->max = p->max_base_address;
+	mem->align = p->alignment;
+	mem->size = p->range_length;
+
+	mem->flags = ACPI_READ_WRITE_MEMORY == p->read_write_attribute ?
+			IORESOURCE_MEM_WRITEABLE : 0;
+
+	pnp_register_mem_resource(option,mem);
+	return;
+}
+
+static void
+pnpacpi_parse_mem32_option(struct pnp_option *option, struct acpi_resource_mem32 *p)
+{
+	struct pnp_mem * mem;
+	mem = pnpacpi_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+	if (!mem)
+		return;
+	mem->min = p->min_base_address;
+	mem->max = p->max_base_address;
+	mem->align = p->alignment;
+	mem->size = p->range_length;
+
+	mem->flags = ACPI_READ_WRITE_MEMORY == p->read_write_attribute ?
+			IORESOURCE_MEM_WRITEABLE : 0;
+
+	pnp_register_mem_resource(option,mem);
+	return;
+}
+
+static void
+pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, struct acpi_resource_fixed_mem32 *p)
+{
+	struct pnp_mem * mem;
+	mem = pnpacpi_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL);
+	if (!mem)
+		return;
+	mem->min = mem->max = p->range_base_address;
+	mem->size = p->range_length;
+	mem->align = 0;
+
+	mem->flags = ACPI_READ_WRITE_MEMORY == p->read_write_attribute ?
+			IORESOURCE_MEM_WRITEABLE : 0;
+
+	pnp_register_mem_resource(option,mem);
+	return;
+}
+
+//XXX
+static struct pnp_option *option, *option_independent;
+
+static acpi_status acpi_pnp_option_resource(struct acpi_resource *res, void *data)
+{
+	int priority = 0;
+	struct pnp_dev *dev = (struct pnp_dev *)data;
+	//printk("pos res id %x\n",res->id);
+
+	switch (res->id) {
+		case ACPI_RSTYPE_IRQ:
+			pnpacpi_parse_irq_option(option, &res->data.irq);
+		break;
+		case ACPI_RSTYPE_EXT_IRQ:
+			pnpacpi_parse_ext_irq_option(option, &res->data.extended_irq);
+		break;
+		case ACPI_RSTYPE_DMA:
+			pnpacpi_parse_dma_option(option, &res->data.dma);
+						
+		break;
+		case ACPI_RSTYPE_IO:
+			pnpacpi_parse_port_option(option, &res->data.io);
+			break;
+		case ACPI_RSTYPE_FIXED_IO:
+			pnpacpi_parse_fixed_port_option(option, &res->data.fixed_io);
+			break;
+		case ACPI_RSTYPE_MEM24:
+			pnpacpi_parse_mem24_option(option, &res->data.memory24);
+			break;
+		case ACPI_RSTYPE_MEM32:
+			pnpacpi_parse_mem32_option(option, &res->data.memory32);
+			break;
+		case ACPI_RSTYPE_FIXED_MEM32:
+			pnpacpi_parse_fixed_mem32_option(option, &res->data.fixed_memory32);
+			break;
+		case ACPI_RSTYPE_START_DPF:
+			switch (res->data.start_dpf.compatibility_priority) {
+				case ACPI_GOOD_CONFIGURATION:
+					priority = PNP_RES_PRIORITY_PREFERRED;
+					break;
+					
+				case ACPI_ACCEPTABLE_CONFIGURATION:
+					priority = PNP_RES_PRIORITY_ACCEPTABLE;
+					break;
+
+				case ACPI_SUB_OPTIMAL_CONFIGURATION:
+					priority = PNP_RES_PRIORITY_FUNCTIONAL;
+					break;
+				default:
+					priority = PNP_RES_PRIORITY_INVALID;
+					break;
+			}
+			option = pnp_register_dependent_option(dev, priority);
+			if (!option)
+				return -1;
+			break;
+		case ACPI_RSTYPE_END_DPF:
+			if (option_independent == option)
+				printk(KERN_WARNING "PnPACPI: Missing SMALL_TAG_STARTDEP tag\n");
+			option = option_independent;
+			break;
+		default:
+			printk(KERN_WARNING "PnPACPI: Option type : %d not handle\n", res->id);
+	}
+			
+	return AE_OK;
+}
+
+static int pnpacpi_get_resources(struct pnp_dev * dev, struct pnp_resource_table * res)
+{
+
+	acpi_status status;
+	status = acpi_pnp_parse_allocated_resource(self[dev->number], &dev->res);
+	return ACPI_FAILURE(status)?-ENODEV:0;
+}
+
+static int pnpacpi_set_resources(struct pnp_dev * dev, struct pnp_resource_table * res)
+{
+	printk(KERN_WARNING "PnPACPI: Not implemented\n");
+	return -ENODEV;
+}
+
+static int pnpacpi_disable_resources(struct pnp_dev *dev)
+{
+	printk(KERN_WARNING "PnPACPI: Not implemented\n");
+	return -ENODEV;
+}
+
+struct pnp_protocol pnpacpi_protocol = {
+	.name	= "Plug and Play ACPI",
+	.get	= pnpacpi_get_resources,
+	.set	= pnpacpi_set_resources,
+	.disable = pnpacpi_disable_resources,
+};
+
+static int acpi_pnp_add_device(struct acpi_device *device)
+{
+	acpi_status status;
+	struct pnp_id *dev_id;
+	char id[8];
+	struct pnp_dev *dev;
+
+	static int num = 0;
+
+	if(num>=MAX_DEVICE)
+		return -ENODEV;
+
+	if (strlen(acpi_device_hid(device)) != 7) {
+		//printk("device : hid %s %d\n", id, strlen(id));
+		return -1;
+	}
+	
+	//printk("device : hid %s \n", acpi_device_hid(device));
+	dev =  pnpacpi_kmalloc(sizeof(struct pnp_dev), GFP_KERNEL);
+	if (!dev)
+		return -1;
+
+	dev->number = num++;
+	self[dev->number] = device;
+	strncpy(dev->name ,device->pnp.bus_id, PNP_NAME_LEN);
+
+
+	/* set the initial values for the PnP device */
+	dev_id = pnpacpi_kmalloc(sizeof(struct pnp_id), GFP_KERNEL);
+	if (!dev_id)
+		goto err;
+	pnpidacpi_to_pnpid(acpi_device_hid(device),id);
+	memcpy(dev_id->id,id,7);
+
+	pnp_add_id(dev_id, dev);
+	//parse allocated resource
+	status = acpi_pnp_parse_allocated_resource(device, &dev->res);
+	if (ACPI_FAILURE(status)) {
+		//printk(KERN_DEBUG "METHOD_NAME__CRS faillure\n");
+		dev->active = 0;
+		//return -EIO;
+	}
+	else
+		dev->active = 1;
+
+	option_independent = option = pnp_register_independent_option(dev);
+	if (!option)
+		goto err;
+	status = acpi_walk_resources(device->handle, METHOD_NAME__PRS, acpi_pnp_option_resource, dev);
+	/*if (ACPI_FAILURE(status))
+		printk(KERN_DEBUG "METHOD_NAME__PRS faillure\n");
+		//return -EIO;
+	*/
+
+	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++) {
+			dev_id = pnpacpi_kmalloc(sizeof(struct pnp_id), GFP_KERNEL);
+			if (!dev_id)
+				continue;
+
+			memcpy(dev_id->id,cid_list->id[i].value,7);
+			pnp_add_id(dev_id, dev);
+		}
+	}
+
+#if 0
+	dev->flags = node->flags;
+	if (!(dev->flags & PNPBIOS_NO_CONFIG))
+		dev->capabilities |= PNP_CONFIGURABLE;
+	if (!(dev->flags & PNPBIOS_NO_DISABLE))
+		dev->capabilities |= PNP_DISABLE;
+	dev->capabilities |= PNP_READ;
+	if (pnpacpi_is_dynamic(dev))
+		dev->capabilities |= PNP_WRITE;
+	if (dev->flags & PNPBIOS_REMOVABLE)
+		dev->capabilities |= PNP_REMOVABLE;
+#endif
+
+	dev->protocol = &pnpacpi_protocol;
+
+	/* clear out the damaged flags */
+	if (!dev->active)
+		pnp_init_resource_table(&dev->res);
+	pnp_add_device(dev);
+	return 0;
+
+err:
+	kfree(dev);
+	return -1;
+}
+
+static void acpi_pnp_add_device_handler(struct acpi_device *device)
+{
+	acpi_pnp_add_device(device);
+}
+
+//XXX put in a header file...
+extern int acpi_driver_scan(void (* handler)(struct acpi_device * dev));
+
+int __init pnpacpi_init(void)
+{
+	printk(KERN_INFO "PnP ACPI init\n");
+	pnp_register_protocol(&pnpacpi_protocol);
+	return acpi_driver_scan(acpi_pnp_add_device_handler);
+}
+device_initcall(pnpacpi_init);
+
+EXPORT_SYMBOL(pnpacpi_protocol);
diff -ruN --exclude='*.cmd' --exclude='*.o' --exclude='*.ko' linux.old/drivers/pnp/pnpacpi/Kconfig linux-2.6.9/drivers/pnp/pnpacpi/Kconfig
--- linux.old/drivers/pnp/pnpacpi/Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.9/drivers/pnp/pnpacpi/Kconfig	2004-09-04 14:11:36.000000000 +0200
@@ -0,0 +1,10 @@
+#
+# Plug and Play ACPI configuration
+#
+config PNPACPI
+	bool "Plug and Play ACPI support (EXPERIMENTAL)"
+	depends on PNP && X86 && ACPI_BUS && EXPERIMENTAL
+	depends on !PNPBIOS
+	default y
+	---help---
+	Todo
diff -ruN --exclude='*.cmd' --exclude='*.o' --exclude='*.ko' linux.old/drivers/pnp/pnpacpi/Makefile linux-2.6.9/drivers/pnp/pnpacpi/Makefile
--- linux.old/drivers/pnp/pnpacpi/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.9/drivers/pnp/pnpacpi/Makefile	2004-09-04 14:37:53.000000000 +0200
@@ -0,0 +1,5 @@
+#
+# Makefile for the kernel PNPACPI driver.
+#
+
+obj-y := core.o
diff -ruN --exclude='*.cmd' --exclude='*.o' --exclude='*.ko' linux.old/drivers/pnp/pnpbios/Kconfig linux-2.6.9/drivers/pnp/pnpbios/Kconfig
--- linux.old/drivers/pnp/pnpbios/Kconfig	2004-06-16 07:19:44.000000000 +0200
+++ linux-2.6.9/drivers/pnp/pnpbios/Kconfig	2004-09-04 14:11:31.000000000 +0200
@@ -4,6 +4,8 @@
 config PNPBIOS
 	bool "Plug and Play BIOS support (EXPERIMENTAL)"
 	depends on PNP && X86 && EXPERIMENTAL
+	depends on !PNPACPI
+	default n
 	---help---
 	  Linux uses the PNPBIOS as defined in "Plug and Play BIOS
 	  Specification Version 1.0A May 5, 1994" to autodetect built-in

^ permalink raw reply	[flat|nested] 6+ messages in thread
* RE: [RFC/patch] ACPI in linux PnP layer
@ 2004-09-09  2:57 Li, Shaohua
  0 siblings, 0 replies; 6+ messages in thread
From: Li, Shaohua @ 2004-09-09  2:57 UTC (permalink / raw)
  To: castet.matthieu-GANU6spQydw,
	acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
  Cc: Brown, Len

Hi Matthieu,
Great work! We are eager for this staff for a long time. I have some
generic comments for your patches.

On Wednesday, September 08, 2004, castet.matthieu-GANU6spQydw@public.gmane.org wrote:
>Hi,
>
>I have started to plug acpi in PnP layer.
>A first patch add the function acpi_driver_scan, that allow to call a
>function
>for each acpi device.
>I have to do that because acpi is load before PnP, and it can't add my
>function
>in acpi_bus_add (driver/acpi/scan.c).
This possible is not required. We can use 'acpi_walk_namespace' and
'acpi_bus_get_device' to reach the same goal.

>The second patch is the PnP acpi driver.
>It parse possible and activated resources.
>It use acpi_register_gsi to activate irq (is that need ???)
Your patch just checked the PNP id length to verify if it's a PNP
device. This isn't sufficient, such as ACPI EC device has PNP id
'PNP0C09', but ACPI core should control it instead of PNP.

>Also there are no disable/set acpi resource support, nor ADDRESS
resource
>support.
You can _CRS, _SRS and other ACPI methods for disable/set acpi resource
support.
Thanks your patches. We are glad to work with you to make it available.

Thanks,
Shaohua


-------------------------------------------------------
This SF.Net email is sponsored by BEA Weblogic Workshop
FREE Java Enterprise J2EE developer tools!
Get your free copy of BEA WebLogic Workshop 8.1 today.
http://ads.osdn.com/?ad_idP47&alloc_id\x10808&op=click

^ permalink raw reply	[flat|nested] 6+ messages in thread
[parent not found: <16A54BF5D6E14E4D916CE26C9AD305752500E0@pdsmsx402.ccr.corp.intel.com>]
* RE: [RFC/patch] ACPI in linux PnP layer
@ 2004-09-27  3:33 Li, Shaohua
  0 siblings, 0 replies; 6+ messages in thread
From: Li, Shaohua @ 2004-09-27  3:33 UTC (permalink / raw)
  To: matthieu castet; +Cc: acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Brown, Len

>For 3, perhaps a cleaner solution could be interaction between pnpacpi
>and "acpi bus" :
>when an acpi driver register, it remove the PNP id it want from the PNP
>layer (fail if there are already a pnp driver that use the id).
>
>And for the drivers that register before (pci_link if I remember), a
>flags could be added somewhere in acpi_device structure that tell the
>device is already registered by a driver.
>
>This add also the advantage of removing conflict between driver that
use
>acpi and those that use pnp for the same device(for example 8250_acpi.c
>and 8250_pnp.c) even if duplicate will be removed.
For this problem, another idea is register a default ACPI driver for all
PNP devices. Sure the driver is only for REAL PNP devices. The
functionality of the driver is link the device to PNP layer. This way in
the initializing code of pnpacpi isn't required to walk ACPI namespace.
The more important is it's easy to support hotplug PNP devices (just
hotplug the ACPI device is needed, which I have matured methods.). How
about it? I will try the method after the ACPI '.match' method is
merged.

>
>On the previous patch I send to the ML, I only change
>dev->active = device->status.functional to dev->active =
>device->status.enabled that you have already done in your patch.
>
>I also add a check for the pnpids : instead of testing in the length is
>7, I ckeck it verify [@-Z][@-Z][@-Z][0-9A-F][0-9A-F][0-9A-F][0-9A-F]\0
>regexp
>
>For that I modify pnpidacpi_to_pnpid
>
>
>+/*
>+ * 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 pnpidacpi_to_pnpid(char *id, char *str)
>+{
>+	TEST_ALPHA(id[0]);
>+	str[0] = id[0];
>+	TEST_ALPHA(id[1]);
>+	str[1] = id[1];
>+	TEST_ALPHA(id[2]);
>+	str[2] = id[2];
>+	TEST_HEX(id[3]);
>+	str[3] = tolower(id[3]);
>+	TEST_HEX(id[4]);
>+	str[4] = tolower(id[4]);
>+	TEST_HEX(id[5]);
>+	str[5] = tolower(id[5]);
>+	TEST_HEX(id[6]);
>+	str[6] = tolower(id[6]);
>+	if (id[7] != '\0')
>+		return 0;
>+	str[7] = '\0';
>+
>+	return 1;
>+}
>
>and in pnpacpi_add_device
>
>+       if ((strlen(acpi_device_hid(device)) != 7) ||
>+               is_exclusive_device(device))
>+               return 0;
>+
>+       pnpidacpi_to_pnpid(acpi_device_hid(device), id);
>become
>+       if ((!pnpidacpi_to_pnpid(acpi_device_hid(device), id)) ||
>+               is_exclusive_device(device))
>+               return 0;
>+
Nice, will add it soon, or you can add it in the patch.

Thanks,
Shaohua


-------------------------------------------------------
This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170
Project Admins to receive an Apple iPod Mini FREE for your judgement on
who ports your project to Linux PPC the best. Sponsored by IBM.
Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2004-09-27  3:33 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-09-08 11:00 [RFC/patch] ACPI in linux PnP layer castet.matthieu-GANU6spQydw
     [not found] ` <1094641221.413ee645d2cb6-/A4Sof3AOA+ksujEA26zIQ@public.gmane.org>
2004-09-08 15:48   ` castet.matthieu-GANU6spQydw
2004-09-09  4:26   ` Dmitry Torokhov
  -- strict thread matches above, loose matches on Subject: below --
2004-09-09  2:57 Li, Shaohua
     [not found] <16A54BF5D6E14E4D916CE26C9AD305752500E0@pdsmsx402.ccr.corp.intel.com>
     [not found] ` <16A54BF5D6E14E4D916CE26C9AD305752500E0-4yWAQGcml66iAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2004-09-26 18:17   ` matthieu castet
2004-09-27  3:33 Li, Shaohua

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox