rsparser.c 29.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5
/*
 * pnpacpi -- PnP ACPI driver
 *
 * Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr>
 * Copyright (c) 2004 Li Shaohua <shaohua.li@intel.com>
6 7
 * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
 *	Bjorn Helgaas <bjorn.helgaas@hp.com>
B
Bob Moore 已提交
8
 *
L
Linus Torvalds 已提交
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#include <linux/kernel.h>
#include <linux/acpi.h>
#include <linux/pci.h>
26 27
#include <linux/pnp.h>
#include "../base.h"
L
Linus Torvalds 已提交
28 29 30 31 32 33 34 35 36 37 38
#include "pnpacpi.h"

#ifdef CONFIG_IA64
#define valid_IRQ(i) (1)
#else
#define valid_IRQ(i) (((i) != 0) && ((i) != 2))
#endif

/*
 * Allocated Resources
 */
39
static int irq_flags(int triggering, int polarity, int shareable)
L
Linus Torvalds 已提交
40
{
41 42
	int flags;

B
Bob Moore 已提交
43
	if (triggering == ACPI_LEVEL_SENSITIVE) {
B
Bjorn Helgaas 已提交
44
		if (polarity == ACPI_ACTIVE_LOW)
45
			flags = IORESOURCE_IRQ_LOWLEVEL;
L
Linus Torvalds 已提交
46
		else
47
			flags = IORESOURCE_IRQ_HIGHLEVEL;
B
Bjorn Helgaas 已提交
48
	} else {
B
Bjorn Helgaas 已提交
49
		if (polarity == ACPI_ACTIVE_LOW)
50
			flags = IORESOURCE_IRQ_LOWEDGE;
L
Linus Torvalds 已提交
51
		else
52
			flags = IORESOURCE_IRQ_HIGHEDGE;
L
Linus Torvalds 已提交
53
	}
54

55
	if (shareable == ACPI_SHARED)
56 57 58
		flags |= IORESOURCE_IRQ_SHAREABLE;

	return flags;
L
Linus Torvalds 已提交
59 60
}

B
Bjorn Helgaas 已提交
61
static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering,
62
			     int *polarity, int *shareable)
L
Linus Torvalds 已提交
63
{
B
Bjorn Helgaas 已提交
64 65
	switch (flags & (IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_HIGHLEVEL |
			 IORESOURCE_IRQ_LOWEDGE  | IORESOURCE_IRQ_HIGHEDGE)) {
L
Linus Torvalds 已提交
66
	case IORESOURCE_IRQ_LOWLEVEL:
B
Bob Moore 已提交
67 68
		*triggering = ACPI_LEVEL_SENSITIVE;
		*polarity = ACPI_ACTIVE_LOW;
L
Linus Torvalds 已提交
69
		break;
B
Bjorn Helgaas 已提交
70
	case IORESOURCE_IRQ_HIGHLEVEL:
B
Bob Moore 已提交
71 72
		*triggering = ACPI_LEVEL_SENSITIVE;
		*polarity = ACPI_ACTIVE_HIGH;
L
Linus Torvalds 已提交
73 74
		break;
	case IORESOURCE_IRQ_LOWEDGE:
B
Bob Moore 已提交
75 76
		*triggering = ACPI_EDGE_SENSITIVE;
		*polarity = ACPI_ACTIVE_LOW;
L
Linus Torvalds 已提交
77 78
		break;
	case IORESOURCE_IRQ_HIGHEDGE:
B
Bob Moore 已提交
79 80
		*triggering = ACPI_EDGE_SENSITIVE;
		*polarity = ACPI_ACTIVE_HIGH;
L
Linus Torvalds 已提交
81
		break;
B
Bjorn Helgaas 已提交
82 83 84 85 86 87
	default:
		dev_err(&dev->dev, "can't encode invalid IRQ mode %#x\n",
			flags);
		*triggering = ACPI_EDGE_SENSITIVE;
		*polarity = ACPI_ACTIVE_HIGH;
		break;
L
Linus Torvalds 已提交
88
	}
89 90 91 92 93

	if (flags & IORESOURCE_IRQ_SHAREABLE)
		*shareable = ACPI_SHARED;
	else
		*shareable = ACPI_EXCLUSIVE;
L
Linus Torvalds 已提交
94 95
}

96
static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
B
Bjorn Helgaas 已提交
97 98
						u32 gsi, int triggering,
						int polarity, int shareable)
L
Linus Torvalds 已提交
99
{
100
	int irq, flags;
101
	int p, t;
102

103 104
	if (!valid_IRQ(gsi)) {
		pnp_add_irq_resource(dev, gsi, IORESOURCE_DISABLED);
105
		return;
106
	}
107

108 109 110 111 112 113 114 115 116 117
	/*
	 * in IO-APIC mode, use overrided attribute. Two reasons:
	 * 1. BIOS bug in DSDT
	 * 2. BIOS uses IO-APIC mode Interrupt Source Override
	 */
	if (!acpi_get_override_irq(gsi, &t, &p)) {
		t = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
		p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;

		if (triggering != t || polarity != p) {
118
			dev_warn(&dev->dev, "IRQ %d override to %s, %s\n",
119 120 121 122 123 124
				gsi, t ? "edge":"level", p ? "low":"high");
			triggering = t;
			polarity = p;
		}
	}

125
	flags = irq_flags(triggering, polarity, shareable);
B
Bob Moore 已提交
126
	irq = acpi_register_gsi(gsi, triggering, polarity);
127 128 129 130
	if (irq >= 0)
		pcibios_penalize_isa_irq(irq, 1);
	else
		flags |= IORESOURCE_DISABLED;
131

132
	pnp_add_irq_resource(dev, irq, flags);
L
Linus Torvalds 已提交
133 134
}

