rsparser.c 27.2 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 54 55 56

	if (shareable)
		flags |= IORESOURCE_IRQ_SHAREABLE;

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

B
Bob Moore 已提交
59
static void decode_irq_flags(int flag, int *triggering, int *polarity)
L
Linus Torvalds 已提交
60 61 62
{
	switch (flag) {
	case IORESOURCE_IRQ_LOWLEVEL:
B
Bob Moore 已提交
63 64
		*triggering = ACPI_LEVEL_SENSITIVE;
		*polarity = ACPI_ACTIVE_LOW;
L
Linus Torvalds 已提交
65
		break;
B
Bjorn Helgaas 已提交
66
	case IORESOURCE_IRQ_HIGHLEVEL:
B
Bob Moore 已提交
67 68
		*triggering = ACPI_LEVEL_SENSITIVE;
		*polarity = ACPI_ACTIVE_HIGH;
L
Linus Torvalds 已提交
69 70
		break;
	case IORESOURCE_IRQ_LOWEDGE:
B
Bob Moore 已提交
71 72
		*triggering = ACPI_EDGE_SENSITIVE;
		*polarity = ACPI_ACTIVE_LOW;
L
Linus Torvalds 已提交
73 74
		break;
	case IORESOURCE_IRQ_HIGHEDGE:
B
Bob Moore 已提交
75 76
		*triggering = ACPI_EDGE_SENSITIVE;
		*polarity = ACPI_ACTIVE_HIGH;
L
Linus Torvalds 已提交
77 78 79 80
		break;
	}
}

81
static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
B
Bjorn Helgaas 已提交
82 83
						u32 gsi, int triggering,
						int polarity, int shareable)
