rsparser.c 29.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
	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 183 184 185 186 187
	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 已提交
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;
B
Bjorn Helgaas 已提交
414
	struct pnp_dma *dma;
L
Linus Torvalds 已提交
415

B
Bob Moore 已提交
416
	if (p->channel_count == 0)
L
Linus Torvalds 已提交
417
		return;
418
	dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
L
Linus Torvalds 已提交
419 420 421
	if (!dma)
		return;

B
Bjorn Helgaas 已提交
422
	for (i = 0; i < p->channel_count; i++)
L
Linus Torvalds 已提交
423
		dma->map |= 1 << p->channels[i];
424 425

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

427
	pnp_register_dma_resource(dev, option, dma);
L
Linus Torvalds 已提交
428 429
}

430 431
static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
					    struct pnp_option *option,
432
					    struct acpi_resource_irq *p)
L
Linus Torvalds 已提交
433 434
{
	int i;
B
Bjorn Helgaas 已提交
435 436
	struct pnp_irq *irq;

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

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

448
	pnp_register_irq_resource(dev, option, irq);
L
Linus Torvalds 已提交
449 450
}

451 452
static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
						struct pnp_option *option,
453
					struct acpi_resource_extended_irq *p)
L
Linus Torvalds 已提交
454 455
{
	int i;
B
Bjorn Helgaas 已提交
456
	struct pnp_irq *irq;
L
Linus Torvalds 已提交
457

B
Bob Moore 已提交
458
	if (p->interrupt_count == 0)
L
Linus Torvalds 已提交
459
		return;
460
	irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
L
Linus Torvalds 已提交
461 462 463
	if (!irq)
		return;

B
Bjorn Helgaas 已提交
464
	for (i = 0; i < p->interrupt_count; i++)
L
Linus Torvalds 已提交
465 466
		if (p->interrupts[i])
			__set_bit(p->interrupts[i], irq->map);
467
	irq->flags = irq_flags(p->triggering, p->polarity, p->sharable);
L
Linus Torvalds 已提交
468

469
	pnp_register_irq_resource(dev, option, irq);
L
Linus Torvalds 已提交
470 471
}

472 473
static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
					     struct pnp_option *option,
474
					     struct acpi_resource_io *io)
L
Linus Torvalds 已提交
475
{
B
Bjorn Helgaas 已提交
476
	struct pnp_port *port;
L
Linus Torvalds 已提交
477

B
Bob Moore 已提交
478
	if (io->address_length == 0)
L
Linus Torvalds 已提交
479
		return;
480
	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
L
Linus Torvalds 已提交
481 482
	if (!port)
		return;
B
Bob Moore 已提交
483 484
	port->min = io->minimum;
	port->max = io->maximum;
L
Linus Torvalds 已提交
485
	port->align = io->alignment;
B
Bob Moore 已提交
486 487
	port->size = io->address_length;
	port->flags = ACPI_DECODE_16 == io->io_decode ?
B
Bjorn Helgaas 已提交
488
	    PNP_PORT_FLAG_16BITADDR : 0;
489
	pnp_register_port_resource(dev, option, port);
L
Linus Torvalds 已提交
490 491
}

492 493
static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
						   struct pnp_option *option,
494
					struct acpi_resource_fixed_io *io)
L
Linus Torvalds 已提交
495
{
B
Bjorn Helgaas 已提交
496
	struct pnp_port *port;
L
Linus Torvalds 已提交
497

B
Bob Moore 已提交
498
	if (io->address_length == 0)
L
Linus Torvalds 已提交
499
		return;
500
	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
L
Linus Torvalds 已提交
501 502
	if (!port)
		return;
B
Bob Moore 已提交
503 504
	port->min = port->max = io->address;
	port->size = io->address_length;
L
Linus Torvalds 已提交
505 506
	port->align = 0;
	port->flags = PNP_PORT_FLAG_FIXED;
507
	pnp_register_port_resource(dev, option, port);
L
Linus Torvalds 已提交
508 509
}

510 511
static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev,
					      struct pnp_option *option,
512
					      struct acpi_resource_memory24 *p)
L
Linus Torvalds 已提交
513
{
B
Bjorn Helgaas 已提交
514
	struct pnp_mem *mem;
L
Linus Torvalds 已提交
515

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

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

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

532 533
static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
					      struct pnp_option *option,
534
					      struct acpi_resource_memory32 *p)
L
Linus Torvalds 已提交
535
{
B
Bjorn Helgaas 已提交
536
	struct pnp_mem *mem;
L
Linus Torvalds 已提交
537

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

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

551
	pnp_register_mem_resource(dev, option, mem);
L
Linus Torvalds 已提交
552 553
}

554 555
static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
						    struct pnp_option *option,
556
					struct acpi_resource_fixed_memory32 *p)