135 136
static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
		     int transfer)
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
{
	int flags = 0;

	if (bus_master)
		flags |= IORESOURCE_DMA_MASTER;
	switch (type) {
	case ACPI_COMPATIBILITY:
		flags |= IORESOURCE_DMA_COMPATIBLE;
		break;
	case ACPI_TYPE_A:
		flags |= IORESOURCE_DMA_TYPEA;
		break;
	case ACPI_TYPE_B:
		flags |= IORESOURCE_DMA_TYPEB;
		break;
	case ACPI_TYPE_F:
		flags |= IORESOURCE_DMA_TYPEF;
		break;
	default:
		/* Set a default value ? */
		flags |= IORESOURCE_DMA_COMPATIBLE;
158
		dev_err(&dev->dev, "invalid DMA type %d\n", type);
159 160 161 162 163 164 165 166 167 168 169 170 171 172
	}
	switch (transfer) {
	case ACPI_TRANSFER_8:
		flags |= IORESOURCE_DMA_8BIT;
		break;
	case ACPI_TRANSFER_8_16:
		flags |= IORESOURCE_DMA_8AND16BIT;
		break;
	case ACPI_TRANSFER_16:
		flags |= IORESOURCE_DMA_16BIT;
		break;
	default:
		/* Set a default value ? */
		flags |= IORESOURCE_DMA_8AND16BIT;
173
		dev_err(&dev->dev, "invalid DMA transfer type %d\n", transfer);
174 175 176 177 178
	}

	return flags;
}

179 180
static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start,
					       u64 len, int io_decode)
L
Linus Torvalds 已提交
181
{
182 183
	int flags = 0;
	u64 end = start + len - 1;
B
Bjorn Helgaas 已提交
184

185
	if (io_decode == ACPI_DECODE_16)
186
		flags |= IORESOURCE_IO_16BIT_ADDR;
187 188 189 190
	if (len == 0 || end >= 0x10003)
		flags |= IORESOURCE_DISABLED;

	pnp_add_io_resource(dev, start, end, flags);
L
Linus Torvalds 已提交
191 192
}

193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
/*
 * Device CSRs that do not appear in PCI config space should be described
 * via ACPI.  This would normally be done with Address Space Descriptors
 * marked as "consumer-only," but old versions of Windows and Linux ignore
 * the producer/consumer flag, so HP invented a vendor-defined resource to
 * describe the location and size of CSR space.
 */
static struct acpi_vendor_uuid hp_ccsr_uuid = {
	.subtype = 2,
	.data = { 0xf9, 0xad, 0xe9, 0x69, 0x4f, 0x92, 0x5f, 0xab, 0xf6, 0x4a,
	    0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad },
};

static int vendor_resource_matches(struct pnp_dev *dev,
				   struct acpi_resource_vendor_typed *vendor,
				   struct acpi_vendor_uuid *match,
				   int expected_len)
{
	int uuid_len = sizeof(vendor->uuid);
	u8 uuid_subtype = vendor->uuid_subtype;
	u8 *uuid = vendor->uuid;
	int actual_len;

	/* byte_length includes uuid_subtype and uuid */
	actual_len = vendor->byte_length - uuid_len - 1;

	if (uuid_subtype == match->subtype &&
	    uuid_len == sizeof(match->data) &&
	    memcmp(uuid, match->data, uuid_len) == 0) {
		if (expected_len && expected_len != actual_len) {
			dev_err(&dev->dev, "wrong vendor descriptor size; "
				"expected %d, found %d bytes\n",
				expected_len, actual_len);
			return 0;
		}

		return 1;
	}

	return 0;
}

static void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev,
				    struct acpi_resource_vendor_typed *vendor)
{
	if (vendor_resource_matches(dev, vendor, &hp_ccsr_uuid, 16)) {
		u64 start, length;

		memcpy(&start, vendor->byte_data, sizeof(start));
		memcpy(&length, vendor->byte_data + 8, sizeof(length));

		pnp_add_mem_resource(dev, start, start + length - 1, 0);
	}
}

248
static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
249
						u64 start, u64 len,
B
Bjorn Helgaas 已提交
250
						int write_protect)
L
Linus Torvalds 已提交
251
{
252 253 254 255 256 257 258 259 260
	int flags = 0;
	u64 end = start + len - 1;

	if (len == 0)
		flags |= IORESOURCE_DISABLED;
	if (write_protect == ACPI_READ_WRITE_MEMORY)
		flags |= IORESOURCE_MEM_WRITEABLE;

	pnp_add_mem_resource(dev, start, end, flags);
L
Linus Torvalds 已提交
261 262
}

263
static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
B
Bjorn Helgaas 已提交
264
						  struct acpi_resource *res)
265 266 267 268 269 270
{
	struct acpi_resource_address64 addr, *p = &addr;
	acpi_status status;

	status = acpi_resource_to_address64(res, p);
	if (!ACPI_SUCCESS(status)) {
271
		dev_warn(&dev->dev, "failed to convert resource type %d\n",
B
Bjorn Helgaas 已提交
272
			 res->type);
273 274 275
		return;
	}

276 277 278
	if (p->producer_consumer == ACPI_PRODUCER)
		return;

279
	if (p->resource_type == ACPI_MEMORY_RANGE)
280
		pnpacpi_parse_allocated_memresource(dev,
B
Bjorn Helgaas 已提交
281 282
			p->minimum, p->address_length,
			p->info.mem.write_protect);
283
	else if (p->resource_type == ACPI_IO_RANGE)
284
		pnpacpi_parse_allocated_ioresource(dev,
B
Bjorn Helgaas 已提交
285 286 287
			p->minimum, p->address_length,
			p->granularity == 0xfff ? ACPI_DECODE_10 :
				ACPI_DECODE_16);
288
}
L
Linus Torvalds 已提交
289 290

static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
B
Bjorn Helgaas 已提交
291
					      void *data)