L
Linus Torvalds 已提交
84
{
85
	int irq, flags;
86
	int p, t;
87 88 89 90

	if (!valid_IRQ(gsi))
		return;

91 92 93 94 95 96 97 98 99 100
	/*
	 * 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) {
101
			dev_warn(&dev->dev, "IRQ %d override to %s, %s\n",
102 103 104 105 106 107
				gsi, t ? "edge":"level", p ? "low":"high");
			triggering = t;
			polarity = p;
		}
	}

108
	flags = irq_flags(triggering, polarity, shareable);
B
Bob Moore 已提交
109
	irq = acpi_register_gsi(gsi, triggering, polarity);
110 111 112 113
	if (irq >= 0)
		pcibios_penalize_isa_irq(irq, 1);
	else
		flags |= IORESOURCE_DISABLED;
114

115
	pnp_add_irq_resource(dev, irq, flags);
L
Linus Torvalds 已提交
116 117
}

118 119 120 121 122 123 124 125 126 127 128 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
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;
}

161
static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev,
B
Bjorn Helgaas 已提交
162
					       u64 io, u64 len, int io_decode)
L
Linus Torvalds 已提交
163
{
164 165
	struct resource *res;
	int i;
166
	static unsigned char warned;
B
Bjorn Helgaas 已提交
167

168 169 170 171 172
	for (i = 0; i < PNP_MAX_PORT; i++) {
		res = pnp_get_resource(dev, IORESOURCE_IO, i);
		if (!pnp_resource_valid(res))
			break;
	}
L
Linus Torvalds 已提交
173
	if (i < PNP_MAX_PORT) {
174
		res->flags = IORESOURCE_IO;	// Also clears _UNSET flag
175
		if (io_decode == ACPI_DECODE_16)
176
			res->flags |= PNP_PORT_FLAG_16BITADDR;
B
Bjorn Helgaas 已提交
177
		if (len <= 0 || (io + len - 1) >= 0x10003) {
178
			res->flags |= IORESOURCE_DISABLED;
L
Linus Torvalds 已提交
179 180
			return;
		}
181 182
		res->start = io;
		res->end = io + len - 1;
183
	} else if (!warned) {
184
		printk(KERN_WARNING "pnpacpi: exceeded the max number of IO "
185
				"resources: %d \n", PNP_MAX_PORT);
186
		warned = 1;
L
Linus Torvalds 已提交
187 188 189
	}
}

190
static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
B
Bjorn Helgaas 已提交
191 192
						u64 mem, u64 len,
						int write_protect)
L
Linus Torvalds 已提交
193
{
194 195
	struct resource *res;
	int i;
196
	static unsigned char warned;
B
Bjorn Helgaas 已提交
197

198 199 200 201 202
	for (i = 0; i < PNP_MAX_MEM; i++) {
		res = pnp_get_resource(dev, IORESOURCE_MEM, i);
		if (!pnp_resource_valid(res))
			break;
	}
L
Linus Torvalds 已提交
203
	if (i < PNP_MAX_MEM) {
204
		res->flags = IORESOURCE_MEM;	// Also clears _UNSET flag
L
Linus Torvalds 已提交
205
		if (len <= 0) {
206
			res->flags |= IORESOURCE_DISABLED;
L
Linus Torvalds 已提交
207 208
			return;
		}
B
Bjorn Helgaas 已提交
209
		if (write_protect == ACPI_READ_WRITE_MEMORY)
210
			res->flags |= IORESOURCE_MEM_WRITEABLE;
211

212 213
		res->start = mem;
		res->end = mem + len - 1;
214
	} else if (!warned) {
215
		printk(KERN_WARNING "pnpacpi: exceeded the max number of mem "
216
				"resources: %d\n", PNP_MAX_MEM);
217
		warned = 1;
L
Linus Torvalds 已提交
218 219 220
	}
}

221
static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
B
Bjorn Helgaas 已提交
222
						  struct acpi_resource *res)
223 224 225 226 227 228
{
	struct acpi_resource_address64 addr, *p = &addr;
	acpi_status status;

	status = acpi_resource_to_address64(res, p);
	if (!ACPI_SUCCESS(status)) {
229
		dev_warn(&dev->dev, "failed to convert resource type %d\n",
B
Bjorn Helgaas 已提交
230
			 res->type);
231 232 233
		return;
	}

234 235 236
	if (p->producer_consumer == ACPI_PRODUCER)
		return;

237
	if (p->resource_type == ACPI_MEMORY_RANGE)
238
		pnpacpi_parse_allocated_memresource(dev,
B
Bjorn Helgaas 已提交
239 240
			p->minimum, p->address_length,
			p->info.mem.write_protect);
241
	else if (p->resource_type == ACPI_IO_RANGE)
242
		pnpacpi_parse_allocated_ioresource(dev,
B
Bjorn Helgaas 已提交
243 244 245
			p->minimum, p->address_length,
			p->granularity == 0xfff ? ACPI_DECODE_10 :
				ACPI_DECODE_16);
246
}
L
Linus Torvalds 已提交
247 248

static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
B
Bjorn Helgaas 已提交
249
					      void *data)
L
Linus Torvalds 已提交
250
{
251
	struct pnp_dev *dev = data;
252 253 254 255 256 257 258 259
	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;
260
	int i, flags;
L
Linus Torvalds 已提交
261

262
	switch (res->type) {
B
Bob Moore 已提交
263
	case ACPI_RESOURCE_TYPE_IRQ:
264 265 266 267
		/*
		 * Per spec, only one interrupt per descriptor is allowed in
		 * _CRS, but some firmware violates this, so parse them all.
		 */
268 269
		irq = &res->data.irq;
		for (i = 0; i < irq->interrupt_count; i++) {
270
			pnpacpi_parse_allocated_irqresource(dev,
271 272 273 274
				irq->interrupts[i],
				irq->triggering,
				irq->polarity,
				irq->sharable);
L
Linus Torvalds 已提交
275 276 277
		}
		break;

B
Bob Moore 已提交
278
	case ACPI_RESOURCE_TYPE_DMA:
279
		dma = &res->data.dma;
280 281 282 283 284 285 286
		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 已提交
287
		break;
288

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

	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
		break;

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

	case ACPI_RESOURCE_TYPE_VENDOR:
		break;

	case ACPI_RESOURCE_TYPE_END_TAG:
		break;

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

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

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

352
		for (i = 0; i < extended_irq->interrupt_count; i++) {
353
			pnpacpi_parse_allocated_irqresource(dev,
354 355 356 357
				extended_irq->interrupts[i],
				extended_irq->triggering,
				extended_irq->polarity,
				extended_irq->sharable);
358 359 360 361
		}
		break;

	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
L
Linus Torvalds 已提交
362
		break;
363

L
Linus Torvalds 已提交
364
	default:
365 366
		dev_warn(&dev->dev, "unknown resource type %d in _CRS\n",
			 res->type);
L
Linus Torvalds 已提交
367 368
		return AE_ERROR;
	}