L
Linus Torvalds 已提交
557
{
B
Bjorn Helgaas 已提交
558
	struct pnp_mem *mem;
L
Linus Torvalds 已提交
559

B
Bob Moore 已提交
560
	if (p->address_length == 0)
L
Linus Torvalds 已提交
561
		return;
562
	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
L
Linus Torvalds 已提交
563 564
	if (!mem)
		return;
B
Bob Moore 已提交
565 566
	mem->min = mem->max = p->address;
	mem->size = p->address_length;
L
Linus Torvalds 已提交
567 568
	mem->align = 0;

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

572
	pnp_register_mem_resource(dev, option, mem);
L
Linus Torvalds 已提交
573 574
}

575 576
static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
						struct pnp_option *option,
577
						struct acpi_resource *r)
578 579 580
{
	struct acpi_resource_address64 addr, *p = &addr;
	acpi_status status;
B
Bjorn Helgaas 已提交
581 582
	struct pnp_mem *mem;
	struct pnp_port *port;
583 584 585

	status = acpi_resource_to_address64(r, p);
	if (!ACPI_SUCCESS(status)) {
B
Bjorn Helgaas 已提交
586 587
		pnp_warn("PnPACPI: failed to convert resource type %d",
			 r->type);
588 589 590 591 592 593 594
		return;
	}

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

	if (p->resource_type == ACPI_MEMORY_RANGE) {
595
		mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
596 597
		if (!mem)
			return;
L
Len Brown 已提交
598
		mem->min = mem->max = p->minimum;
599 600
		mem->size = p->address_length;
		mem->align = 0;
L
Len Brown 已提交
601
		mem->flags = (p->info.mem.write_protect ==
B
Bjorn Helgaas 已提交
602 603
			      ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE
		    : 0;
604
		pnp_register_mem_resource(dev, option, mem);
605
	} else if (p->resource_type == ACPI_IO_RANGE) {
606
		port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
607 608
		if (!port)
			return;
L
Len Brown 已提交
609
		port->min = port->max = p->minimum;
610 611 612
		port->size = p->address_length;
		port->align = 0;
		port->flags = PNP_PORT_FLAG_FIXED;
613
		pnp_register_port_resource(dev, option, port);
614 615 616
	}
}

L
Linus Torvalds 已提交
617 618
struct acpipnp_parse_option_s {
	struct pnp_option *option;
M
Matthieu Castet 已提交
619
	struct pnp_option *option_independent;
L
Linus Torvalds 已提交
620 621 622
	struct pnp_dev *dev;
};

623 624
static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
						  void *data)