L
Linus Torvalds 已提交
292
{
293
	struct pnp_dev *dev = data;
294 295 296 297
	struct acpi_resource_irq *irq;
	struct acpi_resource_dma *dma;
	struct acpi_resource_io *io;
	struct acpi_resource_fixed_io *fixed_io;
298
	struct acpi_resource_vendor_typed *vendor_typed;
299 300 301 302
	struct acpi_resource_memory24 *memory24;
	struct acpi_resource_memory32 *memory32;
	struct acpi_resource_fixed_memory32 *fixed_memory32;
	struct acpi_resource_extended_irq *extended_irq;
303
	int i, flags;
L
Linus Torvalds 已提交
304

305
	switch (res->type) {
B
Bob Moore 已提交
306
	case ACPI_RESOURCE_TYPE_IRQ:
307 308 309 310
		/*
		 * Per spec, only one interrupt per descriptor is allowed in
		 * _CRS, but some firmware violates this, so parse them all.
		 */
311
		irq = &res->data.irq;
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
		if (irq->interrupt_count == 0)
			pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
		else {
			for (i = 0; i < irq->interrupt_count; i++) {
				pnpacpi_parse_allocated_irqresource(dev,
					irq->interrupts[i],
					irq->triggering,
					irq->polarity,
				    irq->sharable);
			}

			/*
			 * The IRQ encoder puts a single interrupt in each
			 * descriptor, so if a _CRS descriptor has more than
			 * one interrupt, we won't be able to re-encode it.
			 */
			if (pnp_can_write(dev) && irq->interrupt_count > 1) {
				dev_warn(&dev->dev, "multiple interrupts in "
					 "_CRS descriptor; configuration can't "
					 "be changed\n");
				dev->capabilities &= ~PNP_WRITE;
			}
L
Linus Torvalds 已提交
334 335 336
		}
		break;

B
Bob Moore 已提交
337
	case ACPI_RESOURCE_TYPE_DMA:
338
		dma = &res->data.dma;
339
		if (dma->channel_count > 0 && dma->channels[0] != (u8) -1)
340
			flags = dma_flags(dev, dma->type, dma->bus_master,
341
					  dma->transfer);
342 343 344
		else
			flags = IORESOURCE_DISABLED;
		pnp_add_dma_resource(dev, dma->channels[0], flags);
L
Linus Torvalds 已提交
345
		break;
346

B
Bob Moore 已提交
347
	case ACPI_RESOURCE_TYPE_IO:
348
		io = &res->data.io;
349
		pnpacpi_parse_allocated_ioresource(dev,
350 351 352
			io->minimum,
			io->address_length,
			io->io_decode);
L
Linus Torvalds 已提交
353
		break;
354 355 356 357 358

	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
		break;

B
Bob Moore 已提交
359
	case ACPI_RESOURCE_TYPE_FIXED_IO:
360
		fixed_io = &res->data.fixed_io;
361
		pnpacpi_parse_allocated_ioresource(dev,
362 363
			fixed_io->address,
			fixed_io->address_length,
B
Bjorn Helgaas 已提交
364
			ACPI_DECODE_10);
L
Linus Torvalds 已提交
365
		break;
366 367

	case ACPI_RESOURCE_TYPE_VENDOR:
368 369
		vendor_typed = &res->data.vendor_typed;
		pnpacpi_parse_allocated_vendor(dev, vendor_typed);
370 371 372 373 374
		break;

	case ACPI_RESOURCE_TYPE_END_TAG:
		break;

B
Bob Moore 已提交
375
	case ACPI_RESOURCE_TYPE_MEMORY24:
376
		memory24 = &res->data.memory24;
377
		pnpacpi_parse_allocated_memresource(dev,
378 379 380
			memory24->minimum,
			memory24->address_length,
			memory24->write_protect);
L
Linus Torvalds 已提交
381
		break;
B
Bob Moore 已提交
382
	case ACPI_RESOURCE_TYPE_MEMORY32:
383
		memory32 = &res->data.memory32;
384
		pnpacpi_parse_allocated_memresource(dev,
385 386 387
			memory32->minimum,
			memory32->address_length,
			memory32->write_protect);
L
Linus Torvalds 已提交
388
		break;
B
Bob Moore 已提交
389
	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
390
		fixed_memory32 = &res->data.fixed_memory32;
391
		pnpacpi_parse_allocated_memresource(dev,
392 393 394
			fixed_memory32->address,
			fixed_memory32->address_length,
			fixed_memory32->write_protect);
L
Linus Torvalds 已提交
395
		break;
B
Bob Moore 已提交
396 397 398
	case ACPI_RESOURCE_TYPE_ADDRESS16:
	case ACPI_RESOURCE_TYPE_ADDRESS32:
	case ACPI_RESOURCE_TYPE_ADDRESS64:
399
		pnpacpi_parse_allocated_address_space(dev, res);
L
Linus Torvalds 已提交
400
		break;
401 402

	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
403 404
		if (res->data.ext_address64.producer_consumer == ACPI_PRODUCER)
			return AE_OK;
405 406 407
		break;

	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
408
		extended_irq = &res->data.extended_irq;
409

410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432
		if (extended_irq->interrupt_count == 0)
			pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
		else {
			for (i = 0; i < extended_irq->interrupt_count; i++) {
				pnpacpi_parse_allocated_irqresource(dev,
					extended_irq->interrupts[i],
					extended_irq->triggering,
					extended_irq->polarity,
					extended_irq->sharable);
			}

			/*
			 * The IRQ encoder puts a single interrupt in each
			 * descriptor, so if a _CRS descriptor has more than
			 * one interrupt, we won't be able to re-encode it.
			 */
			if (pnp_can_write(dev) &&
			    extended_irq->interrupt_count > 1) {
				dev_warn(&dev->dev, "multiple interrupts in "
					 "_CRS descriptor; configuration can't "
					 "be changed\n");
				dev->capabilities &= ~PNP_WRITE;
			}
433 434 435 436
		}
		break;

	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
L
Linus Torvalds 已提交
437
		break;
438

L
Linus Torvalds 已提交
439
	default:
440 441
		dev_warn(&dev->dev, "unknown resource type %d in _CRS\n",
			 res->type);
L
Linus Torvalds 已提交
442 443
		return AE_ERROR;
	}
B
Bjorn Helgaas 已提交
444

L
Linus Torvalds 已提交
445 446 447
	return AE_OK;
}

448
int pnpacpi_parse_allocated_resource(struct pnp_dev *dev)
L
Linus Torvalds 已提交
449
{
450
	acpi_handle handle = dev->data;
451
	acpi_status status;
452

453 454
	dev_dbg(&dev->dev, "parse allocated resources\n");

455
	pnp_init_resources(dev);
L
Linus Torvalds 已提交
456

457 458 459 460 461 462 463 464 465
	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
				     pnpacpi_allocated_resource, dev);

	if (ACPI_FAILURE(status)) {
		if (status != AE_NOT_FOUND)
			dev_err(&dev->dev, "can't evaluate _CRS: %d", status);
		return -EPERM;
	}
	return 0;