B
Bjorn Helgaas 已提交
369

L
Linus Torvalds 已提交
370 371 372
	return AE_OK;
}

373
acpi_status pnpacpi_parse_allocated_resource(struct pnp_dev *dev)
L
Linus Torvalds 已提交
374
{
375 376
	acpi_handle handle = dev->data;

377 378
	dev_dbg(&dev->dev, "parse allocated resources\n");

379
	pnp_init_resources(dev);
L
Linus Torvalds 已提交
380

B
Bjorn Helgaas 已提交
381
	return acpi_walk_resources(handle, METHOD_NAME__CRS,
382
				   pnpacpi_allocated_resource, dev);
L
Linus Torvalds 已提交
383 384
}

385 386
static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
					    struct pnp_option *option,
387
					    struct acpi_resource_dma *p)
L
Linus Torvalds 已提交
388 389
{
	int i;
B
Bjorn Helgaas 已提交
390
	struct pnp_dma *dma;
L
Linus Torvalds 已提交
391

B
Bob Moore 已提交
392
	if (p->channel_count == 0)
L
Linus Torvalds 已提交
393
		return;
394
	dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
L
Linus Torvalds 已提交
395 396 397
	if (!dma)
		return;

B
Bjorn Helgaas 已提交
398
	for (i = 0; i < p->channel_count; i++)
L
Linus Torvalds 已提交
399
		dma->map |= 1 << p->channels[i];
400 401

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

403
	pnp_register_dma_resource(dev, option, dma);
L
Linus Torvalds 已提交
404 405
}

406 407
static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
					    struct pnp_option *option,
408
					    struct acpi_resource_irq *p)
L
Linus Torvalds 已提交
409 410
{
	int i;
B
Bjorn Helgaas 已提交
411 412
	struct pnp_irq *irq;

B
Bob Moore 已提交
413
	if (p->interrupt_count == 0)
L
Linus Torvalds 已提交
414
		return;
415
	irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
L
Linus Torvalds 已提交
416 417 418
	if (!irq)
		return;

B
Bjorn Helgaas 已提交
419
	for (i = 0; i < p->interrupt_count; i++)
L
Linus Torvalds 已提交
420 421
		if (p->interrupts[i])
			__set_bit(p->interrupts[i], irq->map);
422
	irq->flags = irq_flags(p->triggering, p->polarity, p->sharable);
L
Linus Torvalds 已提交
423

424
	pnp_register_irq_resource(dev, option, irq);
L
Linus Torvalds 已提交
425 426
}

427 428
static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
						struct pnp_option *option,
429
					struct acpi_resource_extended_irq *p)