L
Linus Torvalds 已提交
625 626
{
	int priority = 0;
627
	struct acpipnp_parse_option_s *parse_data = data;
L
Linus Torvalds 已提交
628 629 630
	struct pnp_dev *dev = parse_data->dev;
	struct pnp_option *option = parse_data->option;

631
	switch (res->type) {
B
Bjorn Helgaas 已提交
632
	case ACPI_RESOURCE_TYPE_IRQ:
633
		pnpacpi_parse_irq_option(dev, option, &res->data.irq);
B
Bjorn Helgaas 已提交
634
		break;
635

B
Bjorn Helgaas 已提交
636
	case ACPI_RESOURCE_TYPE_DMA:
637
		pnpacpi_parse_dma_option(dev, option, &res->data.dma);
B
Bjorn Helgaas 已提交
638
		break;
639

B
Bjorn Helgaas 已提交
640 641 642 643
	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 已提交
644
			break;
645

B
Bjorn Helgaas 已提交
646 647
		case ACPI_ACCEPTABLE_CONFIGURATION:
			priority = PNP_RES_PRIORITY_ACCEPTABLE;
M
Matthieu Castet 已提交
648
			break;
649

B
Bjorn Helgaas 已提交
650 651
		case ACPI_SUB_OPTIMAL_CONFIGURATION:
			priority = PNP_RES_PRIORITY_FUNCTIONAL;
652
			break;
B
Bjorn Helgaas 已提交
653 654
		default:
			priority = PNP_RES_PRIORITY_INVALID;
655
			break;
B
Bjorn Helgaas 已提交
656
		}
B
Bjorn Helgaas 已提交
657
		/* TBD: Consider performance/robustness bits */
B
Bjorn Helgaas 已提交
658 659 660 661 662
		option = pnp_register_dependent_option(dev, priority);
		if (!option)
			return AE_ERROR;
		parse_data->option = option;
		break;
663

B
Bjorn Helgaas 已提交
664 665 666
	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
		/*only one EndDependentFn is allowed */
		if (!parse_data->option_independent) {
667 668
			dev_warn(&dev->dev, "more than one EndDependentFn "
				 "in _PRS\n");
B
Bjorn Helgaas 已提交
669 670 671 672
			return AE_ERROR;
		}
		parse_data->option = parse_data->option_independent;
		parse_data->option_independent = NULL;
673
		dev_dbg(&dev->dev, "end dependent options\n");
B
Bjorn Helgaas 已提交
674
		break;
675

B
Bjorn Helgaas 已提交
676
	case ACPI_RESOURCE_TYPE_IO:
677
		pnpacpi_parse_port_option(dev, option, &res->data.io);
B
Bjorn Helgaas 已提交
678
		break;
679

B
Bjorn Helgaas 已提交
680
	case ACPI_RESOURCE_TYPE_FIXED_IO:
681 682
		pnpacpi_parse_fixed_port_option(dev, option,
					        &res->data.fixed_io);
B
Bjorn Helgaas 已提交
683
		break;
684

B
Bjorn Helgaas 已提交
685 686 687
	case ACPI_RESOURCE_TYPE_VENDOR:
	case ACPI_RESOURCE_TYPE_END_TAG:
		break;
688

B
Bjorn Helgaas 已提交
689
	case ACPI_RESOURCE_TYPE_MEMORY24:
690
		pnpacpi_parse_mem24_option(dev, option, &res->data.memory24);
B
Bjorn Helgaas 已提交
691
		break;
692

B
Bjorn Helgaas 已提交
693
	case ACPI_RESOURCE_TYPE_MEMORY32:
694
		pnpacpi_parse_mem32_option(dev, option, &res->data.memory32);
B
Bjorn Helgaas 已提交
695
		break;
696

B
Bjorn Helgaas 已提交
697
	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
698
		pnpacpi_parse_fixed_mem32_option(dev, option,
B
Bjorn Helgaas 已提交
699 700
						 &res->data.fixed_memory32);
		break;
701

B
Bjorn Helgaas 已提交
702 703 704
	case ACPI_RESOURCE_TYPE_ADDRESS16:
	case ACPI_RESOURCE_TYPE_ADDRESS32:
	case ACPI_RESOURCE_TYPE_ADDRESS64:
705
		pnpacpi_parse_address_option(dev, option, res);
B
Bjorn Helgaas 已提交
706
		break;
707

B
Bjorn Helgaas 已提交
708 709 710 711
	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
		break;

	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
712 713
		pnpacpi_parse_ext_irq_option(dev, option,
					     &res->data.extended_irq);
B
Bjorn Helgaas 已提交
714 715 716 717 718 719
		break;

	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
		break;

	default:
720 721
		dev_warn(&dev->dev, "unknown resource type %d in _PRS\n",
			 res->type);
B
Bjorn Helgaas 已提交
722
		return AE_ERROR;
L
Linus Torvalds 已提交
723
	}
B
Bjorn Helgaas 已提交
724

L
Linus Torvalds 已提交
725 726 727
	return AE_OK;
}

728
int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)
L
Linus Torvalds 已提交
729
{
730
	acpi_handle handle = dev->data;
L
Linus Torvalds 已提交
731 732 733
	acpi_status status;
	struct acpipnp_parse_option_s parse_data;

734 735
	dev_dbg(&dev->dev, "parse resource options\n");

L
Linus Torvalds 已提交
736 737
	parse_data.option = pnp_register_independent_option(dev);
	if (!parse_data.option)
738 739
		return -ENOMEM;

M
Matthieu Castet 已提交
740
	parse_data.option_independent = parse_data.option;
L
Linus Torvalds 已提交
741
	parse_data.dev = dev;
B
Bob Moore 已提交
742
	status = acpi_walk_resources(handle, METHOD_NAME__PRS,
B
Bjorn Helgaas 已提交
743
				     pnpacpi_option_resource, &parse_data);
L
Linus Torvalds 已提交
744

745 746 747 748 749 750
	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 已提交
751 752
}

753
static int pnpacpi_supported_resource(struct acpi_resource *res)
L
Linus Torvalds 已提交
754
{
755
	switch (res->type) {
B
Bob Moore 已提交
756 757 758 759 760 761 762 763 764 765
	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:
766
	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
767
		return 1;
L
Linus Torvalds 已提交
768
	}
769 770 771 772 773 774 775
	return 0;
}

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

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

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

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

	return AE_OK;
}

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

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

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

	return 0;
}

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

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

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

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

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

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

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

	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 已提交
891 892
}

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

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

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

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

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

	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 已提交
939 940
}

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

947 948 949 950 951 952 953 954 955 956 957 958
	if (pnp_resource_enabled(p)) {
		/* Note: pnp_assign_port copies pnp_port->flags into p->flags */
		io->io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ?
		    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;
	}
959

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

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

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

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

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

988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003
	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,
1004
		memory24->write_protect);
L
Linus Torvalds 已提交
1005 1006
}

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

1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
	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;
	}
1024

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

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

1037 1038 1039 1040 1041 1042 1043 1044 1045 1046
	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;
	}
1047

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

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

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

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