L
Linus Torvalds 已提交
466 467
}

468
static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
469
					    unsigned int option_flags,
470
					    struct acpi_resource_dma *p)
L
Linus Torvalds 已提交
471 472
{
	int i;
473
	unsigned char map = 0, flags;
L
Linus Torvalds 已提交
474

B
Bob Moore 已提交
475
	if (p->channel_count == 0)
L
Linus Torvalds 已提交
476 477
		return;

B
Bjorn Helgaas 已提交
478
	for (i = 0; i < p->channel_count; i++)
479
		map |= 1 << p->channels[i];
L
Linus Torvalds 已提交
480

481
	flags = dma_flags(dev, p->type, p->bus_master, p->transfer);
482
	pnp_register_dma_resource(dev, option_flags, map, flags);
L
Linus Torvalds 已提交
483 484
}

485
static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
486
					    unsigned int option_flags,
487
					    struct acpi_resource_irq *p)
L
Linus Torvalds 已提交
488 489
{
	int i;
490 491
	pnp_irq_mask_t map;
	unsigned char flags;
B
Bjorn Helgaas 已提交
492

B
Bob Moore 已提交
493
	if (p->interrupt_count == 0)
L
Linus Torvalds 已提交
494 495
		return;

496
	bitmap_zero(map.bits, PNP_IRQ_NR);
B
Bjorn Helgaas 已提交
497
	for (i = 0; i < p->interrupt_count; i++)
L
Linus Torvalds 已提交
498
		if (p->interrupts[i])
499
			__set_bit(p->interrupts[i], map.bits);
L
Linus Torvalds 已提交
500

501
	flags = irq_flags(p->triggering, p->polarity, p->sharable);
502
	pnp_register_irq_resource(dev, option_flags, &map, flags);
L
Linus Torvalds 已提交
503 504
}

505
static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
506
					unsigned int option_flags,
507
					struct acpi_resource_extended_irq *p)
L
Linus Torvalds 已提交
508 509
{
	int i;
510 511
	pnp_irq_mask_t map;
	unsigned char flags;
L
Linus Torvalds 已提交
512

B
Bob Moore 已提交
513
	if (p->interrupt_count == 0)
L
Linus Torvalds 已提交
514 515
		return;

516
	bitmap_zero(map.bits, PNP_IRQ_NR);
517 518 519 520 521 522 523 524 525 526
	for (i = 0; i < p->interrupt_count; i++) {
		if (p->interrupts[i]) {
			if (p->interrupts[i] < PNP_IRQ_NR)
				__set_bit(p->interrupts[i], map.bits);
			else
				dev_err(&dev->dev, "ignoring IRQ %d option "
					"(too large for %d entry bitmap)\n",
					p->interrupts[i], PNP_IRQ_NR);
		}
	}
L
Linus Torvalds 已提交
527

528
	flags = irq_flags(p->triggering, p->polarity, p->sharable);
529
	pnp_register_irq_resource(dev, option_flags, &map, flags);
L
Linus Torvalds 已提交
530 531
}

532
static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
533
					     unsigned int option_flags,
534
					     struct acpi_resource_io *io)
L
Linus Torvalds 已提交
535
{
536
	unsigned char flags = 0;
L
Linus Torvalds 已提交
537

B
Bob Moore 已提交
538
	if (io->address_length == 0)
L
Linus Torvalds 已提交
539
		return;
540 541 542

	if (io->io_decode == ACPI_DECODE_16)
		flags = IORESOURCE_IO_16BIT_ADDR;
543
	pnp_register_port_resource(dev, option_flags, io->minimum, io->maximum,
544
				   io->alignment, io->address_length, flags);
L
Linus Torvalds 已提交
545 546
}

547
static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
548
					unsigned int option_flags,
549
					struct acpi_resource_fixed_io *io)
L
Linus Torvalds 已提交
550
{
B
Bob Moore 已提交
551
	if (io->address_length == 0)
L
Linus Torvalds 已提交
552
		return;
553

554 555
	pnp_register_port_resource(dev, option_flags, io->address, io->address,
				   0, io->address_length, IORESOURCE_IO_FIXED);
L
Linus Torvalds 已提交
556 557
}

558
static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
559
					      unsigned int option_flags,
560
					      struct acpi_resource_memory24 *p)
L
Linus Torvalds 已提交
561
{
562
	unsigned char flags = 0;
L
Linus Torvalds 已提交
563

B
Bob Moore 已提交
564
	if (p->address_length == 0)
L
Linus Torvalds 已提交
565 566
		return;

567 568
	if (p->write_protect == ACPI_READ_WRITE_MEMORY)
		flags = IORESOURCE_MEM_WRITEABLE;
569
	pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
570
				  p->alignment, p->address_length, flags);
L
Linus Torvalds 已提交
571 572
}

573
static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
574
					      unsigned int option_flags,
575
					      struct acpi_resource_memory32 *p)
L
Linus Torvalds 已提交
576
{
577
	unsigned char flags = 0;
L
Linus Torvalds 已提交
578

B
Bob Moore 已提交
579
	if (p->address_length == 0)
L
Linus Torvalds 已提交
580 581
		return;

582 583
	if (p->write_protect == ACPI_READ_WRITE_MEMORY)
		flags = IORESOURCE_MEM_WRITEABLE;
584
	pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum,
585
				  p->alignment, p->address_length, flags);
L
Linus Torvalds 已提交
586 587
}

588
static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
589
					unsigned int option_flags,
590
					struct acpi_resource_fixed_memory32 *p)
L
Linus Torvalds 已提交
591
{
592
	unsigned char flags = 0;
L
Linus Torvalds 已提交
593

B
Bob Moore 已提交
594
	if (p->address_length == 0)
L
Linus Torvalds 已提交
595 596
		return;

597 598
	if (p->write_protect == ACPI_READ_WRITE_MEMORY)
		flags = IORESOURCE_MEM_WRITEABLE;
599
	pnp_register_mem_resource(dev, option_flags, p->address, p->address,
600
				  0, p->address_length, flags);
L
Linus Torvalds 已提交
601 602
}