L
Linus Torvalds 已提交
430 431
{
	int i;
B
Bjorn Helgaas 已提交
432
	struct pnp_irq *irq;
L
Linus Torvalds 已提交
433

B
Bob Moore 已提交
434
	if (p->interrupt_count == 0)
L
Linus Torvalds 已提交
435
		return;
436
	irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
L
Linus Torvalds 已提交
437 438 439
	if (!irq)
		return;

B
Bjorn Helgaas 已提交
440
	for (i = 0; i < p->interrupt_count; i++)
L
Linus Torvalds 已提交
441 442
		if (p->interrupts[i])
			__set_bit(p->interrupts[i], irq->map);
443
	irq->flags = irq_flags(p->triggering, p->polarity, p->sharable);
L
Linus Torvalds 已提交
444

445
	pnp_register_irq_resource(dev, option, irq);
L
Linus Torvalds 已提交
446 447
}

448 449
static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
					     struct pnp_option *option,
450
					     struct acpi_resource_io *io)
L
Linus Torvalds 已提交
451
{
B
Bjorn Helgaas 已提交
452
	struct pnp_port *port;
L
Linus Torvalds 已提交
453

B
Bob Moore 已提交
454
	if (io->address_length == 0)
L
Linus Torvalds 已提交
455
		return;
456
	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
L
Linus Torvalds 已提交
457 458
	if (!port)
		return;
B
Bob Moore 已提交
459 460
	port->min = io->minimum;
	port->max = io->maximum;
L
Linus Torvalds 已提交
461
	port->align = io->alignment;
B
Bob Moore 已提交
462 463
	port->size = io->address_length;
	port->flags = ACPI_DECODE_16 == io->io_decode ?
B
Bjorn Helgaas 已提交
464
	    PNP_PORT_FLAG_16BITADDR : 0;
465
	pnp_register_port_resource(dev, option, port);
L
Linus Torvalds 已提交
466 467
}

468 469
static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
						   struct pnp_option *option,
470
					struct acpi_resource_fixed_io *io)
L
Linus Torvalds 已提交
471
{
B
Bjorn Helgaas 已提交
472
	struct pnp_port *port;
L
Linus Torvalds 已提交
473

B
Bob Moore 已提交
474
	if (io->address_length == 0)
L
Linus Torvalds 已提交
475
		return;
476
	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
L
Linus Torvalds 已提交
477 478
	if (!port)
		return;
B
Bob Moore 已提交
479 480
	port->min = port->max = io->address;
	port->size = io->address_length;
L
Linus Torvalds 已提交
481 482
	port->align = 0;
	port->flags = PNP_PORT_FLAG_FIXED;
483
	pnp_register_port_resource(dev, option, port);
L
Linus Torvalds 已提交
484 485
}

486 487
static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
					      struct pnp_option *option,
488
					      struct acpi_resource_memory24 *p)
L
Linus Torvalds 已提交
489
{
B
Bjorn Helgaas 已提交
490
	struct pnp_mem *mem;
L
Linus Torvalds 已提交
491

B
Bob Moore 已提交
492
	if (p->address_length == 0)
L
Linus Torvalds 已提交
493
		return;
494
	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
L
Linus Torvalds 已提交
495 496
	if (!mem)
		return;
B
Bob Moore 已提交
497 498
	mem->min = p->minimum;
	mem->max = p->maximum;
L
Linus Torvalds 已提交
499
	mem->align = p->alignment;
B
Bob Moore 已提交
500
	mem->size = p->address_length;
L
Linus Torvalds 已提交
501

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

505
	pnp_register_mem_resource(dev, option, mem);
L
Linus Torvalds 已提交
506 507
}

508 509
static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
					      struct pnp_option *option,
510
					      struct acpi_resource_memory32 *p)
L
Linus Torvalds 已提交
511
{
B
Bjorn Helgaas 已提交
512
	struct pnp_mem *mem;
L
Linus Torvalds 已提交
513

B
Bob Moore 已提交
514
	if (p->address_length == 0)
L
Linus Torvalds 已提交
515
		return;
516
	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
L
Linus Torvalds 已提交
517 518
	if (!mem)
		return;
B
Bob Moore 已提交
519 520
	mem->min = p->minimum;
	mem->max = p->maximum;
L
Linus Torvalds 已提交
521
	mem->align = p->alignment;
B
Bob Moore 已提交
522
	mem->size = p->address_length;
L
Linus Torvalds 已提交
523

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

527
	pnp_register_mem_resource(dev, option, mem);
L
Linus Torvalds 已提交
528 529
}

