rsparser.c 28.4 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>
B
Bob Moore 已提交
6
 *
L
Linus Torvalds 已提交
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * 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>
24 25
#include <linux/pnp.h>
#include "../base.h"
L
Linus Torvalds 已提交
26 27 28 29 30 31 32 33 34 35 36
#include "pnpacpi.h"

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

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

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

53
	if (shareable == ACPI_SHARED)
54 55 56
		flags |= IORESOURCE_IRQ_SHAREABLE;

	return flags;
L
Linus Torvalds 已提交
57 58
}

B
Bjorn Helgaas 已提交
59
static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering,
60
			     int *polarity, int *shareable)
L
Linus Torvalds 已提交
61
{
B
Bjorn Helgaas 已提交
62 63
	switch (flags & (IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_HIGHLEVEL |
			 IORESOURCE_IRQ_LOWEDGE  | IORESOURCE_IRQ_HIGHEDGE)) {
L
Linus Torvalds 已提交
64
	case IORESOURCE_IRQ_LOWLEVEL:
B
Bob Moore 已提交
65 66
		*triggering = ACPI_LEVEL_SENSITIVE;
		*polarity = ACPI_ACTIVE_LOW;
L
Linus Torvalds 已提交
67
		break;
B
Bjorn Helgaas 已提交
68
	case IORESOURCE_IRQ_HIGHLEVEL:
B
Bob Moore 已提交
69 70
		*triggering = ACPI_LEVEL_SENSITIVE;
		*polarity = ACPI_ACTIVE_HIGH;
L
Linus Torvalds 已提交
71 72
		break;
	case IORESOURCE_IRQ_LOWEDGE:
B
Bob Moore 已提交
73 74
		*triggering = ACPI_EDGE_SENSITIVE;
		*polarity = ACPI_ACTIVE_LOW;
L
Linus Torvalds 已提交
75 76
		break;
	case IORESOURCE_IRQ_HIGHEDGE:
B
Bob Moore 已提交
77 78
		*triggering = ACPI_EDGE_SENSITIVE;
		*polarity = ACPI_ACTIVE_HIGH;
L
Linus Torvalds 已提交
79
		break;
B
Bjorn Helgaas 已提交
80 81 82 83 84 85
	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 已提交
86
	}
87 88 89 90 91

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

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

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

106 107 108 109 110 111 112 113 114 115
	/*
	 * 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) {
116
			dev_warn(&dev->dev, "IRQ %d override to %s, %s\n",
117 118 119 120 121 122
				gsi, t ? "edge":"level", p ? "low":"high");
			triggering = t;
			polarity = p;
		}
	}

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

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

133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
static int dma_flags(int type, int bus_master, int transfer)
{
	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;
		pnp_err("Invalid DMA type");
	}
	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;
		pnp_err("Invalid DMA transfer type");
	}

	return flags;
}

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

182
	if (io_decode == ACPI_DECODE_16)
183
		flags |= IORESOURCE_IO_16BIT_ADDR;
184 185 186 187
	if (len == 0 || end >= 0x10003)
		flags |= IORESOURCE_DISABLED;

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

190
static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
191
						u64 start, u64 len,
B
Bjorn Helgaas 已提交
192
						int write_protect)
L
Linus Torvalds 已提交
193
{
194 195 196 197 198 199 200 201 202
	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 已提交
203 204
}

205
static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
B
Bjorn Helgaas 已提交
206
						  struct acpi_resource *res)
207 208 209 210 211 212
{
	struct acpi_resource_address64 addr, *p = &addr;
	acpi_status status;

	status = acpi_resource_to_address64(res, p);
	if (!ACPI_SUCCESS(status)) {
213
		dev_warn(&dev->dev, "failed to convert resource type %d\n",
B
Bjorn Helgaas 已提交
214
			 res->type);
215 216 217
		return;
	}

218 219 220
	if (p->producer_consumer == ACPI_PRODUCER)
		return;

221
	if (p->resource_type == ACPI_MEMORY_RANGE)
222
		pnpacpi_parse_allocated_memresource(dev,
B
Bjorn Helgaas 已提交
223 224
			p->minimum, p->address_length,
			p->info.mem.write_protect);
225
	else if (p->resource_type == ACPI_IO_RANGE)
226
		pnpacpi_parse_allocated_ioresource(dev,
B
Bjorn Helgaas 已提交
227 228 229
			p->minimum, p->address_length,
			p->granularity == 0xfff ? ACPI_DECODE_10 :
				ACPI_DECODE_16);
230
}
L
Linus Torvalds 已提交
231 232

static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
B
Bjorn Helgaas 已提交
233
					      void *data)
L
Linus Torvalds 已提交
234
{
235
	struct pnp_dev *dev = data;
236 237 238 239 240 241 242 243
	struct acpi_resource_irq *irq;
	struct acpi_resource_dma *dma;
	struct acpi_resource_io *io;
	struct acpi_resource_fixed_io *fixed_io;
	struct acpi_resource_memory24 *memory24;
	struct acpi_resource_memory32 *memory32;
	struct acpi_resource_fixed_memory32 *fixed_memory32;
	struct acpi_resource_extended_irq *extended_irq;
244
	int i, flags;
L
Linus Torvalds 已提交
245

246
	switch (res->type) {
B
Bob Moore 已提交
247
	case ACPI_RESOURCE_TYPE_IRQ:
248 249 250 251
		/*
		 * Per spec, only one interrupt per descriptor is allowed in
		 * _CRS, but some firmware violates this, so parse them all.
		 */
252
		irq = &res->data.irq;
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
		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 已提交
275 276 277
		}
		break;

