rsparser.c 27.0 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 103

	if (!valid_IRQ(gsi))
		return;

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

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

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

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
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;
}

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

180 181 182 183 184 185
	if (io_decode == ACPI_DECODE_16)
		flags |= PNP_PORT_FLAG_16BITADDR;
	if (len == 0 || end >= 0x10003)
		flags |= IORESOURCE_DISABLED;

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

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

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

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

216 217 218
	if (p->producer_consumer == ACPI_PRODUCER)
		return;

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

static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
B
Bjorn Helgaas 已提交
231
					      void *data)
L
Linus Torvalds 已提交
232
{
233
	struct pnp_dev *dev = data;
234 235 236 237 238 239 240 241
	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;
242
	int i, flags;
L
Linus Torvalds 已提交
243

244
	switch (res->type) {
B
Bob Moore 已提交
245
	case ACPI_RESOURCE_TYPE_IRQ:
246 247 248 249
		/*
		 * Per spec, only one interrupt per descriptor is allowed in
		 * _CRS, but some firmware violates this, so parse them all.
		 */
250 251
		irq = &res->data.irq;
		for (i = 0; i < irq->interrupt_count; i++) {
252
			pnpacpi_parse_allocated_irqresource(dev,
253 254 255 256
				irq->interrupts[i],
				irq->triggering,
				irq->polarity,
				irq->sharable);
L
Linus Torvalds 已提交
257 258 259
		}
		break;

B
Bob Moore 已提交
260
	case ACPI_RESOURCE_TYPE_DMA:
261
		dma = &res->data.dma;
262 263 264 265 266 267 268
		if (dma->channel_count > 0) {
			flags = dma_flags(dma->type, dma->bus_master,
					  dma->transfer);
			if (dma->channels[0] == (u8) -1)
				flags |= IORESOURCE_DISABLED;
			pnp_add_dma_resource(dev, dma->channels[0], flags);
		}
L
Linus Torvalds 已提交
269
		break;
270

B
Bob Moore 已提交
271
	case ACPI_RESOURCE_TYPE_IO:
272
		io = &res->data.io;
273
		pnpacpi_parse_allocated_ioresource(dev,
274 275 276
			io->minimum,
			io->address_length,
			io->io_decode);
L
Linus Torvalds 已提交
277
		break;
278 279 280 281 282

	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
		break;

B
Bob Moore 已提交
283
	case ACPI_RESOURCE_TYPE_FIXED_IO:
284
		fixed_io = &res->data.fixed_io;
285
		pnpacpi_parse_allocated_ioresource(dev,
286 287
			fixed_io->address,
			fixed_io->address_length,
B
Bjorn Helgaas 已提交
288
			ACPI_DECODE_10);
L
Linus Torvalds 已提交
289
		break;
290 291 292 293 294 295 296

	case ACPI_RESOURCE_TYPE_VENDOR:
		break;

	case ACPI_RESOURCE_TYPE_END_TAG:
		break;

B
Bob Moore 已提交
297
	case ACPI_RESOURCE_TYPE_MEMORY24:
298
		memory24 = &res->data.memory24;
299
		pnpacpi_parse_allocated_memresource(dev,
300 301 302
			memory24->minimum,
			memory24->address_length,
			memory24->write_protect);
L
Linus Torvalds 已提交
303
		break;
B
Bob Moore 已提交
304
	case ACPI_RESOURCE_TYPE_MEMORY32:
305
		memory32 = &res->data.memory32;
306
		pnpacpi_parse_allocated_memresource(dev,
307 308 309
			memory32->minimum,
			memory32->address_length,
			memory32->write_protect);
L
Linus Torvalds 已提交
310
		break;
B
Bob Moore 已提交
311
	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
312
		fixed_memory32 = &res->data.fixed_memory32;
313
		pnpacpi_parse_allocated_memresource(dev,
314 315 316
			fixed_memory32->address,
			fixed_memory32->address_length,
			fixed_memory32->write_protect);
L
Linus Torvalds 已提交
317
		break;
B
Bob Moore 已提交
318 319 320
	case ACPI_RESOURCE_TYPE_ADDRESS16:
	case ACPI_RESOURCE_TYPE_ADDRESS32:
	case ACPI_RESOURCE_TYPE_ADDRESS64:
321
		pnpacpi_parse_allocated_address_space(dev, res);
L
Linus Torvalds 已提交
322
		break;
323 324

	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
325 326
		if (res->data.ext_address64.producer_consumer == ACPI_PRODUCER)
			return AE_OK;
327 328 329
		break;

	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
330 331
		extended_irq = &res->data.extended_irq;
		if (extended_irq->producer_consumer == ACPI_PRODUCER)
332 333
			return AE_OK;

334
		for (i = 0; i < extended_irq->interrupt_count; i++) {
335
			pnpacpi_parse_allocated_irqresource(dev,
336 337 338 339
				extended_irq->interrupts[i],
				extended_irq->triggering,
				extended_irq->polarity,
				extended_irq->sharable);
340 341 342 343
		}
		break;

	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
L
Linus Torvalds 已提交
344
		break;
345

L
Linus Torvalds 已提交
346
	default:
347 348
		dev_warn(&dev->dev, "unknown resource type %d in _CRS\n",
			 res->type);
L
Linus Torvalds 已提交
349 350
		return AE_ERROR;
	}
B
Bjorn Helgaas 已提交
351

L
Linus Torvalds 已提交
352 353 354
	return AE_OK;
}