530 531
static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
						    struct pnp_option *option,
532
					struct acpi_resource_fixed_memory32 *p)
L
Linus Torvalds 已提交
533
{
B
Bjorn Helgaas 已提交
534
	struct pnp_mem *mem;
L
Linus Torvalds 已提交
535

B
Bob Moore 已提交
536
	if (p->address_length == 0)
L
Linus Torvalds 已提交
537
		return;
538
	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
L
Linus Torvalds 已提交
539 540
	if (!mem)
		return;
B
Bob Moore 已提交
541 542
	mem->min = mem->max = p->address;
	mem->size = p->address_length;
L
Linus Torvalds 已提交
543 544
	mem->align = 0;

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

548
	pnp_register_mem_resource(dev, option, mem);
L
Linus Torvalds 已提交
549 550
}

551 552
static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
						struct pnp_option *option,
553
						struct acpi_resource *r)
554 555 556
{
	struct acpi_resource_address64 addr, *p = &addr;
	acpi_status status;
B
Bjorn Helgaas 已提交
557 558
	struct pnp_mem *mem;
	struct pnp_port *port;
559 560 561

	status = acpi_resource_to_address64(r, p);
	if (!ACPI_SUCCESS(status)) {
B
Bjorn Helgaas 已提交
562 563
		pnp_warn("PnPACPI: failed to convert resource type %d",
			 r->type);
564 565 566 567 568 569 570
		return;
	}

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

	if (p->resource_type == ACPI_MEMORY_RANGE) {
571
		mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
572 573
		if (!mem)
			return;
L
Len Brown 已提交
574
		mem->min = mem->max = p->minimum;
575 576
		mem->size = p->address_length;
		mem->align = 0;
L
Len Brown 已提交
577
		mem->flags = (p->info.mem.write_protect ==
B
Bjorn Helgaas 已提交
578 579
			      ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE
		    : 0;
580
		pnp_register_mem_resource(dev, option, mem);
581
	} else if (p->resource_type == ACPI_IO_RANGE) {
582
		port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
583 584
		if (!port)
			return;
L
Len Brown 已提交
585
		port->min = port->max = p->minimum;
586 587 588
		port->size = p->address_length;
		port->align = 0;
		port->flags = PNP_PORT_FLAG_FIXED;
589
		pnp_register_port_resource(dev, option, port);
590 591 592
	}
}

L
Linus Torvalds 已提交
593 594
struct acpipnp_parse_option_s {
	struct pnp_option *option;
M
Matthieu Castet 已提交
595
	struct pnp_option *option_independent;
L
Linus Torvalds 已提交
596 597 598
	struct pnp_dev *dev;
};

599 600
static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
						  void *data)