B
Bob Moore 已提交
278
	case ACPI_RESOURCE_TYPE_DMA:
279
		dma = &res->data.dma;
280
		if (dma->channel_count > 0 && dma->channels[0] != (u8) -1)
281 282
			flags = dma_flags(dma->type, dma->bus_master,
					  dma->transfer);
283 284 285
		else
			flags = IORESOURCE_DISABLED;
		pnp_add_dma_resource(dev, dma->channels[0], flags);
L
Linus Torvalds 已提交
286
		break;
287

B
Bob Moore 已提交
288
	case ACPI_RESOURCE_TYPE_IO:
289
		io = &res->data.io;
290
		pnpacpi_parse_allocated_ioresource(dev,
291 292 293
			io->minimum,
			io->address_length,
			io->io_decode);
L
Linus Torvalds 已提交
294
		break;
295 296 297 298 299

	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
		break;

B
Bob Moore 已提交
300
	case ACPI_RESOURCE_TYPE_FIXED_IO:
301
		fixed_io = &res->data.fixed_io;
302
		pnpacpi_parse_allocated_ioresource(dev,
303 304
			fixed_io->address,
			fixed_io->address_length,
B
Bjorn Helgaas 已提交
305
			ACPI_DECODE_10);
L
Linus Torvalds 已提交
306
		break;
307 308 309 310 311 312 313

	case ACPI_RESOURCE_TYPE_VENDOR:
		break;

	case ACPI_RESOURCE_TYPE_END_TAG:
		break;

B
Bob Moore 已提交
314
	case ACPI_RESOURCE_TYPE_MEMORY24:
315
		memory24 = &res->data.memory24;
316
		pnpacpi_parse_allocated_memresource(dev,
317 318 319
			memory24->minimum,
			memory24->address_length,
			memory24->write_protect);
L
Linus Torvalds 已提交
320
		break;
B
Bob Moore 已提交
321
	case ACPI_RESOURCE_TYPE_MEMORY32:
322
		memory32 = &res->data.memory32;
323
		pnpacpi_parse_allocated_memresource(dev,
324 325 326
			memory32->minimum,
			memory32->address_length,
			memory32->write_protect);
L
Linus Torvalds 已提交
327
		break;
B
Bob Moore 已提交
328
	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
329
		fixed_memory32 = &res->data.fixed_memory32;
330
		pnpacpi_parse_allocated_memresource(dev,
331 332 333
			fixed_memory32->address,
			fixed_memory32->address_length,
			fixed_memory32->write_protect);
L
Linus Torvalds 已提交
334
		break;
B
Bob Moore 已提交
335 336 337
	case ACPI_RESOURCE_TYPE_ADDRESS16:
	case ACPI_RESOURCE_TYPE_ADDRESS32:
	case ACPI_RESOURCE_TYPE_ADDRESS64:
338
		pnpacpi_parse_allocated_address_space(dev, res);
L
Linus Torvalds 已提交
339
		break;
340 341

	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
342 343
		if (res->data.ext_address64.producer_consumer == ACPI_PRODUCER)
			return AE_OK;
344 345 346
		break;

	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
347 348
		extended_irq = &res->data.extended_irq;
		if (extended_irq->producer_consumer == ACPI_PRODUCER)
349 350
			return AE_OK;

351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
		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;
			}
374 375 376 377
		}
		break;

	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
L
Linus Torvalds 已提交
378
		break;
379

L
Linus Torvalds 已提交
380
	default:
381 382
		dev_warn(&dev->dev, "unknown resource type %d in _CRS\n",
			 res->type);