355
int pnpacpi_parse_allocated_resource(struct pnp_dev *dev)
L
Linus Torvalds 已提交
356
{
357
	acpi_handle handle = dev->data;
358
	acpi_status status;
359

360 361
	dev_dbg(&dev->dev, "parse allocated resources\n");

362
	pnp_init_resources(dev);
L
Linus Torvalds 已提交
363

364 365 366 367 368 369 370 371 372
	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 已提交
373 374
}

375 376
static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
					    struct pnp_option *option,
377
					    struct acpi_resource_dma *p)
L
Linus Torvalds 已提交
378 379
{
	int i;
B
Bjorn Helgaas 已提交
380
	struct pnp_dma *dma;
L
Linus Torvalds 已提交
381

B
Bob Moore 已提交
382
	if (p->channel_count == 0)
L
Linus Torvalds 已提交
383
		return;
384
	dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
L
Linus Torvalds 已提交
385 386 387
	if (!dma)
		return;

B
Bjorn Helgaas 已提交
388
	for (i = 0; i < p->channel_count; i++)
L
Linus Torvalds 已提交
389
		dma->map |= 1 << p->channels[i];
390 391

	dma->flags = dma_flags(p->type, p->bus_master, p->transfer);
L
Linus Torvalds 已提交
392

393
	pnp_register_dma_resource(dev, option, dma);
L
Linus Torvalds 已提交
394 395
}

396 397
static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
					    struct pnp_option *option,
398
					    struct acpi_resource_irq *p)
L
Linus Torvalds 已提交
399 400
{
	int i;
B
Bjorn Helgaas 已提交
401 402
	struct pnp_irq *irq;

B
Bob Moore 已提交
403
	if (p->interrupt_count == 0)
L
Linus Torvalds 已提交
404
		return;
405
	irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
L
Linus Torvalds 已提交
406 407 408
	if (!irq)
		return;

B
Bjorn Helgaas 已提交
409
	for (i = 0; i < p->interrupt_count; i++)
L
Linus Torvalds 已提交
410 411
		if (p->interrupts[i])
			__set_bit(p->interrupts[i], irq->map);
412
	irq->flags = irq_flags(p->triggering, p->polarity, p->sharable);
L
Linus Torvalds 已提交
413

414
	pnp_register_irq_resource(dev, option, irq);
L
Linus Torvalds 已提交
415 416
}

417 418
static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
						struct pnp_option *option,
419
					struct acpi_resource_extended_irq *p)
L
Linus Torvalds 已提交
420 421
{
	int i;
B
Bjorn Helgaas 已提交
422
	struct pnp_irq *irq;
L
Linus Torvalds 已提交
423

B
Bob Moore 已提交
424
	if (p->interrupt_count == 0)
L
Linus Torvalds 已提交
425
		return;
426
	irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
L
Linus Torvalds 已提交
427 428 429
	if (!irq)
		return;

B
Bjorn Helgaas 已提交
430
	for (i = 0; i < p->interrupt_count; i++)
L
Linus Torvalds 已提交
431 432
		if (p->interrupts[i])
			__set_bit(p->interrupts[i], irq->map);
433
	irq->flags = irq_flags(p->triggering, p->polarity, p->sharable);
L
Linus Torvalds 已提交
434

435
	pnp_register_irq_resource(dev, option, irq);
L
Linus Torvalds 已提交
436 437
}