L
Linus Torvalds 已提交
601 602
{
	int priority = 0;
603
	struct acpipnp_parse_option_s *parse_data = data;
L
Linus Torvalds 已提交
604 605 606
	struct pnp_dev *dev = parse_data->dev;
	struct pnp_option *option = parse_data->option;

607
	switch (res->type) {
B
Bjorn Helgaas 已提交
608
	case ACPI_RESOURCE_TYPE_IRQ:
609
		pnpacpi_parse_irq_option(dev, option, &res->data.irq);
B
Bjorn Helgaas 已提交
610
		break;
611

B
Bjorn Helgaas 已提交
612
	case ACPI_RESOURCE_TYPE_DMA:
613
		pnpacpi_parse_dma_option(dev, option, &res->data.dma);
B
Bjorn Helgaas 已提交
614
		break;
615

B
Bjorn Helgaas 已提交
616 617 618 619
	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 已提交
620
			break;
621

B
Bjorn Helgaas 已提交
622 623
		case ACPI_ACCEPTABLE_CONFIGURATION:
			priority = PNP_RES_PRIORITY_ACCEPTABLE;
M
Matthieu Castet 已提交
624
			break;
625

B
Bjorn Helgaas 已提交
626 627
		case ACPI_SUB_OPTIMAL_CONFIGURATION:
			priority = PNP_RES_PRIORITY_FUNCTIONAL;
628
			break;
B
Bjorn Helgaas 已提交
629 630
		default:
			priority = PNP_RES_PRIORITY_INVALID;
631
			break;
B
Bjorn Helgaas 已提交
632
		}
B
Bjorn Helgaas 已提交
633
		/* TBD: Consider performance/robustness bits */
B
Bjorn Helgaas 已提交
634 635 636 637 638
		option = pnp_register_dependent_option(dev, priority);
		if (!option)
			return AE_ERROR;
		parse_data->option = option;
		break;
639

B
Bjorn Helgaas 已提交
640 641 642
	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
		/*only one EndDependentFn is allowed */
		if (!parse_data->option_independent) {
643 644
			dev_warn(&dev->dev, "more than one EndDependentFn "
				 "in _PRS\n");
B
Bjorn Helgaas 已提交
645 646 647 648
			return AE_ERROR;
		}
		parse_data->option = parse_data->option_independent;
		parse_data->option_independent = NULL;
649
		dev_dbg(&dev->dev, "end dependent options\n");
B
Bjorn Helgaas 已提交
650
		break;
651

B
Bjorn Helgaas 已提交
652
	case ACPI_RESOURCE_TYPE_IO:
653
		pnpacpi_parse_port_option(dev, option, &res->data.io);
B
Bjorn Helgaas 已提交
654
		break;
655

B
Bjorn Helgaas 已提交
656
	case ACPI_RESOURCE_TYPE_FIXED_IO:
657 658
		pnpacpi_parse_fixed_port_option(dev, option,
					        &res->data.fixed_io);
B
Bjorn Helgaas 已提交
659
		break;
660

B
Bjorn Helgaas 已提交
661 662 663
	case ACPI_RESOURCE_TYPE_VENDOR:
	case ACPI_RESOURCE_TYPE_END_TAG:
		break;
664

B
Bjorn Helgaas 已提交
665
	case ACPI_RESOURCE_TYPE_MEMORY24:
666
		pnpacpi_parse_mem24_option(dev, option, &res->data.memory24);
B
Bjorn Helgaas 已提交
667
		break;
668

B
Bjorn Helgaas 已提交
669
	case ACPI_RESOURCE_TYPE_MEMORY32:
670
		pnpacpi_parse_mem32_option(dev, option, &res->data.memory32);
B
Bjorn Helgaas 已提交
671
		break;
672

B
Bjorn Helgaas 已提交
673
	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
674
		pnpacpi_parse_fixed_mem32_option(dev, option,
B
Bjorn Helgaas 已提交
675 676
						 &res->data.fixed_memory32);
		break;
677

B
Bjorn Helgaas 已提交
678 679 680
	case ACPI_RESOURCE_TYPE_ADDRESS16:
	case ACPI_RESOURCE_TYPE_ADDRESS32:
	case ACPI_RESOURCE_TYPE_ADDRESS64:
681
		pnpacpi_parse_address_option(dev, option, res);
B
Bjorn Helgaas 已提交
682
		break;
683

B
Bjorn Helgaas 已提交
684 685 686 687
	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
		break;

	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
688 689
		pnpacpi_parse_ext_irq_option(dev, option,
					     &res->data.extended_irq);
B
Bjorn Helgaas 已提交
690 691 692 693 694 695
		break;

	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
		break;

	default:
696 697
		dev_warn(&dev->dev, "unknown resource type %d in _PRS\n",
			 res->type);
B
Bjorn Helgaas 已提交
698
		return AE_ERROR;
L
Linus Torvalds 已提交
699
	}
B
Bjorn Helgaas 已提交
700