L
Linus Torvalds 已提交
383 384
		return AE_ERROR;
	}
B
Bjorn Helgaas 已提交
385

L
Linus Torvalds 已提交
386 387 388
	return AE_OK;
}

389
int pnpacpi_parse_allocated_resource(struct pnp_dev *dev)
L
Linus Torvalds 已提交
390
{
391
	acpi_handle handle = dev->data;
392
	acpi_status status;
393

394 395
	dev_dbg(&dev->dev, "parse allocated resources\n");

396
	pnp_init_resources(dev);
L
Linus Torvalds 已提交
397

398 399 400 401 402 403 404 405 406
	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 已提交
407 408
}

409 410
static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
					    struct pnp_option *option,
411
					    struct acpi_resource_dma *p)
L
Linus Torvalds 已提交
412 413
{
	int i;
414
	unsigned char map = 0, flags;
L
Linus Torvalds 已提交
415

B
Bob Moore 已提交
416
	if (p->channel_count == 0)
L
Linus Torvalds 已提交
417 418
		return;

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

422 423
	flags = dma_flags(p->type, p->bus_master, p->transfer);
	pnp_register_dma_resource(dev, option, map, flags);
L
Linus Torvalds 已提交
424 425
}

426 427
static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
					    struct pnp_option *option,
428
					    struct acpi_resource_irq *p)
L
Linus Torvalds 已提交
429 430
{
	int i;
431 432
	pnp_irq_mask_t map;
	unsigned char flags;
B
Bjorn Helgaas 已提交
433

B
Bob Moore 已提交
434
	if (p->interrupt_count == 0)
L
Linus Torvalds 已提交
435 436
		return;

437
	bitmap_zero(map.bits, PNP_IRQ_NR);
B
Bjorn Helgaas 已提交
438
	for (i = 0; i < p->interrupt_count; i++)
L
Linus Torvalds 已提交
439
		if (p->interrupts[i])
440
			__set_bit(p->interrupts[i], map.bits);
L
Linus Torvalds 已提交
441

442 443
	flags = irq_flags(p->triggering, p->polarity, p->sharable);
	pnp_register_irq_resource(dev, option, &map, flags);
L
Linus Torvalds 已提交
444 445
}

446 447
static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
						struct pnp_option *option,
448
					struct acpi_resource_extended_irq *p)
L
Linus Torvalds 已提交
449 450
{
	int i;
451 452
	pnp_irq_mask_t map;
	unsigned char flags;
L
Linus Torvalds 已提交
453

B
Bob Moore 已提交
454
	if (p->interrupt_count == 0)
L
Linus Torvalds 已提交
455 456
		return;

457
	bitmap_zero(map.bits, PNP_IRQ_NR);
458 459 460 461 462 463 464 465 466 467
	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 已提交
468

469 470
	flags = irq_flags(p->triggering, p->polarity, p->sharable);
	pnp_register_irq_resource(dev, option, &map, flags);
L
Linus Torvalds 已提交
471 472
}

473 474
static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
					     struct pnp_option *option,
475
					     struct acpi_resource_io *io)
L
Linus Torvalds 已提交
476
{
477
	unsigned char flags = 0;
L
Linus Torvalds 已提交
478

B
Bob Moore 已提交
479
	if (io->address_length == 0)
L
Linus Torvalds 已提交
480
		return;
481 482 483 484 485

	if (io->io_decode == ACPI_DECODE_16)
		flags = IORESOURCE_IO_16BIT_ADDR;
	pnp_register_port_resource(dev, option, io->minimum, io->maximum,
				   io->alignment, io->address_length, flags);
L
Linus Torvalds 已提交
486 487
}

488 489
static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
						   struct pnp_option *option,
490
					struct acpi_resource_fixed_io *io)
L
Linus Torvalds 已提交
491
{
B
Bob Moore 已提交
492
	if (io->address_length == 0)
L
Linus Torvalds 已提交
493
		return;
494 495 496

	pnp_register_port_resource(dev, option, io->address, io->address, 0,
				   io->address_length, IORESOURCE_IO_FIXED);
L
Linus Torvalds 已提交
497 498
}

499 500
static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
					      struct pnp_option *option,
501
					      struct acpi_resource_memory24 *p)
L
Linus Torvalds 已提交
502
{
503
	unsigned char flags = 0;
L
Linus Torvalds 已提交
504

B
Bob Moore 已提交
505
	if (p->address_length == 0)
L
Linus Torvalds 已提交
506 507
		return;

508 509 510 511
	if (p->write_protect == ACPI_READ_WRITE_MEMORY)
		flags = IORESOURCE_MEM_WRITEABLE;
	pnp_register_mem_resource(dev, option, p->minimum, p->maximum,
				  p->alignment, p->address_length, flags);
L
Linus Torvalds 已提交
512 513
}