438 439
static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
					     struct pnp_option *option,
440
					     struct acpi_resource_io *io)
L
Linus Torvalds 已提交
441
{
B
Bjorn Helgaas 已提交
442
	struct pnp_port *port;
L
Linus Torvalds 已提交
443

B
Bob Moore 已提交
444
	if (io->address_length == 0)
L
Linus Torvalds 已提交
445
		return;
446
	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
L
Linus Torvalds 已提交
447 448
	if (!port)
		return;
B
Bob Moore 已提交
449 450
	port->min = io->minimum;
	port->max = io->maximum;
L
Linus Torvalds 已提交
451
	port->align = io->alignment;
B
Bob Moore 已提交
452 453
	port->size = io->address_length;
	port->flags = ACPI_DECODE_16 == io->io_decode ?
B
Bjorn Helgaas 已提交
454
	    PNP_PORT_FLAG_16BITADDR : 0;
455
	pnp_register_port_resource(dev, option, port);
L
Linus Torvalds 已提交
456 457
}

458 459
static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
						   struct pnp_option *option,
460
					struct acpi_resource_fixed_io *io)
L
Linus Torvalds 已提交
461
{
B
Bjorn Helgaas 已提交
462
	struct pnp_port *port;
L
Linus Torvalds 已提交
463

B
Bob Moore 已提交
464
	if (io->address_length == 0)
L
Linus Torvalds 已提交
465
		return;
466
	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
L
Linus Torvalds 已提交
467 468
	if (!port)
		return;
B
Bob Moore 已提交
469 470
	port->min = port->max = io->address;
	port->size = io->address_length;
L
Linus Torvalds 已提交
471 472
	port->align = 0;
	port->flags = PNP_PORT_FLAG_FIXED;
473
	pnp_register_port_resource(dev, option, port);
L
Linus Torvalds 已提交
474 475
}

476 477
static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
					      struct pnp_option *option,
478
					      struct acpi_resource_memory24 *p)
L
Linus Torvalds 已提交
479
{
B
Bjorn Helgaas 已提交
480
	struct pnp_mem *mem;
L
Linus Torvalds 已提交
481

B
Bob Moore 已提交
482
	if (p->address_length == 0)
L
Linus Torvalds 已提交
483
		return;
484
	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
L
Linus Torvalds 已提交
485 486
	if (!mem)
		return;
B
Bob Moore 已提交
487 488
	mem->min = p->minimum;
	mem->max = p->maximum;
L
Linus Torvalds 已提交
489
	mem->align = p->alignment;
B
Bob Moore 已提交
490
	mem->size = p->address_length;
L
Linus Torvalds 已提交
491

B
Bob Moore 已提交
492
	mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
B
Bjorn Helgaas 已提交
493
	    IORESOURCE_MEM_WRITEABLE : 0;
L
Linus Torvalds 已提交
494

495
	pnp_register_mem_resource(dev, option, mem);
L
Linus Torvalds 已提交
496 497
}

498 499
static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
					      struct pnp_option *option,
500
					      struct acpi_resource_memory32 *p)
L
Linus Torvalds 已提交
501
{
B
Bjorn Helgaas 已提交
502
	struct pnp_mem *mem;
L
Linus Torvalds 已提交
503

B
Bob Moore 已提交
504
	if (p->address_length == 0)
L
Linus Torvalds 已提交
505
		return;
506
	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
L
Linus Torvalds 已提交
507 508
	if (!mem)
		return;
B
Bob Moore 已提交
509 510
	mem->min = p->minimum;
	mem->max = p->maximum;
L
Linus Torvalds 已提交
511
	mem->align = p->alignment;
B
Bob Moore 已提交
512
	mem->size = p->address_length;
L
Linus Torvalds 已提交
513

B
Bob Moore 已提交
514
	mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
B
Bjorn Helgaas 已提交
515
	    IORESOURCE_MEM_WRITEABLE : 0;
L
Linus Torvalds 已提交
516

517
	pnp_register_mem_resource(dev, option, mem);
L
Linus Torvalds 已提交
518 519
}