603
static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
604
						unsigned int option_flags,
605
						struct acpi_resource *r)
606 607 608
{
	struct acpi_resource_address64 addr, *p = &addr;
	acpi_status status;
609
	unsigned char flags = 0;
610 611

	status = acpi_resource_to_address64(r, p);
612 613
	if (ACPI_FAILURE(status)) {
		dev_warn(&dev->dev, "can't convert resource type %d\n",
B
Bjorn Helgaas 已提交
614
			 r->type);
615 616 617 618 619 620 621
		return;
	}

	if (p->address_length == 0)
		return;

	if (p->resource_type == ACPI_MEMORY_RANGE) {
622 623
		if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
			flags = IORESOURCE_MEM_WRITEABLE;
624 625 626
		pnp_register_mem_resource(dev, option_flags, p->minimum,
					  p->minimum, 0, p->address_length,
					  flags);
627
	} else if (p->resource_type == ACPI_IO_RANGE)
628 629
		pnp_register_port_resource(dev, option_flags, p->minimum,
					   p->minimum, 0, p->address_length,
630
					   IORESOURCE_IO_FIXED);
631 632
}

L
Linus Torvalds 已提交
633 634
struct acpipnp_parse_option_s {
	struct pnp_dev *dev;
635
	unsigned int option_flags;
L
Linus Torvalds 已提交
636 637
};

638 639
static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
						  void *data)
L
Linus Torvalds 已提交
640
{
641
	int priority;
642
	struct acpipnp_parse_option_s *parse_data = data;
L
Linus Torvalds 已提交
643
	struct pnp_dev *dev = parse_data->dev;
644
	unsigned int option_flags = parse_data->option_flags;
L
Linus Torvalds 已提交
645

646
	switch (res->type) {
B
Bjorn Helgaas 已提交
647
	case ACPI_RESOURCE_TYPE_IRQ:
648
		pnpacpi_parse_irq_option(dev, option_flags, &res->data.irq);
B
Bjorn Helgaas 已提交
649
		break;
650

B
Bjorn Helgaas 已提交
651
	case ACPI_RESOURCE_TYPE_DMA:
652
		pnpacpi_parse_dma_option(dev, option_flags, &res->data.dma);
B
Bjorn Helgaas 已提交
653
		break;
654

B
Bjorn Helgaas 已提交
655 656 657 658
	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
		switch (res->data.start_dpf.compatibility_priority) {
		case ACPI_GOOD_CONFIGURATION:
			priority = PNP_RES_PRIORITY_PREFERRED;
L
Linus Torvalds 已提交
659
			break;
660

B
Bjorn Helgaas 已提交
661 662
		case ACPI_ACCEPTABLE_CONFIGURATION:
			priority = PNP_RES_PRIORITY_ACCEPTABLE;
M
Matthieu Castet 已提交
663
			break;
664

B
Bjorn Helgaas 已提交
665 666
		case ACPI_SUB_OPTIMAL_CONFIGURATION:
			priority = PNP_RES_PRIORITY_FUNCTIONAL;
667
			break;
B
Bjorn Helgaas 已提交
668 669
		default:
			priority = PNP_RES_PRIORITY_INVALID;
670
			break;
B
Bjorn Helgaas 已提交
671
		}
672
		parse_data->option_flags = pnp_new_dependent_set(dev, priority);
B
Bjorn Helgaas 已提交
673
		break;
674

B
Bjorn Helgaas 已提交
675
	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
676
		parse_data->option_flags = 0;
B
Bjorn Helgaas 已提交
677
		break;
678

B
Bjorn Helgaas 已提交
679
	case ACPI_RESOURCE_TYPE_IO:
680
		pnpacpi_parse_port_option(dev, option_flags, &res->data.io);
B
Bjorn Helgaas 已提交
681
		break;
682

B
Bjorn Helgaas 已提交
683
	case ACPI_RESOURCE_TYPE_FIXED_IO:
684
		pnpacpi_parse_fixed_port_option(dev, option_flags,
685
					        &res->data.fixed_io);
B
Bjorn Helgaas 已提交
686
		break;
687

B
Bjorn Helgaas 已提交
688 689 690
	case ACPI_RESOURCE_TYPE_VENDOR:
	case ACPI_RESOURCE_TYPE_END_TAG:
		break;
691

B
Bjorn Helgaas 已提交
692
	case ACPI_RESOURCE_TYPE_MEMORY24:
693 694
		pnpacpi_parse_mem24_option(dev, option_flags,
					   &res->data.memory24);
B
Bjorn Helgaas 已提交
695
		break;
696

B
Bjorn Helgaas 已提交
697
	case ACPI_RESOURCE_TYPE_MEMORY32:
698 699
		pnpacpi_parse_mem32_option(dev, option_flags,
					   &res->data.memory32);
B
Bjorn Helgaas 已提交
700
		break;
701

B
Bjorn Helgaas 已提交
702
	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
703
		pnpacpi_parse_fixed_mem32_option(dev, option_flags,
B
Bjorn Helgaas 已提交
704 705
						 &res->data.fixed_memory32);
		break;
706

B
Bjorn Helgaas 已提交
707 708 709
	case ACPI_RESOURCE_TYPE_ADDRESS16:
	case ACPI_RESOURCE_TYPE_ADDRESS32:
	case ACPI_RESOURCE_TYPE_ADDRESS64:
710
		pnpacpi_parse_address_option(dev, option_flags, res);
B
Bjorn Helgaas 已提交
711
		break;
712

B
Bjorn Helgaas 已提交
713 714 715 716
	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
		break;

	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
717
		pnpacpi_parse_ext_irq_option(dev, option_flags,
718
					     &res->data.extended_irq);
B
Bjorn Helgaas 已提交
719 720 721 722 723 724
		break;

	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
		break;

	default:
725 726
		dev_warn(&dev->dev, "unknown resource type %d in _PRS\n",
			 res->type);
B
Bjorn Helgaas 已提交
727
		return AE_ERROR;
L
Linus Torvalds 已提交
728
	}
B
Bjorn Helgaas 已提交
729

L
Linus Torvalds 已提交
730 731 732
	return AE_OK;
}