514 515
static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
					      struct pnp_option *option,
516
					      struct acpi_resource_memory32 *p)
L
Linus Torvalds 已提交
517
{
518
	unsigned char flags = 0;
L
Linus Torvalds 已提交
519

B
Bob Moore 已提交
520
	if (p->address_length == 0)
L
Linus Torvalds 已提交
521 522
		return;

523 524 525 526
	if (p->write_protect == ACPI_READ_WRITE_MEMORY)
		flags = IORESOURCE_MEM_WRITEABLE;
	pnp_register_mem_resource(dev, option, p->minimum, p->maximum,
				  p->alignment, p->address_length, flags);
L
Linus Torvalds 已提交
527 528
}

529 530
static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
						    struct pnp_option *option,
531
					struct acpi_resource_fixed_memory32 *p)
L
Linus Torvalds 已提交
532
{
533
	unsigned char flags = 0;
L
Linus Torvalds 已提交
534

B
Bob Moore 已提交
535
	if (p->address_length == 0)
L
Linus Torvalds 已提交
536 537
		return;

538 539 540 541
	if (p->write_protect == ACPI_READ_WRITE_MEMORY)
		flags = IORESOURCE_MEM_WRITEABLE;
	pnp_register_mem_resource(dev, option, p->address, p->address,
				  0, p->address_length, flags);
L
Linus Torvalds 已提交
542 543
}

544 545
static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
						struct pnp_option *option,
546
						struct acpi_resource *r)
547 548 549
{
	struct acpi_resource_address64 addr, *p = &addr;
	acpi_status status;
550
	unsigned char flags = 0;
551 552 553

	status = acpi_resource_to_address64(r, p);
	if (!ACPI_SUCCESS(status)) {
B
Bjorn Helgaas 已提交
554 555
		pnp_warn("PnPACPI: failed to convert resource type %d",
			 r->type);
556 557 558 559 560 561 562
		return;
	}

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

	if (p->resource_type == ACPI_MEMORY_RANGE) {
563 564 565 566 567 568 569 570
		if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY)
			flags = IORESOURCE_MEM_WRITEABLE;
		pnp_register_mem_resource(dev, option, p->minimum, p->minimum,
					  0, p->address_length, flags);
	} else if (p->resource_type == ACPI_IO_RANGE)
		pnp_register_port_resource(dev, option, p->minimum, p->minimum,
					   0, p->address_length,
					   IORESOURCE_IO_FIXED);
571 572
}

L
Linus Torvalds 已提交
573 574
struct acpipnp_parse_option_s {
	struct pnp_option *option;
M
Matthieu Castet 已提交
575
	struct pnp_option *option_independent;
L
Linus Torvalds 已提交
576 577 578
	struct pnp_dev *dev;
};

579 580
static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
						  void *data)