520 521
static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
						    struct pnp_option *option,
522
					struct acpi_resource_fixed_memory32 *p)
L
Linus Torvalds 已提交
523
{
B
Bjorn Helgaas 已提交
524
	struct pnp_mem *mem;
L
Linus Torvalds 已提交
525

B
Bob Moore 已提交
526
	if (p->address_length == 0)
L
Linus Torvalds 已提交
527
		return;
528
	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
L
Linus Torvalds 已提交
529 530
	if (!mem)
		return;
B
Bob Moore 已提交
531 532
	mem->min = mem->max = p->address;
	mem->size = p->address_length;
L
Linus Torvalds 已提交
533 534
	mem->align = 0;

B
Bob Moore 已提交
535
	mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
B
Bjorn Helgaas 已提交
536
	    IORESOURCE_MEM_WRITEABLE : 0;
L
Linus Torvalds 已提交
537

538
	pnp_register_mem_resource(dev, option, mem);
L
Linus Torvalds 已提交
539 540
}

541 542
static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
						struct pnp_option *option,
543
						struct acpi_resource *r)
544 545 546
{
	struct acpi_resource_address64 addr, *p = &addr;
	acpi_status status;
B
Bjorn Helgaas 已提交
547 548
	struct pnp_mem *mem;
	struct pnp_port *port;
549 550 551

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

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

	if (p->resource_type == ACPI_MEMORY_RANGE) {
561
		mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
562 563
		if (!mem)
			return;
L
Len Brown 已提交
564
		mem->min = mem->max = p->minimum;
565 566
		mem->size = p->address_length;
		mem->align = 0;
L
Len Brown 已提交
567
		mem->flags = (p->info.mem.write_protect ==
B
Bjorn Helgaas 已提交
568 569
			      ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE
		    : 0;
570
		pnp_register_mem_resource(dev, option, mem);
571
	} else if (p->resource_type == ACPI_IO_RANGE) {
572
		port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
573 574
		if (!port)
			return;
L
Len Brown 已提交
575
		port->min = port->max = p->minimum;
576 577 578
		port->size = p->address_length;
		port->align = 0;
		port->flags = PNP_PORT_FLAG_FIXED;
579
		pnp_register_port_resource(dev, option, port);
580 581 582
	}
}

L
Linus Torvalds 已提交
583 584
struct acpipnp_parse_option_s {
	struct pnp_option *option;
M
Matthieu Castet 已提交
585
	struct pnp_option *option_independent;
L
Linus Torvalds 已提交
586 587 588
	struct pnp_dev *dev;
};

589 590
static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
						  void *data)