733
int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)
L
Linus Torvalds 已提交
734
{
735
	acpi_handle handle = dev->data;
L
Linus Torvalds 已提交
736 737 738
	acpi_status status;
	struct acpipnp_parse_option_s parse_data;

739 740
	dev_dbg(&dev->dev, "parse resource options\n");

L
Linus Torvalds 已提交
741
	parse_data.dev = dev;
742 743
	parse_data.option_flags = 0;

B
Bob Moore 已提交
744
	status = acpi_walk_resources(handle, METHOD_NAME__PRS,
B
Bjorn Helgaas 已提交
745
				     pnpacpi_option_resource, &parse_data);
L
Linus Torvalds 已提交
746

747 748 749 750 751 752
	if (ACPI_FAILURE(status)) {
		if (status != AE_NOT_FOUND)
			dev_err(&dev->dev, "can't evaluate _PRS: %d", status);
		return -EPERM;
	}
	return 0;
L
Linus Torvalds 已提交
753 754
}

755
static int pnpacpi_supported_resource(struct acpi_resource *res)
L
Linus Torvalds 已提交
756
{
757
	switch (res->type) {
B
Bob Moore 已提交
758 759 760 761 762 763 764 765 766 767
	case ACPI_RESOURCE_TYPE_IRQ:
	case ACPI_RESOURCE_TYPE_DMA:
	case ACPI_RESOURCE_TYPE_IO:
	case ACPI_RESOURCE_TYPE_FIXED_IO:
	case ACPI_RESOURCE_TYPE_MEMORY24:
	case ACPI_RESOURCE_TYPE_MEMORY32:
	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
	case ACPI_RESOURCE_TYPE_ADDRESS16:
	case ACPI_RESOURCE_TYPE_ADDRESS32:
	case ACPI_RESOURCE_TYPE_ADDRESS64:
768
	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
769
		return 1;
L
Linus Torvalds 已提交
770
	}
771 772 773 774 775 776 777
	return 0;
}

/*
 * Set resource
 */
static acpi_status pnpacpi_count_resources(struct acpi_resource *res,
B
Bjorn Helgaas 已提交
778
					   void *data)
779
{
780
	int *res_cnt = data;
781 782 783

	if (pnpacpi_supported_resource(res))
		(*res_cnt)++;
L
Linus Torvalds 已提交
784 785 786
	return AE_OK;
}

B
Bjorn Helgaas 已提交
787
static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data)
L
Linus Torvalds 已提交
788
{
789
	struct acpi_resource **resource = data;
790 791

	if (pnpacpi_supported_resource(res)) {
792
		(*resource)->type = res->type;
793
		(*resource)->length = sizeof(struct acpi_resource);
794 795 796
		if (res->type == ACPI_RESOURCE_TYPE_IRQ)
			(*resource)->data.irq.descriptor_length =
					res->data.irq.descriptor_length;
L
Linus Torvalds 已提交
797 798 799 800 801 802
		(*resource)++;
	}

	return AE_OK;
}

803
int pnpacpi_build_resource_template(struct pnp_dev *dev,
B
Bjorn Helgaas 已提交
804
				    struct acpi_buffer *buffer)
L
Linus Torvalds 已提交
805
{
806
	acpi_handle handle = dev->data;
L
Linus Torvalds 已提交
807 808 809 810
	struct acpi_resource *resource;
	int res_cnt = 0;
	acpi_status status;

B
Bob Moore 已提交
811
	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
B
Bjorn Helgaas 已提交
812
				     pnpacpi_count_resources, &res_cnt);
L
Linus Torvalds 已提交
813
	if (ACPI_FAILURE(status)) {
814
		dev_err(&dev->dev, "can't evaluate _CRS: %d\n", status);
L
Linus Torvalds 已提交
815 816 817 818 819
		return -EINVAL;
	}
	if (!res_cnt)
		return -EINVAL;
	buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1;
820
	buffer->pointer = kzalloc(buffer->length - 1, GFP_KERNEL);
L
Linus Torvalds 已提交
821 822
	if (!buffer->pointer)
		return -ENOMEM;
823

L
Linus Torvalds 已提交
824
	resource = (struct acpi_resource *)buffer->pointer;
B
Bob Moore 已提交
825
	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
B
Bjorn Helgaas 已提交
826
				     pnpacpi_type_resources, &resource);
L
Linus Torvalds 已提交
827 828
	if (ACPI_FAILURE(status)) {
		kfree(buffer->pointer);
829
		dev_err(&dev->dev, "can't evaluate _CRS: %d\n", status);
L
Linus Torvalds 已提交
830 831 832
		return -EINVAL;
	}
	/* resource will pointer the end resource now */
B
Bob Moore 已提交
833
	resource->type = ACPI_RESOURCE_TYPE_END_TAG;
L
Linus Torvalds 已提交
834 835 836 837

	return 0;
}

838 839
static void pnpacpi_encode_irq(struct pnp_dev *dev,
			       struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
840
			       struct resource *p)
L
Linus Torvalds 已提交
841
{
842
	struct acpi_resource_irq *irq = &resource->data.irq;
843
	int triggering, polarity, shareable;
B
Bjorn Helgaas 已提交
844

845 846 847 848 849 850 851
	if (!pnp_resource_enabled(p)) {
		irq->interrupt_count = 0;
		dev_dbg(&dev->dev, "  encode irq (%s)\n",
			p ? "disabled" : "missing");
		return;
	}

852
	decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
853 854
	irq->triggering = triggering;
	irq->polarity = polarity;
855
	irq->sharable = shareable;
856 857
	irq->interrupt_count = 1;
	irq->interrupts[0] = p->start;
858

859 860
	dev_dbg(&dev->dev, "  encode irq %d %s %s %s (%d-byte descriptor)\n",
		(int) p->start,
861 862
		triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
		polarity == ACPI_ACTIVE_LOW ? "low" : "high",
863 864
		irq->sharable == ACPI_SHARED ? "shared" : "exclusive",
		irq->descriptor_length);
L
Linus Torvalds 已提交
865 866
}

867 868
static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
				   struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