L
Linus Torvalds 已提交
581
{
582
	int priority;
583
	struct acpipnp_parse_option_s *parse_data = data;
L
Linus Torvalds 已提交
584 585 586
	struct pnp_dev *dev = parse_data->dev;
	struct pnp_option *option = parse_data->option;

587
	switch (res->type) {
B
Bjorn Helgaas 已提交
588
	case ACPI_RESOURCE_TYPE_IRQ:
589
		pnpacpi_parse_irq_option(dev, option, &res->data.irq);
B
Bjorn Helgaas 已提交
590
		break;
591

B
Bjorn Helgaas 已提交
592
	case ACPI_RESOURCE_TYPE_DMA:
593
		pnpacpi_parse_dma_option(dev, option, &res->data.dma);
B
Bjorn Helgaas 已提交
594
		break;
595

B
Bjorn Helgaas 已提交
596 597 598 599
	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 已提交
600
			break;
601

B
Bjorn Helgaas 已提交
602 603
		case ACPI_ACCEPTABLE_CONFIGURATION:
			priority = PNP_RES_PRIORITY_ACCEPTABLE;
M
Matthieu Castet 已提交
604
			break;
605

B
Bjorn Helgaas 已提交
606 607
		case ACPI_SUB_OPTIMAL_CONFIGURATION:
			priority = PNP_RES_PRIORITY_FUNCTIONAL;
608
			break;
B
Bjorn Helgaas 已提交
609 610
		default:
			priority = PNP_RES_PRIORITY_INVALID;
611
			break;
B
Bjorn Helgaas 已提交
612
		}
B
Bjorn Helgaas 已提交
613
		/* TBD: Consider performance/robustness bits */
B
Bjorn Helgaas 已提交
614 615 616 617 618
		option = pnp_register_dependent_option(dev, priority);
		if (!option)
			return AE_ERROR;
		parse_data->option = option;
		break;
619

B
Bjorn Helgaas 已提交
620 621 622
	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
		/*only one EndDependentFn is allowed */
		if (!parse_data->option_independent) {
623 624
			dev_warn(&dev->dev, "more than one EndDependentFn "
				 "in _PRS\n");
B
Bjorn Helgaas 已提交
625 626 627 628
			return AE_ERROR;
		}
		parse_data->option = parse_data->option_independent;
		parse_data->option_independent = NULL;
629
		dev_dbg(&dev->dev, "end dependent options\n");
B
Bjorn Helgaas 已提交
630
		break;
631

B
Bjorn Helgaas 已提交
632
	case ACPI_RESOURCE_TYPE_IO:
633
		pnpacpi_parse_port_option(dev, option, &res->data.io);
B
Bjorn Helgaas 已提交
634
		break;
635

B
Bjorn Helgaas 已提交
636
	case ACPI_RESOURCE_TYPE_FIXED_IO:
637 638
		pnpacpi_parse_fixed_port_option(dev, option,
					        &res->data.fixed_io);
B
Bjorn Helgaas 已提交
639
		break;
640

B
Bjorn Helgaas 已提交
641 642 643
	case ACPI_RESOURCE_TYPE_VENDOR:
	case ACPI_RESOURCE_TYPE_END_TAG:
		break;
644

B
Bjorn Helgaas 已提交
645
	case ACPI_RESOURCE_TYPE_MEMORY24:
646
		pnpacpi_parse_mem24_option(dev, option, &res->data.memory24);
B
Bjorn Helgaas 已提交
647
		break;
648

B
Bjorn Helgaas 已提交
649
	case ACPI_RESOURCE_TYPE_MEMORY32:
650
		pnpacpi_parse_mem32_option(dev, option, &res->data.memory32);
B
Bjorn Helgaas 已提交
651
		break;
652

B
Bjorn Helgaas 已提交
653
	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
654
		pnpacpi_parse_fixed_mem32_option(dev, option,
B
Bjorn Helgaas 已提交
655 656
						 &res->data.fixed_memory32);
		break;
657

B
Bjorn Helgaas 已提交
658 659 660
	case ACPI_RESOURCE_TYPE_ADDRESS16:
	case ACPI_RESOURCE_TYPE_ADDRESS32:
	case ACPI_RESOURCE_TYPE_ADDRESS64:
661
		pnpacpi_parse_address_option(dev, option, res);
B
Bjorn Helgaas 已提交
662
		break;
663

B
Bjorn Helgaas 已提交
664 665 666 667
	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
		break;

	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
668 669
		pnpacpi_parse_ext_irq_option(dev, option,
					     &res->data.extended_irq);
B
Bjorn Helgaas 已提交
670 671 672 673 674 675
		break;

	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
		break;

	default:
676 677
		dev_warn(&dev->dev, "unknown resource type %d in _PRS\n",
			 res->type);
B
Bjorn Helgaas 已提交
678
		return AE_ERROR;
L
Linus Torvalds 已提交
679
	}
B
Bjorn Helgaas 已提交
680

L
Linus Torvalds 已提交
681 682 683
	return AE_OK;
}

684
int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)
L
Linus Torvalds 已提交
685
{
686
	acpi_handle handle = dev->data;
L
Linus Torvalds 已提交
687 688 689
	acpi_status status;
	struct acpipnp_parse_option_s parse_data;

690 691
	dev_dbg(&dev->dev, "parse resource options\n");

L
Linus Torvalds 已提交
692 693
	parse_data.option = pnp_register_independent_option(dev);
	if (!parse_data.option)
694 695
		return -ENOMEM;

M
Matthieu Castet 已提交
696
	parse_data.option_independent = parse_data.option;
L
Linus Torvalds 已提交
697
	parse_data.dev = dev;
B
Bob Moore 已提交
698
	status = acpi_walk_resources(handle, METHOD_NAME__PRS,
B
Bjorn Helgaas 已提交
699
				     pnpacpi_option_resource, &parse_data);
L
Linus Torvalds 已提交
700

701 702 703 704 705 706
	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 已提交
707 708
}