L
Linus Torvalds 已提交
591 592
{
	int priority = 0;
593
	struct acpipnp_parse_option_s *parse_data = data;
L
Linus Torvalds 已提交
594 595 596
	struct pnp_dev *dev = parse_data->dev;
	struct pnp_option *option = parse_data->option;

597
	switch (res->type) {
B
Bjorn Helgaas 已提交
598
	case ACPI_RESOURCE_TYPE_IRQ:
599
		pnpacpi_parse_irq_option(dev, option, &res->data.irq);
B
Bjorn Helgaas 已提交
600
		break;
601

B
Bjorn Helgaas 已提交
602
	case ACPI_RESOURCE_TYPE_DMA:
603
		pnpacpi_parse_dma_option(dev, option, &res->data.dma);
B
Bjorn Helgaas 已提交
604
		break;
605

B
Bjorn Helgaas 已提交
606 607 608 609
	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 已提交
610
			break;
611

B
Bjorn Helgaas 已提交
612 613
		case ACPI_ACCEPTABLE_CONFIGURATION:
			priority = PNP_RES_PRIORITY_ACCEPTABLE;
M
Matthieu Castet 已提交
614
			break;
615

B
Bjorn Helgaas 已提交
616 617
		case ACPI_SUB_OPTIMAL_CONFIGURATION:
			priority = PNP_RES_PRIORITY_FUNCTIONAL;
618
			break;
B
Bjorn Helgaas 已提交
619 620
		default:
			priority = PNP_RES_PRIORITY_INVALID;
621
			break;
B
Bjorn Helgaas 已提交
622
		}
B
Bjorn Helgaas 已提交
623
		/* TBD: Consider performance/robustness bits */
B
Bjorn Helgaas 已提交
624 625 626 627 628
		option = pnp_register_dependent_option(dev, priority);
		if (!option)
			return AE_ERROR;
		parse_data->option = option;
		break;
629

B
Bjorn Helgaas 已提交
630 631 632
	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
		/*only one EndDependentFn is allowed */
		if (!parse_data->option_independent) {
633 634
			dev_warn(&dev->dev, "more than one EndDependentFn "
				 "in _PRS\n");
B
Bjorn Helgaas 已提交
635 636 637 638
			return AE_ERROR;
		}
		parse_data->option = parse_data->option_independent;
		parse_data->option_independent = NULL;
639
		dev_dbg(&dev->dev, "end dependent options\n");
B
Bjorn Helgaas 已提交
640
		break;
641

B
Bjorn Helgaas 已提交
642
	case ACPI_RESOURCE_TYPE_IO:
643
		pnpacpi_parse_port_option(dev, option, &res->data.io);
B
Bjorn Helgaas 已提交
644
		break;
645

B
Bjorn Helgaas 已提交
646
	case ACPI_RESOURCE_TYPE_FIXED_IO:
647 648
		pnpacpi_parse_fixed_port_option(dev, option,
					        &res->data.fixed_io);
B
Bjorn Helgaas 已提交
649
		break;
650

B
Bjorn Helgaas 已提交
651 652 653
	case ACPI_RESOURCE_TYPE_VENDOR:
	case ACPI_RESOURCE_TYPE_END_TAG:
		break;
654

B
Bjorn Helgaas 已提交
655
	case ACPI_RESOURCE_TYPE_MEMORY24:
656
		pnpacpi_parse_mem24_option(dev, option, &res->data.memory24);
B
Bjorn Helgaas 已提交
657
		break;
658

B
Bjorn Helgaas 已提交
659
	case ACPI_RESOURCE_TYPE_MEMORY32:
660
		pnpacpi_parse_mem32_option(dev, option, &res->data.memory32);
B
Bjorn Helgaas 已提交
661
		break;
662

B
Bjorn Helgaas 已提交
663
	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
664
		pnpacpi_parse_fixed_mem32_option(dev, option,
B
Bjorn Helgaas 已提交
665 666
						 &res->data.fixed_memory32);
		break;
667

B
Bjorn Helgaas 已提交
668 669 670
	case ACPI_RESOURCE_TYPE_ADDRESS16:
	case ACPI_RESOURCE_TYPE_ADDRESS32:
	case ACPI_RESOURCE_TYPE_ADDRESS64:
671
		pnpacpi_parse_address_option(dev, option, res);
B
Bjorn Helgaas 已提交
672
		break;
673

B
Bjorn Helgaas 已提交
674 675 676 677
	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
		break;

	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
678 679
		pnpacpi_parse_ext_irq_option(dev, option,
					     &res->data.extended_irq);
B
Bjorn Helgaas 已提交
680 681 682 683 684 685
		break;

	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
		break;

	default:
686 687
		dev_warn(&dev->dev, "unknown resource type %d in _PRS\n",
			 res->type);
B
Bjorn Helgaas 已提交
688
		return AE_ERROR;
L
Linus Torvalds 已提交
689
	}
B
Bjorn Helgaas 已提交
690

L
Linus Torvalds 已提交
691 692 693
	return AE_OK;
}

694
int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)
L
Linus Torvalds 已提交
695
{
696
	acpi_handle handle = dev->data;
L
Linus Torvalds 已提交
697 698 699
	acpi_status status;
	struct acpipnp_parse_option_s parse_data;

700 701
	dev_dbg(&dev->dev, "parse resource options\n");

L
Linus Torvalds 已提交
702 703
	parse_data.option = pnp_register_independent_option(dev);
	if (!parse_data.option)
704 705
		return -ENOMEM;

M
Matthieu Castet 已提交
706
	parse_data.option_independent = parse_data.option;
L
Linus Torvalds 已提交
707
	parse_data.dev = dev;
B
Bob Moore 已提交
708
	status = acpi_walk_resources(handle, METHOD_NAME__PRS,
B
Bjorn Helgaas 已提交
709
				     pnpacpi_option_resource, &parse_data);
L
Linus Torvalds 已提交
710

711 712 713 714 715 716
	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 已提交
717 718
}