L
Linus Torvalds 已提交
701 702 703
	return AE_OK;
}

704
acpi_status __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)
L
Linus Torvalds 已提交
705
{
706
	acpi_handle handle = dev->data;
L
Linus Torvalds 已提交
707 708 709
	acpi_status status;
	struct acpipnp_parse_option_s parse_data;

710 711
	dev_dbg(&dev->dev, "parse resource options\n");

L
Linus Torvalds 已提交
712 713 714
	parse_data.option = pnp_register_independent_option(dev);
	if (!parse_data.option)
		return AE_ERROR;
M
Matthieu Castet 已提交
715
	parse_data.option_independent = parse_data.option;
L
Linus Torvalds 已提交
716
	parse_data.dev = dev;
B
Bob Moore 已提交
717
	status = acpi_walk_resources(handle, METHOD_NAME__PRS,
B
Bjorn Helgaas 已提交
718
				     pnpacpi_option_resource, &parse_data);
L
Linus Torvalds 已提交
719 720 721 722

	return status;
}

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

/*
 * Set resource
 */
static acpi_status pnpacpi_count_resources(struct acpi_resource *res,
B
Bjorn Helgaas 已提交
746
					   void *data)
747
{
748
	int *res_cnt = data;
749 750 751

	if (pnpacpi_supported_resource(res))
		(*res_cnt)++;
L
Linus Torvalds 已提交
752 753 754
	return AE_OK;
}

B
Bjorn Helgaas 已提交
755
static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data)
L
Linus Torvalds 已提交
756
{
757
	struct acpi_resource **resource = data;
758 759

	if (pnpacpi_supported_resource(res)) {
760
		(*resource)->type = res->type;
761
		(*resource)->length = sizeof(struct acpi_resource);
L
Linus Torvalds 已提交
762 763 764 765 766 767
		(*resource)++;
	}

	return AE_OK;
}

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

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

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

	return 0;
}

803 804
static void pnpacpi_encode_irq(struct pnp_dev *dev,
			       struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
805
			       struct resource *p)
L
Linus Torvalds 已提交
806
{
807
	struct acpi_resource_irq *irq = &resource->data.irq;
B
Bob Moore 已提交
808
	int triggering, polarity;
B
Bjorn Helgaas 已提交
809 810

	decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
811 812
	irq->triggering = triggering;
	irq->polarity = polarity;
B
Bob Moore 已提交
813
	if (triggering == ACPI_EDGE_SENSITIVE)
814
		irq->sharable = ACPI_EXCLUSIVE;
L
Linus Torvalds 已提交
815
	else
816 817 818
		irq->sharable = ACPI_SHARED;
	irq->interrupt_count = 1;
	irq->interrupts[0] = p->start;
819 820 821 822 823

	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 已提交
824 825
}

826 827
static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
				   struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
828
				   struct resource *p)
L
Linus Torvalds 已提交
829
{
830
	struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq;
B
Bob Moore 已提交
831
	int triggering, polarity;
B
Bjorn Helgaas 已提交
832 833

	decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
834 835 836
	extended_irq->producer_consumer = ACPI_CONSUMER;
	extended_irq->triggering = triggering;
	extended_irq->polarity = polarity;
B
Bob Moore 已提交
837
	if (triggering == ACPI_EDGE_SENSITIVE)
838
		extended_irq->sharable = ACPI_EXCLUSIVE;
L
Linus Torvalds 已提交
839
	else
840 841 842
		extended_irq->sharable = ACPI_SHARED;
	extended_irq->interrupt_count = 1;
	extended_irq->interrupts[0] = p->start;
843 844 845 846 847

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

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

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

	switch (p->flags & IORESOURCE_DMA_TYPE_MASK) {
B
Bjorn Helgaas 已提交
872
	case IORESOURCE_DMA_8BIT:
873
		dma->transfer = ACPI_TRANSFER_8;
B
Bjorn Helgaas 已提交
874 875
		break;
	case IORESOURCE_DMA_8AND16BIT:
876
		dma->transfer = ACPI_TRANSFER_8_16;
B
Bjorn Helgaas 已提交
877 878
		break;
	default:
879
		dma->transfer = ACPI_TRANSFER_16;
880 881
	}

882 883 884
	dma->bus_master = !!(p->flags & IORESOURCE_DMA_MASTER);
	dma->channel_count = 1;
	dma->channels[0] = p->start;
885 886 887 888

	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 已提交
889 890
}