709
static int pnpacpi_supported_resource(struct acpi_resource *res)
L
Linus Torvalds 已提交
710
{
711
	switch (res->type) {
B
Bob Moore 已提交
712 713 714 715 716 717 718 719 720 721
	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:
722
	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
723
		return 1;
L
Linus Torvalds 已提交
724
	}
725 726 727 728 729 730 731
	return 0;
}

/*
 * Set resource
 */
static acpi_status pnpacpi_count_resources(struct acpi_resource *res,
B
Bjorn Helgaas 已提交
732
					   void *data)
733
{
734
	int *res_cnt = data;
735 736 737

	if (pnpacpi_supported_resource(res))
		(*res_cnt)++;
L
Linus Torvalds 已提交
738 739 740
	return AE_OK;
}

B
Bjorn Helgaas 已提交
741
static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data)
L
Linus Torvalds 已提交
742
{
743
	struct acpi_resource **resource = data;
744 745

	if (pnpacpi_supported_resource(res)) {
746
		(*resource)->type = res->type;
747
		(*resource)->length = sizeof(struct acpi_resource);
748 749 750
		if (res->type == ACPI_RESOURCE_TYPE_IRQ)
			(*resource)->data.irq.descriptor_length =
					res->data.irq.descriptor_length;
L
Linus Torvalds 已提交
751 752 753 754 755 756
		(*resource)++;
	}

	return AE_OK;
}

757
int pnpacpi_build_resource_template(struct pnp_dev *dev,
B
Bjorn Helgaas 已提交
758
				    struct acpi_buffer *buffer)
L
Linus Torvalds 已提交
759
{
760
	acpi_handle handle = dev->data;
L
Linus Torvalds 已提交
761 762 763 764
	struct acpi_resource *resource;
	int res_cnt = 0;
	acpi_status status;

B
Bob Moore 已提交
765
	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
B
Bjorn Helgaas 已提交
766
				     pnpacpi_count_resources, &res_cnt);
L
Linus Torvalds 已提交
767
	if (ACPI_FAILURE(status)) {
768
		dev_err(&dev->dev, "can't evaluate _CRS: %d\n", status);
L
Linus Torvalds 已提交
769 770 771 772 773
		return -EINVAL;
	}
	if (!res_cnt)
		return -EINVAL;
	buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1;
774
	buffer->pointer = kzalloc(buffer->length - 1, GFP_KERNEL);
L
Linus Torvalds 已提交
775 776
	if (!buffer->pointer)
		return -ENOMEM;
777

L
Linus Torvalds 已提交
778
	resource = (struct acpi_resource *)buffer->pointer;
B
Bob Moore 已提交
779
	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
B
Bjorn Helgaas 已提交
780
				     pnpacpi_type_resources, &resource);
L
Linus Torvalds 已提交
781 782
	if (ACPI_FAILURE(status)) {
		kfree(buffer->pointer);
783
		dev_err(&dev->dev, "can't evaluate _CRS: %d\n", status);
L
Linus Torvalds 已提交
784 785 786
		return -EINVAL;
	}
	/* resource will pointer the end resource now */
B
Bob Moore 已提交
787
	resource->type = ACPI_RESOURCE_TYPE_END_TAG;
L
Linus Torvalds 已提交
788 789 790 791

	return 0;
}

792 793
static void pnpacpi_encode_irq(struct pnp_dev *dev,
			       struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
794
			       struct resource *p)
L
Linus Torvalds 已提交
795
{
796
	struct acpi_resource_irq *irq = &resource->data.irq;
797
	int triggering, polarity, shareable;
B
Bjorn Helgaas 已提交
798

799 800 801 802 803 804 805
	if (!pnp_resource_enabled(p)) {
		irq->interrupt_count = 0;
		dev_dbg(&dev->dev, "  encode irq (%s)\n",
			p ? "disabled" : "missing");
		return;
	}

806
	decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
807 808
	irq->triggering = triggering;
	irq->polarity = polarity;
809
	irq->sharable = shareable;
810 811
	irq->interrupt_count = 1;
	irq->interrupts[0] = p->start;
812

813 814
	dev_dbg(&dev->dev, "  encode irq %d %s %s %s (%d-byte descriptor)\n",
		(int) p->start,
815 816
		triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
		polarity == ACPI_ACTIVE_LOW ? "low" : "high",
817 818
		irq->sharable == ACPI_SHARED ? "shared" : "exclusive",
		irq->descriptor_length);
L
Linus Torvalds 已提交
819 820
}

821 822
static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
				   struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
823
				   struct resource *p)