719
static int pnpacpi_supported_resource(struct acpi_resource *res)
L
Linus Torvalds 已提交
720
{
721
	switch (res->type) {
B
Bob Moore 已提交
722 723 724 725 726 727 728 729 730 731
	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:
732
	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
733
		return 1;
L
Linus Torvalds 已提交
734
	}
735 736 737 738 739 740 741
	return 0;
}

/*
 * Set resource
 */
static acpi_status pnpacpi_count_resources(struct acpi_resource *res,
B
Bjorn Helgaas 已提交
742
					   void *data)
743
{
744
	int *res_cnt = data;
745 746 747

	if (pnpacpi_supported_resource(res))
		(*res_cnt)++;
L
Linus Torvalds 已提交
748 749 750
	return AE_OK;
}

B
Bjorn Helgaas 已提交
751
static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data)
L
Linus Torvalds 已提交
752
{
753
	struct acpi_resource **resource = data;
754 755

	if (pnpacpi_supported_resource(res)) {
756
		(*resource)->type = res->type;
757
		(*resource)->length = sizeof(struct acpi_resource);
L
Linus Torvalds 已提交
758 759 760 761 762 763
		(*resource)++;
	}

	return AE_OK;
}

764
int pnpacpi_build_resource_template(struct pnp_dev *dev,
B
Bjorn Helgaas 已提交
765
				    struct acpi_buffer *buffer)
L
Linus Torvalds 已提交
766
{
767
	acpi_handle handle = dev->data;
L
Linus Torvalds 已提交
768 769 770 771
	struct acpi_resource *resource;
	int res_cnt = 0;
	acpi_status status;

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

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

	return 0;
}

799 800
static void pnpacpi_encode_irq(struct pnp_dev *dev,
			       struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
801
			       struct resource *p)
L
Linus Torvalds 已提交
802
{
803
	struct acpi_resource_irq *irq = &resource->data.irq;
804
	int triggering, polarity, shareable;
B
Bjorn Helgaas 已提交
805

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 815 816

	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",
		irq->sharable == ACPI_SHARED ? "shared" : "exclusive");
L
Linus Torvalds 已提交
817 818
}

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

826
	decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
827 828 829
	extended_irq->producer_consumer = ACPI_CONSUMER;
	extended_irq->triggering = triggering;
	extended_irq->polarity = polarity;
830
	extended_irq->sharable = shareable;
831 832
	extended_irq->interrupt_count = 1;
	extended_irq->interrupts[0] = p->start;
833 834 835 836 837

	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 已提交
838 839
}

840 841
static void pnpacpi_encode_dma(struct pnp_dev *dev,
			       struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
842
			       struct resource *p)