869
				   struct resource *p)
L
Linus Torvalds 已提交
870
{
871
	struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq;
872
	int triggering, polarity, shareable;
B
Bjorn Helgaas 已提交
873

874 875 876 877 878 879 880
	if (!pnp_resource_enabled(p)) {
		extended_irq->interrupt_count = 0;
		dev_dbg(&dev->dev, "  encode extended irq (%s)\n",
			p ? "disabled" : "missing");
		return;
	}

881
	decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
882 883 884
	extended_irq->producer_consumer = ACPI_CONSUMER;
	extended_irq->triggering = triggering;
	extended_irq->polarity = polarity;
885
	extended_irq->sharable = shareable;
886 887
	extended_irq->interrupt_count = 1;
	extended_irq->interrupts[0] = p->start;
888 889 890 891 892

	dev_dbg(&dev->dev, "  encode irq %d %s %s %s\n", (int) p->start,
		triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
		polarity == ACPI_ACTIVE_LOW ? "low" : "high",
		extended_irq->sharable == ACPI_SHARED ? "shared" : "exclusive");
L
Linus Torvalds 已提交
893 894
}

895 896
static void pnpacpi_encode_dma(struct pnp_dev *dev,
			       struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
897
			       struct resource *p)
L
Linus Torvalds 已提交
898
{
899 900
	struct acpi_resource_dma *dma = &resource->data.dma;

901 902 903 904 905 906 907
	if (!pnp_resource_enabled(p)) {
		dma->channel_count = 0;
		dev_dbg(&dev->dev, "  encode dma (%s)\n",
			p ? "disabled" : "missing");
		return;
	}

L
Linus Torvalds 已提交
908
	/* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
909
	switch (p->flags & IORESOURCE_DMA_SPEED_MASK) {
B
Bjorn Helgaas 已提交
910
	case IORESOURCE_DMA_TYPEA:
911
		dma->type = ACPI_TYPE_A;
B
Bjorn Helgaas 已提交
912 913
		break;
	case IORESOURCE_DMA_TYPEB:
914
		dma->type = ACPI_TYPE_B;
B
Bjorn Helgaas 已提交
915 916
		break;
	case IORESOURCE_DMA_TYPEF:
917
		dma->type = ACPI_TYPE_F;
B
Bjorn Helgaas 已提交
918 919
		break;
	default:
920
		dma->type = ACPI_COMPATIBILITY;
921 922 923
	}

	switch (p->flags & IORESOURCE_DMA_TYPE_MASK) {
B
Bjorn Helgaas 已提交
924
	case IORESOURCE_DMA_8BIT:
925
		dma->transfer = ACPI_TRANSFER_8;
B
Bjorn Helgaas 已提交
926 927
		break;
	case IORESOURCE_DMA_8AND16BIT:
928
		dma->transfer = ACPI_TRANSFER_8_16;
B
Bjorn Helgaas 已提交
929 930
		break;
	default:
931
		dma->transfer = ACPI_TRANSFER_16;
932 933
	}

934 935 936
	dma->bus_master = !!(p->flags & IORESOURCE_DMA_MASTER);
	dma->channel_count = 1;
	dma->channels[0] = p->start;
937 938 939 940

	dev_dbg(&dev->dev, "  encode dma %d "
		"type %#x transfer %#x master %d\n",
		(int) p->start, dma->type, dma->transfer, dma->bus_master);
L
Linus Torvalds 已提交
941 942
}

943 944
static void pnpacpi_encode_io(struct pnp_dev *dev,
			      struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
945
			      struct resource *p)
L
Linus Torvalds 已提交
946
{
947 948
	struct acpi_resource_io *io = &resource->data.io;

949 950
	if (pnp_resource_enabled(p)) {
		/* Note: pnp_assign_port copies pnp_port->flags into p->flags */
951
		io->io_decode = (p->flags & IORESOURCE_IO_16BIT_ADDR) ?
952 953 954 955 956 957 958 959 960
		    ACPI_DECODE_16 : ACPI_DECODE_10;
		io->minimum = p->start;
		io->maximum = p->end;
		io->alignment = 0;	/* Correct? */
		io->address_length = p->end - p->start + 1;
	} else {
		io->minimum = 0;
		io->address_length = 0;
	}
961

962 963
	dev_dbg(&dev->dev, "  encode io %#x-%#x decode %#x\n", io->minimum,
		io->minimum + io->address_length - 1, io->io_decode);
L
Linus Torvalds 已提交
964 965
}

966 967
static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
				    struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
968
				    struct resource *p)
L
Linus Torvalds 已提交
969
{
970 971
	struct acpi_resource_fixed_io *fixed_io = &resource->data.fixed_io;

972 973 974 975 976 977 978
	if (pnp_resource_enabled(p)) {
		fixed_io->address = p->start;
		fixed_io->address_length = p->end - p->start + 1;
	} else {
		fixed_io->address = 0;
		fixed_io->address_length = 0;
	}
979

980 981
	dev_dbg(&dev->dev, "  encode fixed_io %#x-%#x\n", fixed_io->address,
		fixed_io->address + fixed_io->address_length - 1);
L
Linus Torvalds 已提交
982 983
}

984 985
static void pnpacpi_encode_mem24(struct pnp_dev *dev,
				 struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
986
				 struct resource *p)
L
Linus Torvalds 已提交
987
{
988 989
	struct acpi_resource_memory24 *memory24 = &resource->data.memory24;

990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005
	if (pnp_resource_enabled(p)) {
		/* Note: pnp_assign_mem copies pnp_mem->flags into p->flags */
		memory24->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ?
		    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
		memory24->minimum = p->start;
		memory24->maximum = p->end;
		memory24->alignment = 0;
		memory24->address_length = p->end - p->start + 1;
	} else {
		memory24->minimum = 0;
		memory24->address_length = 0;
	}

	dev_dbg(&dev->dev, "  encode mem24 %#x-%#x write_protect %#x\n",
		memory24->minimum,
		memory24->minimum + memory24->address_length - 1,
1006
		memory24->write_protect);
L
Linus Torvalds 已提交
1007 1008
}