L
Linus Torvalds 已提交
824
{
825
	struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq;
826
	int triggering, polarity, shareable;
B
Bjorn Helgaas 已提交
827

828 829 830 831 832 833 834
	if (!pnp_resource_enabled(p)) {
		extended_irq->interrupt_count = 0;
		dev_dbg(&dev->dev, "  encode extended irq (%s)\n",
			p ? "disabled" : "missing");
		return;
	}

835
	decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
836 837 838
	extended_irq->producer_consumer = ACPI_CONSUMER;
	extended_irq->triggering = triggering;
	extended_irq->polarity = polarity;
839
	extended_irq->sharable = shareable;
840 841
	extended_irq->interrupt_count = 1;
	extended_irq->interrupts[0] = p->start;
842 843 844 845 846

	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 已提交
847 848
}

849 850
static void pnpacpi_encode_dma(struct pnp_dev *dev,
			       struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
851
			       struct resource *p)
L
Linus Torvalds 已提交
852
{
853 854
	struct acpi_resource_dma *dma = &resource->data.dma;

855 856 857 858 859 860 861
	if (!pnp_resource_enabled(p)) {
		dma->channel_count = 0;
		dev_dbg(&dev->dev, "  encode dma (%s)\n",
			p ? "disabled" : "missing");
		return;
	}

L
Linus Torvalds 已提交
862
	/* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
863
	switch (p->flags & IORESOURCE_DMA_SPEED_MASK) {
B
Bjorn Helgaas 已提交
864
	case IORESOURCE_DMA_TYPEA:
865
		dma->type = ACPI_TYPE_A;
B
Bjorn Helgaas 已提交
866 867
		break;
	case IORESOURCE_DMA_TYPEB:
868
		dma->type = ACPI_TYPE_B;
B
Bjorn Helgaas 已提交
869 870
		break;
	case IORESOURCE_DMA_TYPEF:
871
		dma->type = ACPI_TYPE_F;
B
Bjorn Helgaas 已提交
872 873
		break;
	default:
874
		dma->type = ACPI_COMPATIBILITY;
875 876 877
	}

	switch (p->flags & IORESOURCE_DMA_TYPE_MASK) {
B
Bjorn Helgaas 已提交
878
	case IORESOURCE_DMA_8BIT:
879
		dma->transfer = ACPI_TRANSFER_8;
B
Bjorn Helgaas 已提交
880 881
		break;
	case IORESOURCE_DMA_8AND16BIT:
882
		dma->transfer = ACPI_TRANSFER_8_16;
B
Bjorn Helgaas 已提交
883 884
		break;
	default:
885
		dma->transfer = ACPI_TRANSFER_16;
886 887
	}

888 889 890
	dma->bus_master = !!(p->flags & IORESOURCE_DMA_MASTER);
	dma->channel_count = 1;
	dma->channels[0] = p->start;
891 892 893 894

	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 已提交
895 896
}

897 898
static void pnpacpi_encode_io(struct pnp_dev *dev,
			      struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
899
			      struct resource *p)
L
Linus Torvalds 已提交
900
{
901 902
	struct acpi_resource_io *io = &resource->data.io;

903 904
	if (pnp_resource_enabled(p)) {
		/* Note: pnp_assign_port copies pnp_port->flags into p->flags */
905
		io->io_decode = (p->flags & IORESOURCE_IO_16BIT_ADDR) ?
906 907 908 909 910 911 912 913 914
		    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;
	}
915

916 917
	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 已提交
918 919
}

920 921
static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
				    struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
922
				    struct resource *p)
L
Linus Torvalds 已提交
923
{
924 925
	struct acpi_resource_fixed_io *fixed_io = &resource->data.fixed_io;

926 927 928 929 930 931 932
	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;
	}
933

934 935
	dev_dbg(&dev->dev, "  encode fixed_io %#x-%#x\n", fixed_io->address,
		fixed_io->address + fixed_io->address_length - 1);
L
Linus Torvalds 已提交
936 937
}

938 939
static void pnpacpi_encode_mem24(struct pnp_dev *dev,
				 struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
940
				 struct resource *p)
L
Linus Torvalds 已提交
941
{
942 943
	struct acpi_resource_memory24 *memory24 = &resource->data.memory24;

944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959
	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,
960
		memory24->write_protect);
L
Linus Torvalds 已提交
961 962
}

963 964
static void pnpacpi_encode_mem32(struct pnp_dev *dev,
				 struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
965
				 struct resource *p)
L
Linus Torvalds 已提交
966
{
967 968
	struct acpi_resource_memory32 *memory32 = &resource->data.memory32;

969 970 971 972 973 974 975 976 977 978 979
	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;
	}
980