L
Linus Torvalds 已提交
843
{
844 845
	struct acpi_resource_dma *dma = &resource->data.dma;

L
Linus Torvalds 已提交
846
	/* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
847
	switch (p->flags & IORESOURCE_DMA_SPEED_MASK) {
B
Bjorn Helgaas 已提交
848
	case IORESOURCE_DMA_TYPEA:
849
		dma->type = ACPI_TYPE_A;
B
Bjorn Helgaas 已提交
850 851
		break;
	case IORESOURCE_DMA_TYPEB:
852
		dma->type = ACPI_TYPE_B;
B
Bjorn Helgaas 已提交
853 854
		break;
	case IORESOURCE_DMA_TYPEF:
855
		dma->type = ACPI_TYPE_F;
B
Bjorn Helgaas 已提交
856 857
		break;
	default:
858
		dma->type = ACPI_COMPATIBILITY;
859 860 861
	}

	switch (p->flags & IORESOURCE_DMA_TYPE_MASK) {
B
Bjorn Helgaas 已提交
862
	case IORESOURCE_DMA_8BIT:
863
		dma->transfer = ACPI_TRANSFER_8;
B
Bjorn Helgaas 已提交
864 865
		break;
	case IORESOURCE_DMA_8AND16BIT:
866
		dma->transfer = ACPI_TRANSFER_8_16;
B
Bjorn Helgaas 已提交
867 868
		break;
	default:
869
		dma->transfer = ACPI_TRANSFER_16;
870 871
	}

872 873 874
	dma->bus_master = !!(p->flags & IORESOURCE_DMA_MASTER);
	dma->channel_count = 1;
	dma->channels[0] = p->start;
875 876 877 878

	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 已提交
879 880
}

881 882
static void pnpacpi_encode_io(struct pnp_dev *dev,
			      struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
883
			      struct resource *p)
L
Linus Torvalds 已提交
884
{
885 886
	struct acpi_resource_io *io = &resource->data.io;

L
Linus Torvalds 已提交
887
	/* Note: pnp_assign_port will copy pnp_port->flags into p->flags */
888
	io->io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ?
B
Bjorn Helgaas 已提交
889
	    ACPI_DECODE_16 : ACPI_DECODE_10;
890 891 892 893
	io->minimum = p->start;
	io->maximum = p->end;
	io->alignment = 0;	/* Correct? */
	io->address_length = p->end - p->start + 1;
894 895 896 897

	dev_dbg(&dev->dev, "  encode io %#llx-%#llx decode %#x\n",
		(unsigned long long) p->start, (unsigned long long) p->end,
		io->io_decode);
L
Linus Torvalds 已提交
898 899
}

900 901
static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
				    struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
902
				    struct resource *p)
L
Linus Torvalds 已提交
903
{
904 905 906 907
	struct acpi_resource_fixed_io *fixed_io = &resource->data.fixed_io;

	fixed_io->address = p->start;
	fixed_io->address_length = p->end - p->start + 1;
908 909 910

	dev_dbg(&dev->dev, "  encode fixed_io %#llx-%#llx\n",
		(unsigned long long) p->start, (unsigned long long) p->end);
L
Linus Torvalds 已提交
911 912
}

913 914
static void pnpacpi_encode_mem24(struct pnp_dev *dev,
				 struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
915
				 struct resource *p)
L
Linus Torvalds 已提交
916
{
917 918
	struct acpi_resource_memory24 *memory24 = &resource->data.memory24;

L
Linus Torvalds 已提交
919
	/* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */
920
	memory24->write_protect =
B
Bjorn Helgaas 已提交
921 922
	    (p->flags & IORESOURCE_MEM_WRITEABLE) ?
	    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
923 924 925 926
	memory24->minimum = p->start;
	memory24->maximum = p->end;
	memory24->alignment = 0;
	memory24->address_length = p->end - p->start + 1;
927 928 929 930

	dev_dbg(&dev->dev, "  encode mem24 %#llx-%#llx write_protect %#x\n",
		(unsigned long long) p->start, (unsigned long long) p->end,
		memory24->write_protect);
L
Linus Torvalds 已提交
931 932
}

933 934
static void pnpacpi_encode_mem32(struct pnp_dev *dev,
				 struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
935
				 struct resource *p)
L
Linus Torvalds 已提交
936
{
937 938 939
	struct acpi_resource_memory32 *memory32 = &resource->data.memory32;

	memory32->write_protect =
B
Bjorn Helgaas 已提交
940 941
	    (p->flags & IORESOURCE_MEM_WRITEABLE) ?
	    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
942 943 944 945
	memory32->minimum = p->start;
	memory32->maximum = p->end;
	memory32->alignment = 0;
	memory32->address_length = p->end - p->start + 1;
946 947 948 949

	dev_dbg(&dev->dev, "  encode mem32 %#llx-%#llx write_protect %#x\n",
		(unsigned long long) p->start, (unsigned long long) p->end,
		memory32->write_protect);
L
Linus Torvalds 已提交
950 951
}

952 953
static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev,
				       struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
954
				       struct resource *p)