1009 1010
static void pnpacpi_encode_mem32(struct pnp_dev *dev,
				 struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
1011
				 struct resource *p)
L
Linus Torvalds 已提交
1012
{
1013 1014
	struct acpi_resource_memory32 *memory32 = &resource->data.memory32;

1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025
	if (pnp_resource_enabled(p)) {
		memory32->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ?
		    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
		memory32->minimum = p->start;
		memory32->maximum = p->end;
		memory32->alignment = 0;
		memory32->address_length = p->end - p->start + 1;
	} else {
		memory32->minimum = 0;
		memory32->alignment = 0;
	}
1026

1027 1028 1029
	dev_dbg(&dev->dev, "  encode mem32 %#x-%#x write_protect %#x\n",
		memory32->minimum,
		memory32->minimum + memory32->address_length - 1,
1030
		memory32->write_protect);
L
Linus Torvalds 已提交
1031 1032
}

1033 1034
static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev,
				       struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
1035
				       struct resource *p)
L
Linus Torvalds 已提交
1036
{
1037 1038
	struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32;

1039 1040 1041 1042 1043 1044 1045 1046 1047 1048
	if (pnp_resource_enabled(p)) {
		fixed_memory32->write_protect =
		    p->flags & IORESOURCE_MEM_WRITEABLE ?
		    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
		fixed_memory32->address = p->start;
		fixed_memory32->address_length = p->end - p->start + 1;
	} else {
		fixed_memory32->address = 0;
		fixed_memory32->address_length = 0;
	}
1049

1050 1051 1052
	dev_dbg(&dev->dev, "  encode fixed_mem32 %#x-%#x write_protect %#x\n",
		fixed_memory32->address,
		fixed_memory32->address + fixed_memory32->address_length - 1,
1053
		fixed_memory32->write_protect);
L
Linus Torvalds 已提交
1054 1055
}

1056
int pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer)
L
Linus Torvalds 已提交
1057 1058 1059
{
	int i = 0;
	/* pnpacpi_build_resource_template allocates extra mem */
B
Bjorn Helgaas 已提交
1060
	int res_cnt = (buffer->length - 1) / sizeof(struct acpi_resource) - 1;
1061
	struct acpi_resource *resource = buffer->pointer;
L
Linus Torvalds 已提交
1062 1063
	int port = 0, irq = 0, dma = 0, mem = 0;

1064
	dev_dbg(&dev->dev, "encode %d resources\n", res_cnt);
L
Linus Torvalds 已提交
1065
	while (i < res_cnt) {
B
Bjorn Helgaas 已提交
1066
		switch (resource->type) {
B
Bob Moore 已提交
1067
		case ACPI_RESOURCE_TYPE_IRQ:
1068
			pnpacpi_encode_irq(dev, resource,
1069
			       pnp_get_resource(dev, IORESOURCE_IRQ, irq));
L
Linus Torvalds 已提交
1070 1071 1072
			irq++;
			break;

B
Bob Moore 已提交
1073
		case ACPI_RESOURCE_TYPE_DMA:
1074
			pnpacpi_encode_dma(dev, resource,
1075
				pnp_get_resource(dev, IORESOURCE_DMA, dma));
B
Bjorn Helgaas 已提交
1076
			dma++;
L
Linus Torvalds 已提交
1077
			break;
B
Bob Moore 已提交
1078
		case ACPI_RESOURCE_TYPE_IO:
1079
			pnpacpi_encode_io(dev, resource,
1080
				pnp_get_resource(dev, IORESOURCE_IO, port));
B
Bjorn Helgaas 已提交
1081
			port++;
L
Linus Torvalds 已提交
1082
			break;
B
Bob Moore 已提交
1083
		case ACPI_RESOURCE_TYPE_FIXED_IO:
1084
			pnpacpi_encode_fixed_io(dev, resource,
1085
				pnp_get_resource(dev, IORESOURCE_IO, port));
B
Bjorn Helgaas 已提交
1086
			port++;
L
Linus Torvalds 已提交
1087
			break;
B
Bob Moore 已提交
1088
		case ACPI_RESOURCE_TYPE_MEMORY24:
1089
			pnpacpi_encode_mem24(dev, resource,
1090
				pnp_get_resource(dev, IORESOURCE_MEM, mem));
B
Bjorn Helgaas 已提交
1091
			mem++;
L
Linus Torvalds 已提交
1092
			break;
B
Bob Moore 已提交
1093
		case ACPI_RESOURCE_TYPE_MEMORY32:
1094
			pnpacpi_encode_mem32(dev, resource,
1095
				pnp_get_resource(dev, IORESOURCE_MEM, mem));
B
Bjorn Helgaas 已提交
1096
			mem++;
L
Linus Torvalds 已提交
1097
			break;
B
Bob Moore 已提交
1098
		case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
1099
			pnpacpi_encode_fixed_mem32(dev, resource,
1100
				pnp_get_resource(dev, IORESOURCE_MEM, mem));
B
Bjorn Helgaas 已提交
1101
			mem++;
L
Linus Torvalds 已提交
1102
			break;
1103
		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
1104
			pnpacpi_encode_ext_irq(dev, resource,
1105
				pnp_get_resource(dev, IORESOURCE_IRQ, irq));
1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116
			irq++;
			break;
		case ACPI_RESOURCE_TYPE_START_DEPENDENT:
		case ACPI_RESOURCE_TYPE_END_DEPENDENT:
		case ACPI_RESOURCE_TYPE_VENDOR:
		case ACPI_RESOURCE_TYPE_END_TAG:
		case ACPI_RESOURCE_TYPE_ADDRESS16:
		case ACPI_RESOURCE_TYPE_ADDRESS32:
		case ACPI_RESOURCE_TYPE_ADDRESS64:
		case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
		case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
B
Bjorn Helgaas 已提交
1117
		default:	/* other type */
1118 1119
			dev_warn(&dev->dev, "can't encode unknown resource "
				 "type %d\n", resource->type);
L
Linus Torvalds 已提交
1120 1121
			return -EINVAL;
		}
B
Bjorn Helgaas 已提交
1122 1123
		resource++;
		i++;
L
Linus Torvalds 已提交
1124 1125 1126
	}
	return 0;
}