981 982 983
	dev_dbg(&dev->dev, "  encode mem32 %#x-%#x write_protect %#x\n",
		memory32->minimum,
		memory32->minimum + memory32->address_length - 1,
984
		memory32->write_protect);
L
Linus Torvalds 已提交
985 986
}

987 988
static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev,
				       struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
989
				       struct resource *p)
L
Linus Torvalds 已提交
990
{
991 992
	struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32;

993 994 995 996 997 998 999 1000 1001 1002
	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;
	}
1003

1004 1005 1006
	dev_dbg(&dev->dev, "  encode fixed_mem32 %#x-%#x write_protect %#x\n",
		fixed_memory32->address,
		fixed_memory32->address + fixed_memory32->address_length - 1,
1007
		fixed_memory32->write_protect);
L
Linus Torvalds 已提交
1008 1009
}

1010
int pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer)
L
Linus Torvalds 已提交
1011 1012 1013
{
	int i = 0;
	/* pnpacpi_build_resource_template allocates extra mem */
B
Bjorn Helgaas 已提交
1014
	int res_cnt = (buffer->length - 1) / sizeof(struct acpi_resource) - 1;
1015
	struct acpi_resource *resource = buffer->pointer;
L
Linus Torvalds 已提交
1016 1017
	int port = 0, irq = 0, dma = 0, mem = 0;

1018
	dev_dbg(&dev->dev, "encode %d resources\n", res_cnt);
L
Linus Torvalds 已提交
1019
	while (i < res_cnt) {
B
Bjorn Helgaas 已提交
1020
		switch (resource->type) {
B
Bob Moore 已提交
1021
		case ACPI_RESOURCE_TYPE_IRQ:
1022
			pnpacpi_encode_irq(dev, resource,
1023
			       pnp_get_resource(dev, IORESOURCE_IRQ, irq));
L
Linus Torvalds 已提交
1024 1025 1026
			irq++;
			break;

B
Bob Moore 已提交
1027
		case ACPI_RESOURCE_TYPE_DMA:
1028
			pnpacpi_encode_dma(dev, resource,
1029
				pnp_get_resource(dev, IORESOURCE_DMA, dma));
B
Bjorn Helgaas 已提交
1030
			dma++;
L
Linus Torvalds 已提交
1031
			break;
B
Bob Moore 已提交
1032
		case ACPI_RESOURCE_TYPE_IO:
1033
			pnpacpi_encode_io(dev, resource,
1034
				pnp_get_resource(dev, IORESOURCE_IO, port));
B
Bjorn Helgaas 已提交
1035
			port++;
L
Linus Torvalds 已提交
1036
			break;
B
Bob Moore 已提交
1037
		case ACPI_RESOURCE_TYPE_FIXED_IO:
1038
			pnpacpi_encode_fixed_io(dev, resource,
1039
				pnp_get_resource(dev, IORESOURCE_IO, port));
B
Bjorn Helgaas 已提交
1040
			port++;
L
Linus Torvalds 已提交
1041
			break;
B
Bob Moore 已提交
1042
		case ACPI_RESOURCE_TYPE_MEMORY24:
1043
			pnpacpi_encode_mem24(dev, resource,
1044
				pnp_get_resource(dev, IORESOURCE_MEM, mem));
B
Bjorn Helgaas 已提交
1045
			mem++;
L
Linus Torvalds 已提交
1046
			break;
B
Bob Moore 已提交
1047
		case ACPI_RESOURCE_TYPE_MEMORY32:
1048
			pnpacpi_encode_mem32(dev, resource,
1049
				pnp_get_resource(dev, IORESOURCE_MEM, mem));
B
Bjorn Helgaas 已提交
1050
			mem++;
L
Linus Torvalds 已提交
1051
			break;
B
Bob Moore 已提交
1052
		case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
1053
			pnpacpi_encode_fixed_mem32(dev, resource,
1054
				pnp_get_resource(dev, IORESOURCE_MEM, mem));
B
Bjorn Helgaas 已提交
1055
			mem++;
L
Linus Torvalds 已提交
1056
			break;
1057
		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
1058
			pnpacpi_encode_ext_irq(dev, resource,
1059
				pnp_get_resource(dev, IORESOURCE_IRQ, irq));
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070
			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 已提交
1071
		default:	/* other type */
1072 1073
			dev_warn(&dev->dev, "can't encode unknown resource "
				 "type %d\n", resource->type);
L
Linus Torvalds 已提交
1074 1075
			return -EINVAL;
		}
B
Bjorn Helgaas 已提交
1076 1077
		resource++;
		i++;
L
Linus Torvalds 已提交
1078 1079 1080
	}
	return 0;
}