11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pnpacpi -- PnP ACPI driver
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr>
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 2004 Li Shaohua <shaohua.li@intel.com>
640ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
740ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas *	Bjorn Helgaas <bjorn.helgaas@hp.com>
850eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore *
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify it
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * under the terms of the GNU General Public License as published by the
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Free Software Foundation; either version 2, or (at your option) any
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * later version.
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, but
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * WITHOUT ANY WARRANTY; without even the implied warranty of
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * General Public License for more details.
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/acpi.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
2602d83b5da3efa3c278ce87db2637f3dd6837166dBjorn Helgaas#include <linux/pnp.h>
275a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
2802d83b5da3efa3c278ce87db2637f3dd6837166dBjorn Helgaas#include "../base.h"
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "pnpacpi.h"
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_IA64
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define valid_IRQ(i) (1)
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define valid_IRQ(i) (((i) != 0) && ((i) != 2))
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Allocated Resources
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
40cd7ec927d9cd3d2001cbbdce872bd73f6e49c986Bjorn Helgaasstatic int irq_flags(int triggering, int polarity, int shareable)
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
42cd7ec927d9cd3d2001cbbdce872bd73f6e49c986Bjorn Helgaas	int flags;
43cd7ec927d9cd3d2001cbbdce872bd73f6e49c986Bjorn Helgaas
4450eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	if (triggering == ACPI_LEVEL_SENSITIVE) {
451c6e7d0aeecac38e66b1bb63e3eff07b2a1c2f2cBjorn Helgaas		if (polarity == ACPI_ACTIVE_LOW)
46cd7ec927d9cd3d2001cbbdce872bd73f6e49c986Bjorn Helgaas			flags = IORESOURCE_IRQ_LOWLEVEL;
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
48cd7ec927d9cd3d2001cbbdce872bd73f6e49c986Bjorn Helgaas			flags = IORESOURCE_IRQ_HIGHLEVEL;
499dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	} else {
501c6e7d0aeecac38e66b1bb63e3eff07b2a1c2f2cBjorn Helgaas		if (polarity == ACPI_ACTIVE_LOW)
51cd7ec927d9cd3d2001cbbdce872bd73f6e49c986Bjorn Helgaas			flags = IORESOURCE_IRQ_LOWEDGE;
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
53cd7ec927d9cd3d2001cbbdce872bd73f6e49c986Bjorn Helgaas			flags = IORESOURCE_IRQ_HIGHEDGE;
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
55cd7ec927d9cd3d2001cbbdce872bd73f6e49c986Bjorn Helgaas
56a993273beae8022390e48fe9205480565ad470abBjorn Helgaas	if (shareable == ACPI_SHARED)
57cd7ec927d9cd3d2001cbbdce872bd73f6e49c986Bjorn Helgaas		flags |= IORESOURCE_IRQ_SHAREABLE;
58cd7ec927d9cd3d2001cbbdce872bd73f6e49c986Bjorn Helgaas
59cd7ec927d9cd3d2001cbbdce872bd73f6e49c986Bjorn Helgaas	return flags;
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
62e9fe9e188118a0a34c6200d9b10ea6247f53592dBjorn Helgaasstatic void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering,
63a993273beae8022390e48fe9205480565ad470abBjorn Helgaas			     int *polarity, int *shareable)
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
65e9fe9e188118a0a34c6200d9b10ea6247f53592dBjorn Helgaas	switch (flags & (IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_HIGHLEVEL |
66e9fe9e188118a0a34c6200d9b10ea6247f53592dBjorn Helgaas			 IORESOURCE_IRQ_LOWEDGE  | IORESOURCE_IRQ_HIGHEDGE)) {
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IORESOURCE_IRQ_LOWLEVEL:
6850eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore		*triggering = ACPI_LEVEL_SENSITIVE;
6950eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore		*polarity = ACPI_ACTIVE_LOW;
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
711c6e7d0aeecac38e66b1bb63e3eff07b2a1c2f2cBjorn Helgaas	case IORESOURCE_IRQ_HIGHLEVEL:
7250eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore		*triggering = ACPI_LEVEL_SENSITIVE;
7350eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore		*polarity = ACPI_ACTIVE_HIGH;
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IORESOURCE_IRQ_LOWEDGE:
7650eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore		*triggering = ACPI_EDGE_SENSITIVE;
7750eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore		*polarity = ACPI_ACTIVE_LOW;
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IORESOURCE_IRQ_HIGHEDGE:
8050eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore		*triggering = ACPI_EDGE_SENSITIVE;
8150eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore		*polarity = ACPI_ACTIVE_HIGH;
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
83e9fe9e188118a0a34c6200d9b10ea6247f53592dBjorn Helgaas	default:
84e9fe9e188118a0a34c6200d9b10ea6247f53592dBjorn Helgaas		dev_err(&dev->dev, "can't encode invalid IRQ mode %#x\n",
85e9fe9e188118a0a34c6200d9b10ea6247f53592dBjorn Helgaas			flags);
86e9fe9e188118a0a34c6200d9b10ea6247f53592dBjorn Helgaas		*triggering = ACPI_EDGE_SENSITIVE;
87e9fe9e188118a0a34c6200d9b10ea6247f53592dBjorn Helgaas		*polarity = ACPI_ACTIVE_HIGH;
88e9fe9e188118a0a34c6200d9b10ea6247f53592dBjorn Helgaas		break;
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
90a993273beae8022390e48fe9205480565ad470abBjorn Helgaas
91a993273beae8022390e48fe9205480565ad470abBjorn Helgaas	if (flags & IORESOURCE_IRQ_SHAREABLE)
92a993273beae8022390e48fe9205480565ad470abBjorn Helgaas		*shareable = ACPI_SHARED;
93a993273beae8022390e48fe9205480565ad470abBjorn Helgaas	else
94a993273beae8022390e48fe9205480565ad470abBjorn Helgaas		*shareable = ACPI_EXCLUSIVE;
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
974ab55d8d4f7b910c4c60e0f8ff70d0dfdd484f02Bjorn Helgaasstatic void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
9807d4e9af109221ab731c5aaf832e89776c64b013Bjorn Helgaas						u32 gsi, int triggering,
9907d4e9af109221ab731c5aaf832e89776c64b013Bjorn Helgaas						int polarity, int shareable)
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
101dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas	int irq, flags;
10261fd47e0c84764f49b4e52bfd8170fac52636f00Shaohua Li	int p, t;
103dbed12da5bb06b15c63930e9282b45daea566d7bBjorn Helgaas
1045acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas	if (!valid_IRQ(gsi)) {
1055acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas		pnp_add_irq_resource(dev, gsi, IORESOURCE_DISABLED);
106dbed12da5bb06b15c63930e9282b45daea566d7bBjorn Helgaas		return;
1075acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas	}
108dbed12da5bb06b15c63930e9282b45daea566d7bBjorn Helgaas
10961fd47e0c84764f49b4e52bfd8170fac52636f00Shaohua Li	/*
11061fd47e0c84764f49b4e52bfd8170fac52636f00Shaohua Li	 * in IO-APIC mode, use overrided attribute. Two reasons:
11161fd47e0c84764f49b4e52bfd8170fac52636f00Shaohua Li	 * 1. BIOS bug in DSDT
11261fd47e0c84764f49b4e52bfd8170fac52636f00Shaohua Li	 * 2. BIOS uses IO-APIC mode Interrupt Source Override
11361fd47e0c84764f49b4e52bfd8170fac52636f00Shaohua Li	 */
11461fd47e0c84764f49b4e52bfd8170fac52636f00Shaohua Li	if (!acpi_get_override_irq(gsi, &t, &p)) {
11561fd47e0c84764f49b4e52bfd8170fac52636f00Shaohua Li		t = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
11661fd47e0c84764f49b4e52bfd8170fac52636f00Shaohua Li		p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
11761fd47e0c84764f49b4e52bfd8170fac52636f00Shaohua Li
11861fd47e0c84764f49b4e52bfd8170fac52636f00Shaohua Li		if (triggering != t || polarity != p) {
119af11cb2d521f9d7e10c565bafe8f2358772baa65Bjorn Helgaas			dev_warn(&dev->dev, "IRQ %d override to %s, %s\n",
12061fd47e0c84764f49b4e52bfd8170fac52636f00Shaohua Li				gsi, t ? "edge":"level", p ? "low":"high");
12161fd47e0c84764f49b4e52bfd8170fac52636f00Shaohua Li			triggering = t;
12261fd47e0c84764f49b4e52bfd8170fac52636f00Shaohua Li			polarity = p;
12361fd47e0c84764f49b4e52bfd8170fac52636f00Shaohua Li		}
12461fd47e0c84764f49b4e52bfd8170fac52636f00Shaohua Li	}
12561fd47e0c84764f49b4e52bfd8170fac52636f00Shaohua Li
126dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas	flags = irq_flags(triggering, polarity, shareable);
127a2f809b08ae4dddc1015c7dcd8659e5729e45b3eYinghai Lu	irq = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
128dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas	if (irq >= 0)
129dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas		pcibios_penalize_isa_irq(irq, 1);
130dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas	else
131dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas		flags |= IORESOURCE_DISABLED;
132dbed12da5bb06b15c63930e9282b45daea566d7bBjorn Helgaas
133dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas	pnp_add_irq_resource(dev, irq, flags);
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
136958a1fdd3904b009c926cb840be48ce3c5f2389eBjorn Helgaasstatic int dma_flags(struct pnp_dev *dev, int type, int bus_master,
137958a1fdd3904b009c926cb840be48ce3c5f2389eBjorn Helgaas		     int transfer)
138362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher{
139362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher	int flags = 0;
140362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher
141362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher	if (bus_master)
142362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher		flags |= IORESOURCE_DMA_MASTER;
143362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher	switch (type) {
144362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher	case ACPI_COMPATIBILITY:
145362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher		flags |= IORESOURCE_DMA_COMPATIBLE;
146362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher		break;
147362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher	case ACPI_TYPE_A:
148362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher		flags |= IORESOURCE_DMA_TYPEA;
149362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher		break;
150362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher	case ACPI_TYPE_B:
151362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher		flags |= IORESOURCE_DMA_TYPEB;
152362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher		break;
153362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher	case ACPI_TYPE_F:
154362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher		flags |= IORESOURCE_DMA_TYPEF;
155362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher		break;
156362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher	default:
157362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher		/* Set a default value ? */
158362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher		flags |= IORESOURCE_DMA_COMPATIBLE;
159958a1fdd3904b009c926cb840be48ce3c5f2389eBjorn Helgaas		dev_err(&dev->dev, "invalid DMA type %d\n", type);
160362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher	}
161362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher	switch (transfer) {
162362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher	case ACPI_TRANSFER_8:
163362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher		flags |= IORESOURCE_DMA_8BIT;
164362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher		break;
165362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher	case ACPI_TRANSFER_8_16:
166362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher		flags |= IORESOURCE_DMA_8AND16BIT;
167362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher		break;
168362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher	case ACPI_TRANSFER_16:
169362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher		flags |= IORESOURCE_DMA_16BIT;
170362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher		break;
171362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher	default:
172362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher		/* Set a default value ? */
173362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher		flags |= IORESOURCE_DMA_8AND16BIT;
174958a1fdd3904b009c926cb840be48ce3c5f2389eBjorn Helgaas		dev_err(&dev->dev, "invalid DMA transfer type %d\n", transfer);
175362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher	}
176362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher
177362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher	return flags;
178362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher}
179362ea087db9d99bb0cf79479544dfafa9e18c300Michael Karcher
180cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaasstatic void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start,
181fa35b49260b615d634bfa1f767aa315fa323c2e9Bjorn Helgaas					       u64 len, int io_decode,
182fa35b49260b615d634bfa1f767aa315fa323c2e9Bjorn Helgaas					       int window)
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
184cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas	int flags = 0;
185cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas	u64 end = start + len - 1;
18607d4e9af109221ab731c5aaf832e89776c64b013Bjorn Helgaas
187cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas	if (io_decode == ACPI_DECODE_16)
18808c9f262f268f7948be13bf3a5bda1d635c649b4Bjorn Helgaas		flags |= IORESOURCE_IO_16BIT_ADDR;
189cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas	if (len == 0 || end >= 0x10003)
190cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas		flags |= IORESOURCE_DISABLED;
191fa35b49260b615d634bfa1f767aa315fa323c2e9Bjorn Helgaas	if (window)
192fa35b49260b615d634bfa1f767aa315fa323c2e9Bjorn Helgaas		flags |= IORESOURCE_WINDOW;
193cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas
194cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas	pnp_add_io_resource(dev, start, end, flags);
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19740ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas/*
19840ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas * Device CSRs that do not appear in PCI config space should be described
19940ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas * via ACPI.  This would normally be done with Address Space Descriptors
20040ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas * marked as "consumer-only," but old versions of Windows and Linux ignore
20140ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas * the producer/consumer flag, so HP invented a vendor-defined resource to
20240ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas * describe the location and size of CSR space.
20340ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas */
20440ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaasstatic struct acpi_vendor_uuid hp_ccsr_uuid = {
20540ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas	.subtype = 2,
20640ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas	.data = { 0xf9, 0xad, 0xe9, 0x69, 0x4f, 0x92, 0x5f, 0xab, 0xf6, 0x4a,
20740ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas	    0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad },
20840ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas};
20940ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas
21040ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaasstatic int vendor_resource_matches(struct pnp_dev *dev,
21140ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas				   struct acpi_resource_vendor_typed *vendor,
21240ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas				   struct acpi_vendor_uuid *match,
21340ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas				   int expected_len)
21440ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas{
21540ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas	int uuid_len = sizeof(vendor->uuid);
21640ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas	u8 uuid_subtype = vendor->uuid_subtype;
21740ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas	u8 *uuid = vendor->uuid;
21840ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas	int actual_len;
21940ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas
22040ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas	/* byte_length includes uuid_subtype and uuid */
22140ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas	actual_len = vendor->byte_length - uuid_len - 1;
22240ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas
22340ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas	if (uuid_subtype == match->subtype &&
22440ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas	    uuid_len == sizeof(match->data) &&
22540ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas	    memcmp(uuid, match->data, uuid_len) == 0) {
22640ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas		if (expected_len && expected_len != actual_len) {
22740ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas			dev_err(&dev->dev, "wrong vendor descriptor size; "
22840ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas				"expected %d, found %d bytes\n",
22940ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas				expected_len, actual_len);
23040ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas			return 0;
23140ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas		}
23240ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas
23340ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas		return 1;
23440ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas	}
23540ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas
23640ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas	return 0;
23740ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas}
23840ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas
23940ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaasstatic void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev,
24040ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas				    struct acpi_resource_vendor_typed *vendor)
24140ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas{
24240ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas	if (vendor_resource_matches(dev, vendor, &hp_ccsr_uuid, 16)) {
24340ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas		u64 start, length;
24440ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas
24540ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas		memcpy(&start, vendor->byte_data, sizeof(start));
24640ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas		memcpy(&length, vendor->byte_data + 8, sizeof(length));
24740ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas
24840ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas		pnp_add_mem_resource(dev, start, start + length - 1, 0);
24940ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas	}
25040ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas}
25140ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas
2524ab55d8d4f7b910c4c60e0f8ff70d0dfdd484f02Bjorn Helgaasstatic void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
253d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas						u64 start, u64 len,
254fa35b49260b615d634bfa1f767aa315fa323c2e9Bjorn Helgaas						int write_protect, int window)
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
256d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas	int flags = 0;
257d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas	u64 end = start + len - 1;
258d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas
259d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas	if (len == 0)
260d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas		flags |= IORESOURCE_DISABLED;
261d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas	if (write_protect == ACPI_READ_WRITE_MEMORY)
262d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas		flags |= IORESOURCE_MEM_WRITEABLE;
263fa35b49260b615d634bfa1f767aa315fa323c2e9Bjorn Helgaas	if (window)
264fa35b49260b615d634bfa1f767aa315fa323c2e9Bjorn Helgaas		flags |= IORESOURCE_WINDOW;
265d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas
266d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas	pnp_add_mem_resource(dev, start, end, flags);
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2697e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaasstatic void pnpacpi_parse_allocated_busresource(struct pnp_dev *dev,
2707e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas						u64 start, u64 len)
2717e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas{
2727e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas	u64 end = start + len - 1;
2737e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas
2747e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas	pnp_add_bus_resource(dev, start, end);
2757e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas}
2767e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas
2774ab55d8d4f7b910c4c60e0f8ff70d0dfdd484f02Bjorn Helgaasstatic void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
27807d4e9af109221ab731c5aaf832e89776c64b013Bjorn Helgaas						  struct acpi_resource *res)
2791acfb7f2b0d460ee86bdb25ad0679070ec8a5f0dBjorn Helgaas{
2801acfb7f2b0d460ee86bdb25ad0679070ec8a5f0dBjorn Helgaas	struct acpi_resource_address64 addr, *p = &addr;
2811acfb7f2b0d460ee86bdb25ad0679070ec8a5f0dBjorn Helgaas	acpi_status status;
282fa35b49260b615d634bfa1f767aa315fa323c2e9Bjorn Helgaas	int window;
2833162b6f0c5e1fcad372d64194fb3cb968941b428Bjorn Helgaas	u64 len;
2841acfb7f2b0d460ee86bdb25ad0679070ec8a5f0dBjorn Helgaas
2851acfb7f2b0d460ee86bdb25ad0679070ec8a5f0dBjorn Helgaas	status = acpi_resource_to_address64(res, p);
2861acfb7f2b0d460ee86bdb25ad0679070ec8a5f0dBjorn Helgaas	if (!ACPI_SUCCESS(status)) {
287af11cb2d521f9d7e10c565bafe8f2358772baa65Bjorn Helgaas		dev_warn(&dev->dev, "failed to convert resource type %d\n",
2889dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas			 res->type);
2891acfb7f2b0d460ee86bdb25ad0679070ec8a5f0dBjorn Helgaas		return;
2901acfb7f2b0d460ee86bdb25ad0679070ec8a5f0dBjorn Helgaas	}
2911acfb7f2b0d460ee86bdb25ad0679070ec8a5f0dBjorn Helgaas
292f238b414a74a13c3d62e31a08e81b585d750df74Bjorn Helgaas	/* Windows apparently computes length rather than using _LEN */
293f238b414a74a13c3d62e31a08e81b585d750df74Bjorn Helgaas	len = p->maximum - p->minimum + 1;
294fa35b49260b615d634bfa1f767aa315fa323c2e9Bjorn Helgaas	window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
2952b8de5f50e4a302b83ebcd5b0120621336d50bd6Matthieu CASTET
2961acfb7f2b0d460ee86bdb25ad0679070ec8a5f0dBjorn Helgaas	if (p->resource_type == ACPI_MEMORY_RANGE)
2973162b6f0c5e1fcad372d64194fb3cb968941b428Bjorn Helgaas		pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
298fa35b49260b615d634bfa1f767aa315fa323c2e9Bjorn Helgaas			p->info.mem.write_protect, window);
2991acfb7f2b0d460ee86bdb25ad0679070ec8a5f0dBjorn Helgaas	else if (p->resource_type == ACPI_IO_RANGE)
3003162b6f0c5e1fcad372d64194fb3cb968941b428Bjorn Helgaas		pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
30107d4e9af109221ab731c5aaf832e89776c64b013Bjorn Helgaas			p->granularity == 0xfff ? ACPI_DECODE_10 :
302fa35b49260b615d634bfa1f767aa315fa323c2e9Bjorn Helgaas				ACPI_DECODE_16, window);
3037e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas	else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
3043162b6f0c5e1fcad372d64194fb3cb968941b428Bjorn Helgaas		pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
3051acfb7f2b0d460ee86bdb25ad0679070ec8a5f0dBjorn Helgaas}
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3078cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaasstatic void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev,
3088cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas						      struct acpi_resource *res)
3098cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas{
3108cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas	struct acpi_resource_extended_address64 *p = &res->data.ext_address64;
311fa35b49260b615d634bfa1f767aa315fa323c2e9Bjorn Helgaas	int window;
3123162b6f0c5e1fcad372d64194fb3cb968941b428Bjorn Helgaas	u64 len;
3138cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas
314f238b414a74a13c3d62e31a08e81b585d750df74Bjorn Helgaas	/* Windows apparently computes length rather than using _LEN */
315f238b414a74a13c3d62e31a08e81b585d750df74Bjorn Helgaas	len = p->maximum - p->minimum + 1;
316fa35b49260b615d634bfa1f767aa315fa323c2e9Bjorn Helgaas	window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
3178cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas
3188cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas	if (p->resource_type == ACPI_MEMORY_RANGE)
3193162b6f0c5e1fcad372d64194fb3cb968941b428Bjorn Helgaas		pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
320fa35b49260b615d634bfa1f767aa315fa323c2e9Bjorn Helgaas			p->info.mem.write_protect, window);
3218cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas	else if (p->resource_type == ACPI_IO_RANGE)
3223162b6f0c5e1fcad372d64194fb3cb968941b428Bjorn Helgaas		pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
3238cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas			p->granularity == 0xfff ? ACPI_DECODE_10 :
324fa35b49260b615d634bfa1f767aa315fa323c2e9Bjorn Helgaas				ACPI_DECODE_16, window);
3257e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas	else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
3263162b6f0c5e1fcad372d64194fb3cb968941b428Bjorn Helgaas		pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
3278cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas}
3288cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
3309dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas					      void *data)
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3324ab55d8d4f7b910c4c60e0f8ff70d0dfdd484f02Bjorn Helgaas	struct pnp_dev *dev = data;
3339570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	struct acpi_resource_irq *irq;
3349570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	struct acpi_resource_dma *dma;
3359570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	struct acpi_resource_io *io;
3369570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	struct acpi_resource_fixed_io *fixed_io;
33740ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas	struct acpi_resource_vendor_typed *vendor_typed;
3389570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	struct acpi_resource_memory24 *memory24;
3399570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	struct acpi_resource_memory32 *memory32;
3409570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	struct acpi_resource_fixed_memory32 *fixed_memory32;
3419570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	struct acpi_resource_extended_irq *extended_irq;
342dc16f5f2ede8cc2acf8ac22857a7fecf3a4296c2Bjorn Helgaas	int i, flags;
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
344eca008c8134df15262a0362623edb59902628c95Len Brown	switch (res->type) {
34550eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	case ACPI_RESOURCE_TYPE_IRQ:
346dbed12da5bb06b15c63930e9282b45daea566d7bBjorn Helgaas		/*
347dbed12da5bb06b15c63930e9282b45daea566d7bBjorn Helgaas		 * Per spec, only one interrupt per descriptor is allowed in
348dbed12da5bb06b15c63930e9282b45daea566d7bBjorn Helgaas		 * _CRS, but some firmware violates this, so parse them all.
349dbed12da5bb06b15c63930e9282b45daea566d7bBjorn Helgaas		 */
3509570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas		irq = &res->data.irq;
3515acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas		if (irq->interrupt_count == 0)
3525acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas			pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
3535acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas		else {
3545acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas			for (i = 0; i < irq->interrupt_count; i++) {
3555acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas				pnpacpi_parse_allocated_irqresource(dev,
3565acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas					irq->interrupts[i],
3575acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas					irq->triggering,
3585acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas					irq->polarity,
3595acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas				    irq->sharable);
3605acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas			}
3615acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas
3625acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas			/*
3635acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas			 * The IRQ encoder puts a single interrupt in each
3645acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas			 * descriptor, so if a _CRS descriptor has more than
3655acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas			 * one interrupt, we won't be able to re-encode it.
3665acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas			 */
3675acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas			if (pnp_can_write(dev) && irq->interrupt_count > 1) {
3685acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas				dev_warn(&dev->dev, "multiple interrupts in "
3695acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas					 "_CRS descriptor; configuration can't "
3705acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas					 "be changed\n");
3715acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas				dev->capabilities &= ~PNP_WRITE;
3725acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas			}
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37650eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	case ACPI_RESOURCE_TYPE_DMA:
3779570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas		dma = &res->data.dma;
3785acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas		if (dma->channel_count > 0 && dma->channels[0] != (u8) -1)
379958a1fdd3904b009c926cb840be48ce3c5f2389eBjorn Helgaas			flags = dma_flags(dev, dma->type, dma->bus_master,
380dc16f5f2ede8cc2acf8ac22857a7fecf3a4296c2Bjorn Helgaas					  dma->transfer);
3815acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas		else
3825acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas			flags = IORESOURCE_DISABLED;
3835acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas		pnp_add_dma_resource(dev, dma->channels[0], flags);
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3850af5853bccd263161df80c259d61fc71211c5ac3Len Brown
38650eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	case ACPI_RESOURCE_TYPE_IO:
3879570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas		io = &res->data.io;
3884ab55d8d4f7b910c4c60e0f8ff70d0dfdd484f02Bjorn Helgaas		pnpacpi_parse_allocated_ioresource(dev,
3899570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas			io->minimum,
3909570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas			io->address_length,
391fa35b49260b615d634bfa1f767aa315fa323c2e9Bjorn Helgaas			io->io_decode, 0);
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
3930af5853bccd263161df80c259d61fc71211c5ac3Len Brown
3940af5853bccd263161df80c259d61fc71211c5ac3Len Brown	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
3950af5853bccd263161df80c259d61fc71211c5ac3Len Brown	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
3960af5853bccd263161df80c259d61fc71211c5ac3Len Brown		break;
3970af5853bccd263161df80c259d61fc71211c5ac3Len Brown
39850eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	case ACPI_RESOURCE_TYPE_FIXED_IO:
3999570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas		fixed_io = &res->data.fixed_io;
4004ab55d8d4f7b910c4c60e0f8ff70d0dfdd484f02Bjorn Helgaas		pnpacpi_parse_allocated_ioresource(dev,
4019570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas			fixed_io->address,
4029570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas			fixed_io->address_length,
403fa35b49260b615d634bfa1f767aa315fa323c2e9Bjorn Helgaas			ACPI_DECODE_10, 0);
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
4050af5853bccd263161df80c259d61fc71211c5ac3Len Brown
4060af5853bccd263161df80c259d61fc71211c5ac3Len Brown	case ACPI_RESOURCE_TYPE_VENDOR:
40740ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas		vendor_typed = &res->data.vendor_typed;
40840ab4f4c1d843362eb26d83425317e91fbd98b17Bjorn Helgaas		pnpacpi_parse_allocated_vendor(dev, vendor_typed);
4090af5853bccd263161df80c259d61fc71211c5ac3Len Brown		break;
4100af5853bccd263161df80c259d61fc71211c5ac3Len Brown
4110af5853bccd263161df80c259d61fc71211c5ac3Len Brown	case ACPI_RESOURCE_TYPE_END_TAG:
4120af5853bccd263161df80c259d61fc71211c5ac3Len Brown		break;
4130af5853bccd263161df80c259d61fc71211c5ac3Len Brown
41450eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	case ACPI_RESOURCE_TYPE_MEMORY24:
4159570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas		memory24 = &res->data.memory24;
4164ab55d8d4f7b910c4c60e0f8ff70d0dfdd484f02Bjorn Helgaas		pnpacpi_parse_allocated_memresource(dev,
4179570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas			memory24->minimum,
4189570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas			memory24->address_length,
419fa35b49260b615d634bfa1f767aa315fa323c2e9Bjorn Helgaas			memory24->write_protect, 0);
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
42150eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	case ACPI_RESOURCE_TYPE_MEMORY32:
4229570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas		memory32 = &res->data.memory32;
4234ab55d8d4f7b910c4c60e0f8ff70d0dfdd484f02Bjorn Helgaas		pnpacpi_parse_allocated_memresource(dev,
4249570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas			memory32->minimum,
4259570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas			memory32->address_length,
426fa35b49260b615d634bfa1f767aa315fa323c2e9Bjorn Helgaas			memory32->write_protect, 0);
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
42850eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
4299570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas		fixed_memory32 = &res->data.fixed_memory32;
4304ab55d8d4f7b910c4c60e0f8ff70d0dfdd484f02Bjorn Helgaas		pnpacpi_parse_allocated_memresource(dev,
4319570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas			fixed_memory32->address,
4329570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas			fixed_memory32->address_length,
433fa35b49260b615d634bfa1f767aa315fa323c2e9Bjorn Helgaas			fixed_memory32->write_protect, 0);
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
43550eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	case ACPI_RESOURCE_TYPE_ADDRESS16:
43650eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	case ACPI_RESOURCE_TYPE_ADDRESS32:
43750eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	case ACPI_RESOURCE_TYPE_ADDRESS64:
4384ab55d8d4f7b910c4c60e0f8ff70d0dfdd484f02Bjorn Helgaas		pnpacpi_parse_allocated_address_space(dev, res);
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
4400af5853bccd263161df80c259d61fc71211c5ac3Len Brown
4410af5853bccd263161df80c259d61fc71211c5ac3Len Brown	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
4428cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas		pnpacpi_parse_allocated_ext_address_space(dev, res);
4430af5853bccd263161df80c259d61fc71211c5ac3Len Brown		break;
4440af5853bccd263161df80c259d61fc71211c5ac3Len Brown
4450af5853bccd263161df80c259d61fc71211c5ac3Len Brown	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
4469570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas		extended_irq = &res->data.extended_irq;
4472b8de5f50e4a302b83ebcd5b0120621336d50bd6Matthieu CASTET
4485acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas		if (extended_irq->interrupt_count == 0)
4495acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas			pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
4505acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas		else {
4515acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas			for (i = 0; i < extended_irq->interrupt_count; i++) {
4525acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas				pnpacpi_parse_allocated_irqresource(dev,
4535acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas					extended_irq->interrupts[i],
4545acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas					extended_irq->triggering,
4555acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas					extended_irq->polarity,
4565acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas					extended_irq->sharable);
4575acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas			}
4585acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas
4595acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas			/*
4605acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas			 * The IRQ encoder puts a single interrupt in each
4615acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas			 * descriptor, so if a _CRS descriptor has more than
4625acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas			 * one interrupt, we won't be able to re-encode it.
4635acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas			 */
4645acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas			if (pnp_can_write(dev) &&
4655acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas			    extended_irq->interrupt_count > 1) {
4665acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas				dev_warn(&dev->dev, "multiple interrupts in "
4675acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas					 "_CRS descriptor; configuration can't "
4685acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas					 "be changed\n");
4695acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas				dev->capabilities &= ~PNP_WRITE;
4705acf91415799025410cc0d13101340d352f34c89Bjorn Helgaas			}
4710af5853bccd263161df80c259d61fc71211c5ac3Len Brown		}
4720af5853bccd263161df80c259d61fc71211c5ac3Len Brown		break;
4730af5853bccd263161df80c259d61fc71211c5ac3Len Brown
4740af5853bccd263161df80c259d61fc71211c5ac3Len Brown	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
4760af5853bccd263161df80c259d61fc71211c5ac3Len Brown
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
478af11cb2d521f9d7e10c565bafe8f2358772baa65Bjorn Helgaas		dev_warn(&dev->dev, "unknown resource type %d in _CRS\n",
479af11cb2d521f9d7e10c565bafe8f2358772baa65Bjorn Helgaas			 res->type);
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return AE_ERROR;
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4821c6e7d0aeecac38e66b1bb63e3eff07b2a1c2f2cBjorn Helgaas
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return AE_OK;
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
486d152cf5d0c3325979e71ee53b425fdd51a1a285aBjorn Helgaasint pnpacpi_parse_allocated_resource(struct pnp_dev *dev)
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
488c4da6940a7a41c72781ff2d62ebd4b99f3749f14Bjorn Helgaas	struct acpi_device *acpi_dev = dev->data;
489c4da6940a7a41c72781ff2d62ebd4b99f3749f14Bjorn Helgaas	acpi_handle handle = acpi_dev->handle;
490d152cf5d0c3325979e71ee53b425fdd51a1a285aBjorn Helgaas	acpi_status status;
4914ab55d8d4f7b910c4c60e0f8ff70d0dfdd484f02Bjorn Helgaas
4922f53432c2aedbe79020e44525eb069d9138a01ddBjorn Helgaas	pnp_dbg(&dev->dev, "parse allocated resources\n");
49372dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas
494f44900020926b2cb06b87f0f52643d6285514fc3Bjorn Helgaas	pnp_init_resources(dev);
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
496d152cf5d0c3325979e71ee53b425fdd51a1a285aBjorn Helgaas	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
497d152cf5d0c3325979e71ee53b425fdd51a1a285aBjorn Helgaas				     pnpacpi_allocated_resource, dev);
498d152cf5d0c3325979e71ee53b425fdd51a1a285aBjorn Helgaas
499d152cf5d0c3325979e71ee53b425fdd51a1a285aBjorn Helgaas	if (ACPI_FAILURE(status)) {
500d152cf5d0c3325979e71ee53b425fdd51a1a285aBjorn Helgaas		if (status != AE_NOT_FOUND)
501d152cf5d0c3325979e71ee53b425fdd51a1a285aBjorn Helgaas			dev_err(&dev->dev, "can't evaluate _CRS: %d", status);
502d152cf5d0c3325979e71ee53b425fdd51a1a285aBjorn Helgaas		return -EPERM;
503d152cf5d0c3325979e71ee53b425fdd51a1a285aBjorn Helgaas	}
504d152cf5d0c3325979e71ee53b425fdd51a1a285aBjorn Helgaas	return 0;
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
507c1caf06ccfd3a4efd4b489f89bcdabd2362f31d0Bjorn Helgaasstatic __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
5081f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas					    unsigned int option_flags,
5092bb9a6b32f98873adf89a0de04c898681a2c5b8eThomas Renninger					    struct acpi_resource_dma *p)
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
51218fd470a48396c8795ba7256c5973e92ffa25cb3Witold Szczeponik	unsigned char map = 0, flags;
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5149dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	for (i = 0; i < p->channel_count; i++)
515c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas		map |= 1 << p->channels[i];
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51718fd470a48396c8795ba7256c5973e92ffa25cb3Witold Szczeponik	flags = dma_flags(dev, p->type, p->bus_master, p->transfer);
5181f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	pnp_register_dma_resource(dev, option_flags, map, flags);
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
521c1caf06ccfd3a4efd4b489f89bcdabd2362f31d0Bjorn Helgaasstatic __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
5221f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas					    unsigned int option_flags,
5232bb9a6b32f98873adf89a0de04c898681a2c5b8eThomas Renninger					    struct acpi_resource_irq *p)
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
526c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas	pnp_irq_mask_t map;
52718fd470a48396c8795ba7256c5973e92ffa25cb3Witold Szczeponik	unsigned char flags;
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
529c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas	bitmap_zero(map.bits, PNP_IRQ_NR);
5309dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	for (i = 0; i < p->interrupt_count; i++)
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (p->interrupts[i])
532c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas			__set_bit(p->interrupts[i], map.bits);
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53418fd470a48396c8795ba7256c5973e92ffa25cb3Witold Szczeponik	flags = irq_flags(p->triggering, p->polarity, p->sharable);
5351f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	pnp_register_irq_resource(dev, option_flags, &map, flags);
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
538c1caf06ccfd3a4efd4b489f89bcdabd2362f31d0Bjorn Helgaasstatic __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
5391f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas					unsigned int option_flags,
5402bb9a6b32f98873adf89a0de04c898681a2c5b8eThomas Renninger					struct acpi_resource_extended_irq *p)
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
543c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas	pnp_irq_mask_t map;
54418fd470a48396c8795ba7256c5973e92ffa25cb3Witold Szczeponik	unsigned char flags;
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
546c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas	bitmap_zero(map.bits, PNP_IRQ_NR);
547fe2cf598e6942abd8fb70fee230d74b1a1eae0d1Bjorn Helgaas	for (i = 0; i < p->interrupt_count; i++) {
548fe2cf598e6942abd8fb70fee230d74b1a1eae0d1Bjorn Helgaas		if (p->interrupts[i]) {
549fe2cf598e6942abd8fb70fee230d74b1a1eae0d1Bjorn Helgaas			if (p->interrupts[i] < PNP_IRQ_NR)
550fe2cf598e6942abd8fb70fee230d74b1a1eae0d1Bjorn Helgaas				__set_bit(p->interrupts[i], map.bits);
551fe2cf598e6942abd8fb70fee230d74b1a1eae0d1Bjorn Helgaas			else
552fe2cf598e6942abd8fb70fee230d74b1a1eae0d1Bjorn Helgaas				dev_err(&dev->dev, "ignoring IRQ %d option "
553fe2cf598e6942abd8fb70fee230d74b1a1eae0d1Bjorn Helgaas					"(too large for %d entry bitmap)\n",
554fe2cf598e6942abd8fb70fee230d74b1a1eae0d1Bjorn Helgaas					p->interrupts[i], PNP_IRQ_NR);
555fe2cf598e6942abd8fb70fee230d74b1a1eae0d1Bjorn Helgaas		}
556fe2cf598e6942abd8fb70fee230d74b1a1eae0d1Bjorn Helgaas	}
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55818fd470a48396c8795ba7256c5973e92ffa25cb3Witold Szczeponik	flags = irq_flags(p->triggering, p->polarity, p->sharable);
5591f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	pnp_register_irq_resource(dev, option_flags, &map, flags);
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
562c1caf06ccfd3a4efd4b489f89bcdabd2362f31d0Bjorn Helgaasstatic __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
5631f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas					     unsigned int option_flags,
5642bb9a6b32f98873adf89a0de04c898681a2c5b8eThomas Renninger					     struct acpi_resource_io *io)
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
566c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas	unsigned char flags = 0;
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
568c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas	if (io->io_decode == ACPI_DECODE_16)
56918fd470a48396c8795ba7256c5973e92ffa25cb3Witold Szczeponik		flags = IORESOURCE_IO_16BIT_ADDR;
5701f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	pnp_register_port_resource(dev, option_flags, io->minimum, io->maximum,
571c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas				   io->alignment, io->address_length, flags);
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
574c1caf06ccfd3a4efd4b489f89bcdabd2362f31d0Bjorn Helgaasstatic __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
5751f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas					unsigned int option_flags,
5762bb9a6b32f98873adf89a0de04c898681a2c5b8eThomas Renninger					struct acpi_resource_fixed_io *io)
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5781f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	pnp_register_port_resource(dev, option_flags, io->address, io->address,
57918fd470a48396c8795ba7256c5973e92ffa25cb3Witold Szczeponik				   0, io->address_length, IORESOURCE_IO_FIXED);
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
582c1caf06ccfd3a4efd4b489f89bcdabd2362f31d0Bjorn Helgaasstatic __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
5831f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas					      unsigned int option_flags,
5842bb9a6b32f98873adf89a0de04c898681a2c5b8eThomas Renninger					      struct acpi_resource_memory24 *p)
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
586c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas	unsigned char flags = 0;
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
588c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas	if (p->write_protect == ACPI_READ_WRITE_MEMORY)
58918fd470a48396c8795ba7256c5973e92ffa25cb3Witold Szczeponik		flags = IORESOURCE_MEM_WRITEABLE;
5901f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
591c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas				  p->alignment, p->address_length, flags);
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
594c1caf06ccfd3a4efd4b489f89bcdabd2362f31d0Bjorn Helgaasstatic __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
5951f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas					      unsigned int option_flags,
5962bb9a6b32f98873adf89a0de04c898681a2c5b8eThomas Renninger					      struct acpi_resource_memory32 *p)
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
598c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas	unsigned char flags = 0;
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
600c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas	if (p->write_protect == ACPI_READ_WRITE_MEMORY)
60118fd470a48396c8795ba7256c5973e92ffa25cb3Witold Szczeponik		flags = IORESOURCE_MEM_WRITEABLE;
6021f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
603c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas				  p->alignment, p->address_length, flags);
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
606c1caf06ccfd3a4efd4b489f89bcdabd2362f31d0Bjorn Helgaasstatic __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
6071f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas					unsigned int option_flags,
6082bb9a6b32f98873adf89a0de04c898681a2c5b8eThomas Renninger					struct acpi_resource_fixed_memory32 *p)
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
610c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas	unsigned char flags = 0;
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
612c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas	if (p->write_protect == ACPI_READ_WRITE_MEMORY)
61318fd470a48396c8795ba7256c5973e92ffa25cb3Witold Szczeponik		flags = IORESOURCE_MEM_WRITEABLE;
6141f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	pnp_register_mem_resource(dev, option_flags, p->address, p->address,
615c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas				  0, p->address_length, flags);
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
618c1caf06ccfd3a4efd4b489f89bcdabd2362f31d0Bjorn Helgaasstatic __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
6191f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas						unsigned int option_flags,
6202bb9a6b32f98873adf89a0de04c898681a2c5b8eThomas Renninger						struct acpi_resource *r)
6216f957eaf79356a32e838f5f262ee9a60544b1d5bBjorn Helgaas{
6226f957eaf79356a32e838f5f262ee9a60544b1d5bBjorn Helgaas	struct acpi_resource_address64 addr, *p = &addr;
6236f957eaf79356a32e838f5f262ee9a60544b1d5bBjorn Helgaas	acpi_status status;
624c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas	unsigned char flags = 0;
6256f957eaf79356a32e838f5f262ee9a60544b1d5bBjorn Helgaas
6266f957eaf79356a32e838f5f262ee9a60544b1d5bBjorn Helgaas	status = acpi_resource_to_address64(r, p);
627958a1fdd3904b009c926cb840be48ce3c5f2389eBjorn Helgaas	if (ACPI_FAILURE(status)) {
628958a1fdd3904b009c926cb840be48ce3c5f2389eBjorn Helgaas		dev_warn(&dev->dev, "can't convert resource type %d\n",
6299dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas			 r->type);
6306f957eaf79356a32e838f5f262ee9a60544b1d5bBjorn Helgaas		return;
6316f957eaf79356a32e838f5f262ee9a60544b1d5bBjorn Helgaas	}
6326f957eaf79356a32e838f5f262ee9a60544b1d5bBjorn Helgaas
6336f957eaf79356a32e838f5f262ee9a60544b1d5bBjorn Helgaas	if (p->resource_type == ACPI_MEMORY_RANGE) {
634c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas		if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
63518fd470a48396c8795ba7256c5973e92ffa25cb3Witold Szczeponik			flags = IORESOURCE_MEM_WRITEABLE;
6361f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas		pnp_register_mem_resource(dev, option_flags, p->minimum,
6371f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas					  p->minimum, 0, p->address_length,
6381f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas					  flags);
639c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas	} else if (p->resource_type == ACPI_IO_RANGE)
6401f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas		pnp_register_port_resource(dev, option_flags, p->minimum,
6411f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas					   p->minimum, 0, p->address_length,
64218fd470a48396c8795ba7256c5973e92ffa25cb3Witold Szczeponik					   IORESOURCE_IO_FIXED);
6436f957eaf79356a32e838f5f262ee9a60544b1d5bBjorn Helgaas}
6446f957eaf79356a32e838f5f262ee9a60544b1d5bBjorn Helgaas
6458cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaasstatic __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev,
6468cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas						    unsigned int option_flags,
6478cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas						    struct acpi_resource *r)
6488cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas{
6498cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas	struct acpi_resource_extended_address64 *p = &r->data.ext_address64;
6508cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas	unsigned char flags = 0;
6518cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas
6528cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas	if (p->resource_type == ACPI_MEMORY_RANGE) {
6538cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas		if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
65418fd470a48396c8795ba7256c5973e92ffa25cb3Witold Szczeponik			flags = IORESOURCE_MEM_WRITEABLE;
6558cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas		pnp_register_mem_resource(dev, option_flags, p->minimum,
6568cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas					  p->minimum, 0, p->address_length,
6578cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas					  flags);
6588cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas	} else if (p->resource_type == ACPI_IO_RANGE)
6598cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas		pnp_register_port_resource(dev, option_flags, p->minimum,
6608cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas					   p->minimum, 0, p->address_length,
66118fd470a48396c8795ba7256c5973e92ffa25cb3Witold Szczeponik					   IORESOURCE_IO_FIXED);
6628cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas}
6638cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct acpipnp_parse_option_s {
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pnp_dev *dev;
6661f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	unsigned int option_flags;
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6692bb9a6b32f98873adf89a0de04c898681a2c5b8eThomas Renningerstatic __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
6702bb9a6b32f98873adf89a0de04c898681a2c5b8eThomas Renninger						  void *data)
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
672e2a1a6f1cfaf6ee770a8700e5df8a3708dae503bBjorn Helgaas	int priority;
6734721a4cc8864f0eb92958c3e0479e7994e8b0072Bjorn Helgaas	struct acpipnp_parse_option_s *parse_data = data;
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pnp_dev *dev = parse_data->dev;
6751f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	unsigned int option_flags = parse_data->option_flags;
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
677eca008c8134df15262a0362623edb59902628c95Len Brown	switch (res->type) {
6789dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	case ACPI_RESOURCE_TYPE_IRQ:
6791f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas		pnpacpi_parse_irq_option(dev, option_flags, &res->data.irq);
6809dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		break;
6810af5853bccd263161df80c259d61fc71211c5ac3Len Brown
6829dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	case ACPI_RESOURCE_TYPE_DMA:
6831f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas		pnpacpi_parse_dma_option(dev, option_flags, &res->data.dma);
6849dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		break;
6850af5853bccd263161df80c259d61fc71211c5ac3Len Brown
6869dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
6879dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		switch (res->data.start_dpf.compatibility_priority) {
6889dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		case ACPI_GOOD_CONFIGURATION:
6899dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas			priority = PNP_RES_PRIORITY_PREFERRED;
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6910af5853bccd263161df80c259d61fc71211c5ac3Len Brown
6929dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		case ACPI_ACCEPTABLE_CONFIGURATION:
6939dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas			priority = PNP_RES_PRIORITY_ACCEPTABLE;
694b008b8d7092053fc1f036cfc54dc11740cc424edMatthieu CASTET			break;
6950af5853bccd263161df80c259d61fc71211c5ac3Len Brown
6969dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		case ACPI_SUB_OPTIMAL_CONFIGURATION:
6979dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas			priority = PNP_RES_PRIORITY_FUNCTIONAL;
6980af5853bccd263161df80c259d61fc71211c5ac3Len Brown			break;
6999dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		default:
7009dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas			priority = PNP_RES_PRIORITY_INVALID;
7010af5853bccd263161df80c259d61fc71211c5ac3Len Brown			break;
7029dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		}
7031f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas		parse_data->option_flags = pnp_new_dependent_set(dev, priority);
7049dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		break;
7050af5853bccd263161df80c259d61fc71211c5ac3Len Brown
7069dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
7071f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas		parse_data->option_flags = 0;
7089dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		break;
7090af5853bccd263161df80c259d61fc71211c5ac3Len Brown
7109dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	case ACPI_RESOURCE_TYPE_IO:
7111f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas		pnpacpi_parse_port_option(dev, option_flags, &res->data.io);
7129dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		break;
7130af5853bccd263161df80c259d61fc71211c5ac3Len Brown
7149dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	case ACPI_RESOURCE_TYPE_FIXED_IO:
7151f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas		pnpacpi_parse_fixed_port_option(dev, option_flags,
716c1caf06ccfd3a4efd4b489f89bcdabd2362f31d0Bjorn Helgaas					        &res->data.fixed_io);
7179dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		break;
7180af5853bccd263161df80c259d61fc71211c5ac3Len Brown
7199dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	case ACPI_RESOURCE_TYPE_VENDOR:
7209dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	case ACPI_RESOURCE_TYPE_END_TAG:
7219dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		break;
7220af5853bccd263161df80c259d61fc71211c5ac3Len Brown
7239dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	case ACPI_RESOURCE_TYPE_MEMORY24:
7241f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas		pnpacpi_parse_mem24_option(dev, option_flags,
7251f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas					   &res->data.memory24);
7269dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		break;
7270af5853bccd263161df80c259d61fc71211c5ac3Len Brown
7289dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	case ACPI_RESOURCE_TYPE_MEMORY32:
7291f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas		pnpacpi_parse_mem32_option(dev, option_flags,
7301f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas					   &res->data.memory32);
7319dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		break;
7320af5853bccd263161df80c259d61fc71211c5ac3Len Brown
7339dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
7341f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas		pnpacpi_parse_fixed_mem32_option(dev, option_flags,
7359dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas						 &res->data.fixed_memory32);
7369dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		break;
7370af5853bccd263161df80c259d61fc71211c5ac3Len Brown
7389dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	case ACPI_RESOURCE_TYPE_ADDRESS16:
7399dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	case ACPI_RESOURCE_TYPE_ADDRESS32:
7409dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	case ACPI_RESOURCE_TYPE_ADDRESS64:
7411f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas		pnpacpi_parse_address_option(dev, option_flags, res);
7429dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		break;
7430af5853bccd263161df80c259d61fc71211c5ac3Len Brown
7449dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
7458cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas		pnpacpi_parse_ext_address_option(dev, option_flags, res);
7469dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		break;
7479dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas
7489dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
7491f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas		pnpacpi_parse_ext_irq_option(dev, option_flags,
750c1caf06ccfd3a4efd4b489f89bcdabd2362f31d0Bjorn Helgaas					     &res->data.extended_irq);
7519dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		break;
7529dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas
7539dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
7549dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		break;
7559dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas
7569dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	default:
757af11cb2d521f9d7e10c565bafe8f2358772baa65Bjorn Helgaas		dev_warn(&dev->dev, "unknown resource type %d in _PRS\n",
758af11cb2d521f9d7e10c565bafe8f2358772baa65Bjorn Helgaas			 res->type);
7599dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		return AE_ERROR;
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7611c6e7d0aeecac38e66b1bb63e3eff07b2a1c2f2cBjorn Helgaas
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return AE_OK;
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
765d152cf5d0c3325979e71ee53b425fdd51a1a285aBjorn Helgaasint __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
767c4da6940a7a41c72781ff2d62ebd4b99f3749f14Bjorn Helgaas	struct acpi_device *acpi_dev = dev->data;
768c4da6940a7a41c72781ff2d62ebd4b99f3749f14Bjorn Helgaas	acpi_handle handle = acpi_dev->handle;
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_status status;
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct acpipnp_parse_option_s parse_data;
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7722f53432c2aedbe79020e44525eb069d9138a01ddBjorn Helgaas	pnp_dbg(&dev->dev, "parse resource options\n");
77372dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	parse_data.dev = dev;
7751f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	parse_data.option_flags = 0;
7761f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas
77750eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	status = acpi_walk_resources(handle, METHOD_NAME__PRS,
7789dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas				     pnpacpi_option_resource, &parse_data);
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
780d152cf5d0c3325979e71ee53b425fdd51a1a285aBjorn Helgaas	if (ACPI_FAILURE(status)) {
781d152cf5d0c3325979e71ee53b425fdd51a1a285aBjorn Helgaas		if (status != AE_NOT_FOUND)
782d152cf5d0c3325979e71ee53b425fdd51a1a285aBjorn Helgaas			dev_err(&dev->dev, "can't evaluate _PRS: %d", status);
783d152cf5d0c3325979e71ee53b425fdd51a1a285aBjorn Helgaas		return -EPERM;
784d152cf5d0c3325979e71ee53b425fdd51a1a285aBjorn Helgaas	}
785d152cf5d0c3325979e71ee53b425fdd51a1a285aBjorn Helgaas	return 0;
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
788b5f2490b6e3317059e87ba40d4f659d1c30afc1fBjorn Helgaasstatic int pnpacpi_supported_resource(struct acpi_resource *res)
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
790eca008c8134df15262a0362623edb59902628c95Len Brown	switch (res->type) {
79150eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	case ACPI_RESOURCE_TYPE_IRQ:
79250eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	case ACPI_RESOURCE_TYPE_DMA:
79350eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	case ACPI_RESOURCE_TYPE_IO:
79450eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	case ACPI_RESOURCE_TYPE_FIXED_IO:
79550eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	case ACPI_RESOURCE_TYPE_MEMORY24:
79650eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	case ACPI_RESOURCE_TYPE_MEMORY32:
79750eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
79850eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	case ACPI_RESOURCE_TYPE_ADDRESS16:
79950eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	case ACPI_RESOURCE_TYPE_ADDRESS32:
80050eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	case ACPI_RESOURCE_TYPE_ADDRESS64:
8018cb24c8fd70ea8431744de1ca0ca34ab45fbbdaaBjorn Helgaas	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
8020af5853bccd263161df80c259d61fc71211c5ac3Len Brown	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
803b5f2490b6e3317059e87ba40d4f659d1c30afc1fBjorn Helgaas		return 1;
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
805b5f2490b6e3317059e87ba40d4f659d1c30afc1fBjorn Helgaas	return 0;
806b5f2490b6e3317059e87ba40d4f659d1c30afc1fBjorn Helgaas}
807b5f2490b6e3317059e87ba40d4f659d1c30afc1fBjorn Helgaas
808b5f2490b6e3317059e87ba40d4f659d1c30afc1fBjorn Helgaas/*
809b5f2490b6e3317059e87ba40d4f659d1c30afc1fBjorn Helgaas * Set resource
810b5f2490b6e3317059e87ba40d4f659d1c30afc1fBjorn Helgaas */
811b5f2490b6e3317059e87ba40d4f659d1c30afc1fBjorn Helgaasstatic acpi_status pnpacpi_count_resources(struct acpi_resource *res,
8129dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas					   void *data)
813b5f2490b6e3317059e87ba40d4f659d1c30afc1fBjorn Helgaas{
8144721a4cc8864f0eb92958c3e0479e7994e8b0072Bjorn Helgaas	int *res_cnt = data;
815b5f2490b6e3317059e87ba40d4f659d1c30afc1fBjorn Helgaas
816b5f2490b6e3317059e87ba40d4f659d1c30afc1fBjorn Helgaas	if (pnpacpi_supported_resource(res))
817b5f2490b6e3317059e87ba40d4f659d1c30afc1fBjorn Helgaas		(*res_cnt)++;
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return AE_OK;
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8211c6e7d0aeecac38e66b1bb63e3eff07b2a1c2f2cBjorn Helgaasstatic acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data)
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8234721a4cc8864f0eb92958c3e0479e7994e8b0072Bjorn Helgaas	struct acpi_resource **resource = data;
824b5f2490b6e3317059e87ba40d4f659d1c30afc1fBjorn Helgaas
825b5f2490b6e3317059e87ba40d4f659d1c30afc1fBjorn Helgaas	if (pnpacpi_supported_resource(res)) {
826eca008c8134df15262a0362623edb59902628c95Len Brown		(*resource)->type = res->type;
827b5f2490b6e3317059e87ba40d4f659d1c30afc1fBjorn Helgaas		(*resource)->length = sizeof(struct acpi_resource);
82836d872a370d3d10e5a7faa9dcacce744260fb13bBjorn Helgaas		if (res->type == ACPI_RESOURCE_TYPE_IRQ)
82936d872a370d3d10e5a7faa9dcacce744260fb13bBjorn Helgaas			(*resource)->data.irq.descriptor_length =
83036d872a370d3d10e5a7faa9dcacce744260fb13bBjorn Helgaas					res->data.irq.descriptor_length;
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(*resource)++;
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return AE_OK;
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
837cdef6254e17e98f1071ce1bfc8f2a87997c855d0Bjorn Helgaasint pnpacpi_build_resource_template(struct pnp_dev *dev,
8389dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas				    struct acpi_buffer *buffer)
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
840c4da6940a7a41c72781ff2d62ebd4b99f3749f14Bjorn Helgaas	struct acpi_device *acpi_dev = dev->data;
841c4da6940a7a41c72781ff2d62ebd4b99f3749f14Bjorn Helgaas	acpi_handle handle = acpi_dev->handle;
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct acpi_resource *resource;
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int res_cnt = 0;
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	acpi_status status;
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
84650eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
8479dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas				     pnpacpi_count_resources, &res_cnt);
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ACPI_FAILURE(status)) {
849d152cf5d0c3325979e71ee53b425fdd51a1a285aBjorn Helgaas		dev_err(&dev->dev, "can't evaluate _CRS: %d\n", status);
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!res_cnt)
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1;
855cd86128088554d64fea1679191509f00e6353c5bRobert P. J. Day	buffer->pointer = kzalloc(buffer->length - 1, GFP_KERNEL);
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!buffer->pointer)
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
85872dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	resource = (struct acpi_resource *)buffer->pointer;
86050eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
8619dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas				     pnpacpi_type_resources, &resource);
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ACPI_FAILURE(status)) {
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(buffer->pointer);
864d152cf5d0c3325979e71ee53b425fdd51a1a285aBjorn Helgaas		dev_err(&dev->dev, "can't evaluate _CRS: %d\n", status);
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* resource will pointer the end resource now */
86850eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore	resource->type = ACPI_RESOURCE_TYPE_END_TAG;
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
87372dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaasstatic void pnpacpi_encode_irq(struct pnp_dev *dev,
87472dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas			       struct acpi_resource *resource,
8759dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas			       struct resource *p)
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8779570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	struct acpi_resource_irq *irq = &resource->data.irq;
878a993273beae8022390e48fe9205480565ad470abBjorn Helgaas	int triggering, polarity, shareable;
8791c6e7d0aeecac38e66b1bb63e3eff07b2a1c2f2cBjorn Helgaas
880aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	if (!pnp_resource_enabled(p)) {
881aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		irq->interrupt_count = 0;
8822f53432c2aedbe79020e44525eb069d9138a01ddBjorn Helgaas		pnp_dbg(&dev->dev, "  encode irq (%s)\n",
883aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas			p ? "disabled" : "missing");
884aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		return;
885aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	}
886aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas
887a993273beae8022390e48fe9205480565ad470abBjorn Helgaas	decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
8889570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	irq->triggering = triggering;
8899570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	irq->polarity = polarity;
890a993273beae8022390e48fe9205480565ad470abBjorn Helgaas	irq->sharable = shareable;
8919570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	irq->interrupt_count = 1;
8929570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	irq->interrupts[0] = p->start;
89372dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas
8942f53432c2aedbe79020e44525eb069d9138a01ddBjorn Helgaas	pnp_dbg(&dev->dev, "  encode irq %d %s %s %s (%d-byte descriptor)\n",
89536d872a370d3d10e5a7faa9dcacce744260fb13bBjorn Helgaas		(int) p->start,
89672dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas		triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
89772dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas		polarity == ACPI_ACTIVE_LOW ? "low" : "high",
89836d872a370d3d10e5a7faa9dcacce744260fb13bBjorn Helgaas		irq->sharable == ACPI_SHARED ? "shared" : "exclusive",
89936d872a370d3d10e5a7faa9dcacce744260fb13bBjorn Helgaas		irq->descriptor_length);
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
90272dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaasstatic void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
90372dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas				   struct acpi_resource *resource,
9049dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas				   struct resource *p)
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9069570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq;
907a993273beae8022390e48fe9205480565ad470abBjorn Helgaas	int triggering, polarity, shareable;
9081c6e7d0aeecac38e66b1bb63e3eff07b2a1c2f2cBjorn Helgaas
909aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	if (!pnp_resource_enabled(p)) {
910aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		extended_irq->interrupt_count = 0;
9112f53432c2aedbe79020e44525eb069d9138a01ddBjorn Helgaas		pnp_dbg(&dev->dev, "  encode extended irq (%s)\n",
912aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas			p ? "disabled" : "missing");
913aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		return;
914aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	}
915aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas
916a993273beae8022390e48fe9205480565ad470abBjorn Helgaas	decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
9179570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	extended_irq->producer_consumer = ACPI_CONSUMER;
9189570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	extended_irq->triggering = triggering;
9199570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	extended_irq->polarity = polarity;
920a993273beae8022390e48fe9205480565ad470abBjorn Helgaas	extended_irq->sharable = shareable;
9219570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	extended_irq->interrupt_count = 1;
9229570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	extended_irq->interrupts[0] = p->start;
92372dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas
9242f53432c2aedbe79020e44525eb069d9138a01ddBjorn Helgaas	pnp_dbg(&dev->dev, "  encode irq %d %s %s %s\n", (int) p->start,
92572dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas		triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
92672dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas		polarity == ACPI_ACTIVE_LOW ? "low" : "high",
92772dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas		extended_irq->sharable == ACPI_SHARED ? "shared" : "exclusive");
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
93072dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaasstatic void pnpacpi_encode_dma(struct pnp_dev *dev,
93172dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas			       struct acpi_resource *resource,
9329dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas			       struct resource *p)
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9349570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	struct acpi_resource_dma *dma = &resource->data.dma;
9359570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas
936aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	if (!pnp_resource_enabled(p)) {
937aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		dma->channel_count = 0;
9382f53432c2aedbe79020e44525eb069d9138a01ddBjorn Helgaas		pnp_dbg(&dev->dev, "  encode dma (%s)\n",
939aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas			p ? "disabled" : "missing");
940aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		return;
941aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	}
942aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
944ccc4c7bbd6a2d47bf5899c2c8cf2e0d176a4dc0fVojtech Pavlik	switch (p->flags & IORESOURCE_DMA_SPEED_MASK) {
9459dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	case IORESOURCE_DMA_TYPEA:
9469570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas		dma->type = ACPI_TYPE_A;
9479dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		break;
9489dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	case IORESOURCE_DMA_TYPEB:
9499570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas		dma->type = ACPI_TYPE_B;
9509dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		break;
9519dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	case IORESOURCE_DMA_TYPEF:
9529570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas		dma->type = ACPI_TYPE_F;
9539dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		break;
9549dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	default:
9559570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas		dma->type = ACPI_COMPATIBILITY;
956ccc4c7bbd6a2d47bf5899c2c8cf2e0d176a4dc0fVojtech Pavlik	}
957ccc4c7bbd6a2d47bf5899c2c8cf2e0d176a4dc0fVojtech Pavlik
958ccc4c7bbd6a2d47bf5899c2c8cf2e0d176a4dc0fVojtech Pavlik	switch (p->flags & IORESOURCE_DMA_TYPE_MASK) {
9599dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	case IORESOURCE_DMA_8BIT:
9609570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas		dma->transfer = ACPI_TRANSFER_8;
9619dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		break;
9629dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	case IORESOURCE_DMA_8AND16BIT:
9639570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas		dma->transfer = ACPI_TRANSFER_8_16;
9649dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		break;
9659dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	default:
9669570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas		dma->transfer = ACPI_TRANSFER_16;
967ccc4c7bbd6a2d47bf5899c2c8cf2e0d176a4dc0fVojtech Pavlik	}
968ccc4c7bbd6a2d47bf5899c2c8cf2e0d176a4dc0fVojtech Pavlik
9699570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	dma->bus_master = !!(p->flags & IORESOURCE_DMA_MASTER);
9709570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	dma->channel_count = 1;
9719570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	dma->channels[0] = p->start;
97272dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas
9732f53432c2aedbe79020e44525eb069d9138a01ddBjorn Helgaas	pnp_dbg(&dev->dev, "  encode dma %d "
97472dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas		"type %#x transfer %#x master %d\n",
97572dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas		(int) p->start, dma->type, dma->transfer, dma->bus_master);
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
97872dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaasstatic void pnpacpi_encode_io(struct pnp_dev *dev,
97972dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas			      struct acpi_resource *resource,
9809dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas			      struct resource *p)
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9829570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	struct acpi_resource_io *io = &resource->data.io;
9839570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas
984aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	if (pnp_resource_enabled(p)) {
985aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		/* Note: pnp_assign_port copies pnp_port->flags into p->flags */
98608c9f262f268f7948be13bf3a5bda1d635c649b4Bjorn Helgaas		io->io_decode = (p->flags & IORESOURCE_IO_16BIT_ADDR) ?
987aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		    ACPI_DECODE_16 : ACPI_DECODE_10;
988aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		io->minimum = p->start;
989aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		io->maximum = p->end;
990aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		io->alignment = 0;	/* Correct? */
99128f65c11f2ffb3957259dece647a24f8ad2e241bJoe Perches		io->address_length = resource_size(p);
992aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	} else {
993aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		io->minimum = 0;
994aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		io->address_length = 0;
995aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	}
99672dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas
9972f53432c2aedbe79020e44525eb069d9138a01ddBjorn Helgaas	pnp_dbg(&dev->dev, "  encode io %#x-%#x decode %#x\n", io->minimum,
998aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		io->minimum + io->address_length - 1, io->io_decode);
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
100172dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaasstatic void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
100272dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas				    struct acpi_resource *resource,
10039dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas				    struct resource *p)
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10059570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	struct acpi_resource_fixed_io *fixed_io = &resource->data.fixed_io;
10069570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas
1007aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	if (pnp_resource_enabled(p)) {
1008aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		fixed_io->address = p->start;
100928f65c11f2ffb3957259dece647a24f8ad2e241bJoe Perches		fixed_io->address_length = resource_size(p);
1010aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	} else {
1011aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		fixed_io->address = 0;
1012aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		fixed_io->address_length = 0;
1013aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	}
101472dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas
10152f53432c2aedbe79020e44525eb069d9138a01ddBjorn Helgaas	pnp_dbg(&dev->dev, "  encode fixed_io %#x-%#x\n", fixed_io->address,
1016aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		fixed_io->address + fixed_io->address_length - 1);
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
101972dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaasstatic void pnpacpi_encode_mem24(struct pnp_dev *dev,
102072dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas				 struct acpi_resource *resource,
10219dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas				 struct resource *p)
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10239570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	struct acpi_resource_memory24 *memory24 = &resource->data.memory24;
10249570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas
1025aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	if (pnp_resource_enabled(p)) {
1026aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		/* Note: pnp_assign_mem copies pnp_mem->flags into p->flags */
1027aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		memory24->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ?
1028aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
1029aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		memory24->minimum = p->start;
1030aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		memory24->maximum = p->end;
1031aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		memory24->alignment = 0;
103228f65c11f2ffb3957259dece647a24f8ad2e241bJoe Perches		memory24->address_length = resource_size(p);
1033aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	} else {
1034aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		memory24->minimum = 0;
1035aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		memory24->address_length = 0;
1036aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	}
1037aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas
10382f53432c2aedbe79020e44525eb069d9138a01ddBjorn Helgaas	pnp_dbg(&dev->dev, "  encode mem24 %#x-%#x write_protect %#x\n",
1039aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		memory24->minimum,
1040aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		memory24->minimum + memory24->address_length - 1,
104172dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas		memory24->write_protect);
10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
104472dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaasstatic void pnpacpi_encode_mem32(struct pnp_dev *dev,
104572dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas				 struct acpi_resource *resource,
10469dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas				 struct resource *p)
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10489570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	struct acpi_resource_memory32 *memory32 = &resource->data.memory32;
10499570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas
1050aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	if (pnp_resource_enabled(p)) {
1051aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		memory32->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ?
1052aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
1053aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		memory32->minimum = p->start;
1054aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		memory32->maximum = p->end;
1055aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		memory32->alignment = 0;
105628f65c11f2ffb3957259dece647a24f8ad2e241bJoe Perches		memory32->address_length = resource_size(p);
1057aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	} else {
1058aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		memory32->minimum = 0;
1059aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		memory32->alignment = 0;
1060aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	}
106172dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas
10622f53432c2aedbe79020e44525eb069d9138a01ddBjorn Helgaas	pnp_dbg(&dev->dev, "  encode mem32 %#x-%#x write_protect %#x\n",
1063aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		memory32->minimum,
1064aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		memory32->minimum + memory32->address_length - 1,
106572dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas		memory32->write_protect);
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
106872dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaasstatic void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev,
106972dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas				       struct acpi_resource *resource,
10709dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas				       struct resource *p)
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10729570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas	struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32;
10739570a20e9da282721afc6885dbeaa1b9c1e7ff4dBjorn Helgaas
1074aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	if (pnp_resource_enabled(p)) {
1075aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		fixed_memory32->write_protect =
1076aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		    p->flags & IORESOURCE_MEM_WRITEABLE ?
1077aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
1078aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		fixed_memory32->address = p->start;
107928f65c11f2ffb3957259dece647a24f8ad2e241bJoe Perches		fixed_memory32->address_length = resource_size(p);
1080aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	} else {
1081aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		fixed_memory32->address = 0;
1082aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		fixed_memory32->address_length = 0;
1083aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	}
108472dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas
10852f53432c2aedbe79020e44525eb069d9138a01ddBjorn Helgaas	pnp_dbg(&dev->dev, "  encode fixed_mem32 %#x-%#x write_protect %#x\n",
1086aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		fixed_memory32->address,
1087aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		fixed_memory32->address + fixed_memory32->address_length - 1,
108872dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas		fixed_memory32->write_protect);
10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10914ab55d8d4f7b910c4c60e0f8ff70d0dfdd484f02Bjorn Helgaasint pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer)
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = 0;
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* pnpacpi_build_resource_template allocates extra mem */
10959dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	int res_cnt = (buffer->length - 1) / sizeof(struct acpi_resource) - 1;
10964721a4cc8864f0eb92958c3e0479e7994e8b0072Bjorn Helgaas	struct acpi_resource *resource = buffer->pointer;
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int port = 0, irq = 0, dma = 0, mem = 0;
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10992f53432c2aedbe79020e44525eb069d9138a01ddBjorn Helgaas	pnp_dbg(&dev->dev, "encode %d resources\n", res_cnt);
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (i < res_cnt) {
11019dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		switch (resource->type) {
110250eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore		case ACPI_RESOURCE_TYPE_IRQ:
110372dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas			pnpacpi_encode_irq(dev, resource,
11047e2cf31f1c97ac14b6d9dc5f1ce9e1e01aef9c18Bjorn Helgaas			       pnp_get_resource(dev, IORESOURCE_IRQ, irq));
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			irq++;
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
110850eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore		case ACPI_RESOURCE_TYPE_DMA:
110972dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas			pnpacpi_encode_dma(dev, resource,
11107e2cf31f1c97ac14b6d9dc5f1ce9e1e01aef9c18Bjorn Helgaas				pnp_get_resource(dev, IORESOURCE_DMA, dma));
11111c6e7d0aeecac38e66b1bb63e3eff07b2a1c2f2cBjorn Helgaas			dma++;
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
111350eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore		case ACPI_RESOURCE_TYPE_IO:
111472dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas			pnpacpi_encode_io(dev, resource,
11157e2cf31f1c97ac14b6d9dc5f1ce9e1e01aef9c18Bjorn Helgaas				pnp_get_resource(dev, IORESOURCE_IO, port));
11161c6e7d0aeecac38e66b1bb63e3eff07b2a1c2f2cBjorn Helgaas			port++;
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
111850eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore		case ACPI_RESOURCE_TYPE_FIXED_IO:
111972dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas			pnpacpi_encode_fixed_io(dev, resource,
11207e2cf31f1c97ac14b6d9dc5f1ce9e1e01aef9c18Bjorn Helgaas				pnp_get_resource(dev, IORESOURCE_IO, port));
11211c6e7d0aeecac38e66b1bb63e3eff07b2a1c2f2cBjorn Helgaas			port++;
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
112350eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore		case ACPI_RESOURCE_TYPE_MEMORY24:
112472dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas			pnpacpi_encode_mem24(dev, resource,
11257e2cf31f1c97ac14b6d9dc5f1ce9e1e01aef9c18Bjorn Helgaas				pnp_get_resource(dev, IORESOURCE_MEM, mem));
11261c6e7d0aeecac38e66b1bb63e3eff07b2a1c2f2cBjorn Helgaas			mem++;
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
112850eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore		case ACPI_RESOURCE_TYPE_MEMORY32:
112972dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas			pnpacpi_encode_mem32(dev, resource,
11307e2cf31f1c97ac14b6d9dc5f1ce9e1e01aef9c18Bjorn Helgaas				pnp_get_resource(dev, IORESOURCE_MEM, mem));
11311c6e7d0aeecac38e66b1bb63e3eff07b2a1c2f2cBjorn Helgaas			mem++;
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
113350eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore		case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
113472dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas			pnpacpi_encode_fixed_mem32(dev, resource,
11357e2cf31f1c97ac14b6d9dc5f1ce9e1e01aef9c18Bjorn Helgaas				pnp_get_resource(dev, IORESOURCE_MEM, mem));
11361c6e7d0aeecac38e66b1bb63e3eff07b2a1c2f2cBjorn Helgaas			mem++;
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
11380af5853bccd263161df80c259d61fc71211c5ac3Len Brown		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
113972dcc883d8e5b59105e75ee5265442e458740575Bjorn Helgaas			pnpacpi_encode_ext_irq(dev, resource,
11407e2cf31f1c97ac14b6d9dc5f1ce9e1e01aef9c18Bjorn Helgaas				pnp_get_resource(dev, IORESOURCE_IRQ, irq));
11410af5853bccd263161df80c259d61fc71211c5ac3Len Brown			irq++;
11420af5853bccd263161df80c259d61fc71211c5ac3Len Brown			break;
11430af5853bccd263161df80c259d61fc71211c5ac3Len Brown		case ACPI_RESOURCE_TYPE_START_DEPENDENT:
11440af5853bccd263161df80c259d61fc71211c5ac3Len Brown		case ACPI_RESOURCE_TYPE_END_DEPENDENT:
11450af5853bccd263161df80c259d61fc71211c5ac3Len Brown		case ACPI_RESOURCE_TYPE_VENDOR:
11460af5853bccd263161df80c259d61fc71211c5ac3Len Brown		case ACPI_RESOURCE_TYPE_END_TAG:
11470af5853bccd263161df80c259d61fc71211c5ac3Len Brown		case ACPI_RESOURCE_TYPE_ADDRESS16:
11480af5853bccd263161df80c259d61fc71211c5ac3Len Brown		case ACPI_RESOURCE_TYPE_ADDRESS32:
11490af5853bccd263161df80c259d61fc71211c5ac3Len Brown		case ACPI_RESOURCE_TYPE_ADDRESS64:
11500af5853bccd263161df80c259d61fc71211c5ac3Len Brown		case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
11510af5853bccd263161df80c259d61fc71211c5ac3Len Brown		case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
11529dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		default:	/* other type */
1153af11cb2d521f9d7e10c565bafe8f2358772baa65Bjorn Helgaas			dev_warn(&dev->dev, "can't encode unknown resource "
1154af11cb2d521f9d7e10c565bafe8f2358772baa65Bjorn Helgaas				 "type %d\n", resource->type);
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EINVAL;
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11571c6e7d0aeecac38e66b1bb63e3eff07b2a1c2f2cBjorn Helgaas		resource++;
11581c6e7d0aeecac38e66b1bb63e3eff07b2a1c2f2cBjorn Helgaas		i++;
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1162