891 892
static void pnpacpi_encode_io(struct pnp_dev *dev,
			      struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
893
			      struct resource *p)
L
Linus Torvalds 已提交
894
{
895 896
	struct acpi_resource_io *io = &resource->data.io;

L
Linus Torvalds 已提交
897
	/* Note: pnp_assign_port will copy pnp_port->flags into p->flags */
898
	io->io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ?
B
Bjorn Helgaas 已提交
899
	    ACPI_DECODE_16 : ACPI_DECODE_10;
900 901 902 903
	io->minimum = p->start;
	io->maximum = p->end;
	io->alignment = 0;	/* Correct? */
	io->address_length = p->end - p->start + 1;
904 905 906 907

	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 已提交
908 909
}

910 911
static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
				    struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
912
				    struct resource *p)
L
Linus Torvalds 已提交
913
{
914 915 916 917
	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;
918 919 920

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

923 924
static void pnpacpi_encode_mem24(struct pnp_dev *dev,
				 struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
925
				 struct resource *p)
L
Linus Torvalds 已提交
926
{
927 928
	struct acpi_resource_memory24 *memory24 = &resource->data.memory24;

L
Linus Torvalds 已提交
929
	/* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */
930
	memory24->write_protect =
B
Bjorn Helgaas 已提交
931 932
	    (p->flags & IORESOURCE_MEM_WRITEABLE) ?
	    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
933 934 935 936
	memory24->minimum = p->start;
	memory24->maximum = p->end;
	memory24->alignment = 0;
	memory24->address_length = p->end - p->start + 1;
937 938 939 940

	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 已提交
941 942
}

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

	memory32->write_protect =
B
Bjorn Helgaas 已提交
950 951
	    (p->flags & IORESOURCE_MEM_WRITEABLE) ?
	    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
952 953 954 955
	memory32->minimum = p->start;
	memory32->maximum = p->end;
	memory32->alignment = 0;
	memory32->address_length = p->end - p->start + 1;
956 957 958 959

	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 已提交
960 961
}

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

	fixed_memory32->write_protect =
B
Bjorn Helgaas 已提交
969 970
	    (p->flags & IORESOURCE_MEM_WRITEABLE) ?
	    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
971 972
	fixed_memory32->address = p->start;
	fixed_memory32->address_length = p->end - p->start + 1;
973 974 975 976 977

	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 已提交
978 979
}

980
int pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer)
L
Linus Torvalds 已提交
981 982 983
{
	int i = 0;
	/* pnpacpi_build_resource_template allocates extra mem */
B
Bjorn Helgaas 已提交
984
	int res_cnt = (buffer->length - 1) / sizeof(struct acpi_resource) - 1;
985
	struct acpi_resource *resource = buffer->pointer;
L
Linus Torvalds 已提交
986 987
	int port = 0, irq = 0, dma = 0, mem = 0;

988
	dev_dbg(&dev->dev, "encode %d resources\n", res_cnt);
L
Linus Torvalds 已提交
989
	while (i < res_cnt) {
B
Bjorn Helgaas 已提交
990
		switch (resource->type) {
B
Bob Moore 已提交
991
		case ACPI_RESOURCE_TYPE_IRQ:
992
			pnpacpi_encode_irq(dev, resource,
993
			       pnp_get_resource(dev, IORESOURCE_IRQ, irq));
L
Linus Torvalds 已提交
994 995 996
			irq++;
			break;

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