L
Linus Torvalds 已提交
955
{
956 957 958
	struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32;

	fixed_memory32->write_protect =
B
Bjorn Helgaas 已提交
959 960
	    (p->flags & IORESOURCE_MEM_WRITEABLE) ?
	    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
961 962
	fixed_memory32->address = p->start;
	fixed_memory32->address_length = p->end - p->start + 1;
963 964 965 966 967

	dev_dbg(&dev->dev, "  encode fixed_mem32 %#llx-%#llx "
		"write_protect %#x\n",
		(unsigned long long) p->start, (unsigned long long) p->end,
		fixed_memory32->write_protect);
L
Linus Torvalds 已提交
968 969
}

970
int pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer)
L
Linus Torvalds 已提交
971 972 973
{
	int i = 0;
	/* pnpacpi_build_resource_template allocates extra mem */
B
Bjorn Helgaas 已提交
974
	int res_cnt = (buffer->length - 1) / sizeof(struct acpi_resource) - 1;
975
	struct acpi_resource *resource = buffer->pointer;
L
Linus Torvalds 已提交
976 977
	int port = 0, irq = 0, dma = 0, mem = 0;

978
	dev_dbg(&dev->dev, "encode %d resources\n", res_cnt);
L
Linus Torvalds 已提交
979
	while (i < res_cnt) {
B
Bjorn Helgaas 已提交
980
		switch (resource->type) {
B
Bob Moore 已提交
981
		case ACPI_RESOURCE_TYPE_IRQ:
982
			pnpacpi_encode_irq(dev, resource,
983
			       pnp_get_resource(dev, IORESOURCE_IRQ, irq));
L
Linus Torvalds 已提交
984 985 986
			irq++;
			break;

B
Bob Moore 已提交
987
		case ACPI_RESOURCE_TYPE_DMA:
988
			pnpacpi_encode_dma(dev, resource,
989
				pnp_get_resource(dev, IORESOURCE_DMA, dma));
B
Bjorn Helgaas 已提交
990
			dma++;
L
Linus Torvalds 已提交
991
			break;
B
Bob Moore 已提交
992
		case ACPI_RESOURCE_TYPE_IO:
993
			pnpacpi_encode_io(dev, resource,
994
				pnp_get_resource(dev, IORESOURCE_IO, port));
B
Bjorn Helgaas 已提交
995
			port++;
L
Linus Torvalds 已提交
996
			break;
B
Bob Moore 已提交
997
		case ACPI_RESOURCE_TYPE_FIXED_IO:
998
			pnpacpi_encode_fixed_io(dev, resource,
999
				pnp_get_resource(dev, IORESOURCE_IO, port));
B
Bjorn Helgaas 已提交
1000
			port++;
L
Linus Torvalds 已提交
1001
			break;
B
Bob Moore 已提交
1002
		case ACPI_RESOURCE_TYPE_MEMORY24:
1003
			pnpacpi_encode_mem24(dev, resource,
1004
				pnp_get_resource(dev, IORESOURCE_MEM, mem));
B
Bjorn Helgaas 已提交
1005
			mem++;
L
Linus Torvalds 已提交
1006
			break;
B
Bob Moore 已提交
1007
		case ACPI_RESOURCE_TYPE_MEMORY32:
1008
			pnpacpi_encode_mem32(dev, resource,
1009
				pnp_get_resource(dev, IORESOURCE_MEM, mem));
B
Bjorn Helgaas 已提交
1010
			mem++;
L
Linus Torvalds 已提交
1011
			break;
B
Bob Moore 已提交
1012
		case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
1013
			pnpacpi_encode_fixed_mem32(dev, resource,
1014
				pnp_get_resource(dev, IORESOURCE_MEM, mem));
B
Bjorn Helgaas 已提交
1015
			mem++;
L
Linus Torvalds 已提交
1016
			break;
1017
		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
1018
			pnpacpi_encode_ext_irq(dev, resource,
1019
				pnp_get_resource(dev, IORESOURCE_IRQ, irq));
1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
			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 已提交
1031
		default:	/* other type */
1032 1033
			dev_warn(&dev->dev, "can't encode unknown resource "
				 "type %d\n", resource->type);
L
Linus Torvalds 已提交
1034 1035
			return -EINVAL;
		}
B
Bjorn Helgaas 已提交
1036 1037
		resource++;
		i++;
L
Linus Torvalds 已提交
1038 1039 1040
	}
	return 0;
}