rsparser.c 28.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 86
	struct resource *res;
	int i;
87
	int irq;
88
	int p, t;
89
	static unsigned char warned;
90 91 92 93

	if (!valid_IRQ(gsi))
		return;

94 95 96 97 98
	for (i = 0; i < PNP_MAX_IRQ; i++) {
		res = pnp_get_resource(dev, IORESOURCE_IRQ, i);
		if (!pnp_resource_valid(res))
			break;
	}
99 100 101 102 103 104
	if (i >= PNP_MAX_IRQ) {
		if (!warned) {
			printk(KERN_WARNING "pnpacpi: exceeded the max number"
				" of IRQ resources: %d\n", PNP_MAX_IRQ);
			warned = 1;
		}
105
		return;
106
	}
107 108 109 110 111 112 113 114 115 116
	/*
	 * 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) {
117
			dev_warn(&dev->dev, "IRQ %d override to %s, %s\n",
118 119 120 121 122 123
				gsi, t ? "edge":"level", p ? "low":"high");
			triggering = t;
			polarity = p;
		}
	}

124 125
	res->flags = IORESOURCE_IRQ;	// Also clears _UNSET flag
	res->flags |= irq_flags(triggering, polarity, shareable);
B
Bob Moore 已提交
126
	irq = acpi_register_gsi(gsi, triggering, polarity);
127
	if (irq < 0) {
128
		res->flags |= IORESOURCE_DISABLED;
129
		return;
L
Linus Torvalds 已提交
130
	}
131

132 133
	res->start = irq;
	res->end = irq;
134
	pcibios_penalize_isa_irq(irq, 1);
L
Linus Torvalds 已提交
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 176 177 178 179
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;
}

180
static void pnpacpi_parse_allocated_dmaresource(struct pnp_dev *dev,
181
						u32 dma, int flags)
L
Linus Torvalds 已提交
182
{
183 184
	struct resource *res;
	int i;
185
	static unsigned char warned;
B
Bjorn Helgaas 已提交
186

187 188 189 190 191
	for (i = 0; i < PNP_MAX_DMA; i++) {
		res = pnp_get_resource(dev, IORESOURCE_DMA, i);
		if (!pnp_resource_valid(res))
			break;
	}
L
Linus Torvalds 已提交
192
	if (i < PNP_MAX_DMA) {
193 194
		res->flags = IORESOURCE_DMA;	// Also clears _UNSET flag
		res->flags |= flags;
L
Linus Torvalds 已提交
195
		if (dma == -1) {
196
			res->flags |= IORESOURCE_DISABLED;
L
Linus Torvalds 已提交
197 198
			return;
		}
199 200
		res->start = dma;
		res->end = dma;
201
	} else if (!warned) {
202
		printk(KERN_WARNING "pnpacpi: exceeded the max number of DMA "
203
				"resources: %d \n", PNP_MAX_DMA);
204
		warned = 1;
L
Linus Torvalds 已提交
205 206 207
	}
}

208
static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev,
B
Bjorn Helgaas 已提交
209
					       u64 io, u64 len, int io_decode)
L
Linus Torvalds 已提交
210
{
211 212
	struct resource *res;
	int i;
213
	static unsigned char warned;
B
Bjorn Helgaas 已提交
214

215 216 217 218 219
	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 已提交
220
	if (i < PNP_MAX_PORT) {
221
		res->flags = IORESOURCE_IO;	// Also clears _UNSET flag
222
		if (io_decode == ACPI_DECODE_16)
223
			res->flags |= PNP_PORT_FLAG_16BITADDR;
B
Bjorn Helgaas 已提交
224
		if (len <= 0 || (io + len - 1) >= 0x10003) {
225
			res->flags |= IORESOURCE_DISABLED;
L
Linus Torvalds 已提交
226 227
			return;
		}
228 229
		res->start = io;
		res->end = io + len - 1;
230
	} else if (!warned) {
231
		printk(KERN_WARNING "pnpacpi: exceeded the max number of IO "
232
				"resources: %d \n", PNP_MAX_PORT);
233
		warned = 1;
L
Linus Torvalds 已提交
234 235 236
	}
}

237
static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
B
Bjorn Helgaas 已提交
238 239
						u64 mem, u64 len,
						int write_protect)
L
Linus Torvalds 已提交
240
{
241 242
	struct resource *res;
	int i;
243
	static unsigned char warned;
B
Bjorn Helgaas 已提交
244

245 246 247 248 249
	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 已提交
250
	if (i < PNP_MAX_MEM) {
251
		res->flags = IORESOURCE_MEM;	// Also clears _UNSET flag
L
Linus Torvalds 已提交
252
		if (len <= 0) {
253
			res->flags |= IORESOURCE_DISABLED;
L
Linus Torvalds 已提交
254 255
			return;
		}
B
Bjorn Helgaas 已提交
256
		if (write_protect == ACPI_READ_WRITE_MEMORY)
257
			res->flags |= IORESOURCE_MEM_WRITEABLE;
258

259 260
		res->start = mem;
		res->end = mem + len - 1;
261
	} else if (!warned) {
262
		printk(KERN_WARNING "pnpacpi: exceeded the max number of mem "
263
				"resources: %d\n", PNP_MAX_MEM);
264
		warned = 1;
L
Linus Torvalds 已提交
265 266 267
	}
}

268
static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
B
Bjorn Helgaas 已提交
269
						  struct acpi_resource *res)
270 271 272 273 274 275
{
	struct acpi_resource_address64 addr, *p = &addr;
	acpi_status status;

	status = acpi_resource_to_address64(res, p);
	if (!ACPI_SUCCESS(status)) {
276
		dev_warn(&dev->dev, "failed to convert resource type %d\n",
B
Bjorn Helgaas 已提交
277
			 res->type);
278 279 280
		return;
	}

281 282 283
	if (p->producer_consumer == ACPI_PRODUCER)
		return;

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

static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
B
Bjorn Helgaas 已提交
296
					      void *data)
L
Linus Torvalds 已提交
297
{
298
	struct pnp_dev *dev = data;
299 300 301 302 303 304 305 306
	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;
307
	int i;
L
Linus Torvalds 已提交
308

309
	switch (res->type) {
B
Bob Moore 已提交
310
	case ACPI_RESOURCE_TYPE_IRQ:
311 312 313 314
		/*
		 * Per spec, only one interrupt per descriptor is allowed in
		 * _CRS, but some firmware violates this, so parse them all.
		 */
315 316
		irq = &res->data.irq;
		for (i = 0; i < irq->interrupt_count; i++) {
317
			pnpacpi_parse_allocated_irqresource(dev,
318 319 320 321
				irq->interrupts[i],
				irq->triggering,
				irq->polarity,
				irq->sharable);
L
Linus Torvalds 已提交
322 323 324
		}
		break;

B
Bob Moore 已提交
325
	case ACPI_RESOURCE_TYPE_DMA:
326 327
		dma = &res->data.dma;
		if (dma->channel_count > 0)
328
			pnpacpi_parse_allocated_dmaresource(dev,
329
				dma->channels[0],
330 331
				dma_flags(dma->type, dma->bus_master,
					  dma->transfer));
L
Linus Torvalds 已提交
332
		break;
333

B
Bob Moore 已提交
334
	case ACPI_RESOURCE_TYPE_IO:
335
		io = &res->data.io;
336
		pnpacpi_parse_allocated_ioresource(dev,
337 338 339
			io->minimum,
			io->address_length,
			io->io_decode);
L
Linus Torvalds 已提交
340
		break;
341 342 343 344 345

	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
		break;

B
Bob Moore 已提交
346
	case ACPI_RESOURCE_TYPE_FIXED_IO:
347
		fixed_io = &res->data.fixed_io;
348
		pnpacpi_parse_allocated_ioresource(dev,
349 350
			fixed_io->address,
			fixed_io->address_length,
B
Bjorn Helgaas 已提交
351
			ACPI_DECODE_10);
L
Linus Torvalds 已提交
352
		break;
353 354 355 356 357 358 359

	case ACPI_RESOURCE_TYPE_VENDOR:
		break;

	case ACPI_RESOURCE_TYPE_END_TAG:
		break;

B
Bob Moore 已提交
360
	case ACPI_RESOURCE_TYPE_MEMORY24:
361
		memory24 = &res->data.memory24;
362
		pnpacpi_parse_allocated_memresource(dev,
363 364 365
			memory24->minimum,
			memory24->address_length,
			memory24->write_protect);
L
Linus Torvalds 已提交
366
		break;
B
Bob Moore 已提交
367
	case ACPI_RESOURCE_TYPE_MEMORY32:
368
		memory32 = &res->data.memory32;
369
		pnpacpi_parse_allocated_memresource(dev,
370 371 372
			memory32->minimum,
			memory32->address_length,
			memory32->write_protect);
L
Linus Torvalds 已提交
373
		break;
B
Bob Moore 已提交
374
	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
375
		fixed_memory32 = &res->data.fixed_memory32;
376
		pnpacpi_parse_allocated_memresource(dev,
377 378 379
			fixed_memory32->address,
			fixed_memory32->address_length,
			fixed_memory32->write_protect);
L
Linus Torvalds 已提交
380
		break;
B
Bob Moore 已提交
381 382 383
	case ACPI_RESOURCE_TYPE_ADDRESS16:
	case ACPI_RESOURCE_TYPE_ADDRESS32:
	case ACPI_RESOURCE_TYPE_ADDRESS64:
384
		pnpacpi_parse_allocated_address_space(dev, res);
L
Linus Torvalds 已提交
385
		break;
386 387

	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
388 389
		if (res->data.ext_address64.producer_consumer == ACPI_PRODUCER)
			return AE_OK;
390 391 392
		break;

	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
393 394
		extended_irq = &res->data.extended_irq;
		if (extended_irq->producer_consumer == ACPI_PRODUCER)
395 396
			return AE_OK;

397
		for (i = 0; i < extended_irq->interrupt_count; i++) {
398
			pnpacpi_parse_allocated_irqresource(dev,
399 400 401 402
				extended_irq->interrupts[i],
				extended_irq->triggering,
				extended_irq->polarity,
				extended_irq->sharable);
403 404 405 406
		}
		break;

	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
L
Linus Torvalds 已提交
407
		break;
408

L
Linus Torvalds 已提交
409
	default:
410 411
		dev_warn(&dev->dev, "unknown resource type %d in _CRS\n",
			 res->type);
L
Linus Torvalds 已提交
412 413
		return AE_ERROR;
	}
B
Bjorn Helgaas 已提交
414

L
Linus Torvalds 已提交
415 416 417
	return AE_OK;
}

418
acpi_status pnpacpi_parse_allocated_resource(struct pnp_dev *dev)
L
Linus Torvalds 已提交
419
{
420 421
	acpi_handle handle = dev->data;

422 423
	dev_dbg(&dev->dev, "parse allocated resources\n");

424
	pnp_init_resources(dev);
L
Linus Torvalds 已提交
425

B
Bjorn Helgaas 已提交
426
	return acpi_walk_resources(handle, METHOD_NAME__CRS,
427
				   pnpacpi_allocated_resource, dev);
L
Linus Torvalds 已提交
428 429
}

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

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

B
Bjorn Helgaas 已提交
443
	for (i = 0; i < p->channel_count; i++)
L
Linus Torvalds 已提交
444
		dma->map |= 1 << p->channels[i];
445 446

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

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

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

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_ext_irq_option(struct pnp_dev *dev,
						struct pnp_option *option,
474
					struct acpi_resource_extended_irq *p)
L
Linus Torvalds 已提交
475 476
{
	int i;
B
Bjorn Helgaas 已提交
477
	struct pnp_irq *irq;
L
Linus Torvalds 已提交
478

B
Bob Moore 已提交
479
	if (p->interrupt_count == 0)
L
Linus Torvalds 已提交
480
		return;
481
	irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
L
Linus Torvalds 已提交
482 483 484
	if (!irq)
		return;

B
Bjorn Helgaas 已提交
485
	for (i = 0; i < p->interrupt_count; i++)
L
Linus Torvalds 已提交
486 487
		if (p->interrupts[i])
			__set_bit(p->interrupts[i], irq->map);
488
	irq->flags = irq_flags(p->triggering, p->polarity, p->sharable);
L
Linus Torvalds 已提交
489

490
	pnp_register_irq_resource(dev, option, irq);
L
Linus Torvalds 已提交
491 492
}

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

B
Bob Moore 已提交
499
	if (io->address_length == 0)
L
Linus Torvalds 已提交
500
		return;
501
	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
L
Linus Torvalds 已提交
502 503
	if (!port)
		return;
B
Bob Moore 已提交
504 505
	port->min = io->minimum;
	port->max = io->maximum;
L
Linus Torvalds 已提交
506
	port->align = io->alignment;
B
Bob Moore 已提交
507 508
	port->size = io->address_length;
	port->flags = ACPI_DECODE_16 == io->io_decode ?
B
Bjorn Helgaas 已提交
509
	    PNP_PORT_FLAG_16BITADDR : 0;
510
	pnp_register_port_resource(dev, option, port);
L
Linus Torvalds 已提交
511 512
}

513 514
static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
						   struct pnp_option *option,
515
					struct acpi_resource_fixed_io *io)
L
Linus Torvalds 已提交
516
{
B
Bjorn Helgaas 已提交
517
	struct pnp_port *port;
L
Linus Torvalds 已提交
518

B
Bob Moore 已提交
519
	if (io->address_length == 0)
L
Linus Torvalds 已提交
520
		return;
521
	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
L
Linus Torvalds 已提交
522 523
	if (!port)
		return;
B
Bob Moore 已提交
524 525
	port->min = port->max = io->address;
	port->size = io->address_length;
L
Linus Torvalds 已提交
526 527
	port->align = 0;
	port->flags = PNP_PORT_FLAG_FIXED;
528
	pnp_register_port_resource(dev, option, port);
L
Linus Torvalds 已提交
529 530
}

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

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

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

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

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

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

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_fixed_mem32_option(struct pnp_dev *dev,
						    struct pnp_option *option,
577
					struct acpi_resource_fixed_memory32 *p)
L
Linus Torvalds 已提交
578
{
B
Bjorn Helgaas 已提交
579
	struct pnp_mem *mem;
L
Linus Torvalds 已提交
580

B
Bob Moore 已提交
581
	if (p->address_length == 0)
L
Linus Torvalds 已提交
582
		return;
583
	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
L
Linus Torvalds 已提交
584 585
	if (!mem)
		return;
B
Bob Moore 已提交
586 587
	mem->min = mem->max = p->address;
	mem->size = p->address_length;
L
Linus Torvalds 已提交
588 589
	mem->align = 0;

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

593
	pnp_register_mem_resource(dev, option, mem);
L
Linus Torvalds 已提交
594 595
}

596 597
static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
						struct pnp_option *option,
598
						struct acpi_resource *r)
599 600 601
{
	struct acpi_resource_address64 addr, *p = &addr;
	acpi_status status;
B
Bjorn Helgaas 已提交
602 603
	struct pnp_mem *mem;
	struct pnp_port *port;
604 605 606

	status = acpi_resource_to_address64(r, p);
	if (!ACPI_SUCCESS(status)) {
B
Bjorn Helgaas 已提交
607 608
		pnp_warn("PnPACPI: failed to convert resource type %d",
			 r->type);
609 610 611 612 613 614 615
		return;
	}

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

	if (p->resource_type == ACPI_MEMORY_RANGE) {
616
		mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
617 618
		if (!mem)
			return;
L
Len Brown 已提交
619
		mem->min = mem->max = p->minimum;
620 621
		mem->size = p->address_length;
		mem->align = 0;
L
Len Brown 已提交
622
		mem->flags = (p->info.mem.write_protect ==
B
Bjorn Helgaas 已提交
623 624
			      ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE
		    : 0;
625
		pnp_register_mem_resource(dev, option, mem);
626
	} else if (p->resource_type == ACPI_IO_RANGE) {
627
		port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
628 629
		if (!port)
			return;
L
Len Brown 已提交
630
		port->min = port->max = p->minimum;
631 632 633
		port->size = p->address_length;
		port->align = 0;
		port->flags = PNP_PORT_FLAG_FIXED;
634
		pnp_register_port_resource(dev, option, port);
635 636 637
	}
}

L
Linus Torvalds 已提交
638 639
struct acpipnp_parse_option_s {
	struct pnp_option *option;
M
Matthieu Castet 已提交
640
	struct pnp_option *option_independent;
L
Linus Torvalds 已提交
641 642 643
	struct pnp_dev *dev;
};

644 645
static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
						  void *data)
L
Linus Torvalds 已提交
646 647
{
	int priority = 0;
648
	struct acpipnp_parse_option_s *parse_data = data;
L
Linus Torvalds 已提交
649 650 651
	struct pnp_dev *dev = parse_data->dev;
	struct pnp_option *option = parse_data->option;

652
	switch (res->type) {
B
Bjorn Helgaas 已提交
653
	case ACPI_RESOURCE_TYPE_IRQ:
654
		pnpacpi_parse_irq_option(dev, option, &res->data.irq);
B
Bjorn Helgaas 已提交
655
		break;
656

B
Bjorn Helgaas 已提交
657
	case ACPI_RESOURCE_TYPE_DMA:
658
		pnpacpi_parse_dma_option(dev, option, &res->data.dma);
B
Bjorn Helgaas 已提交
659
		break;
660

B
Bjorn Helgaas 已提交
661 662 663 664
	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 已提交
665
			break;
666

B
Bjorn Helgaas 已提交
667 668
		case ACPI_ACCEPTABLE_CONFIGURATION:
			priority = PNP_RES_PRIORITY_ACCEPTABLE;
M
Matthieu Castet 已提交
669
			break;
670

B
Bjorn Helgaas 已提交
671 672
		case ACPI_SUB_OPTIMAL_CONFIGURATION:
			priority = PNP_RES_PRIORITY_FUNCTIONAL;
673
			break;
B
Bjorn Helgaas 已提交
674 675
		default:
			priority = PNP_RES_PRIORITY_INVALID;
676
			break;
B
Bjorn Helgaas 已提交
677
		}
B
Bjorn Helgaas 已提交
678
		/* TBD: Consider performance/robustness bits */
B
Bjorn Helgaas 已提交
679 680 681 682 683
		option = pnp_register_dependent_option(dev, priority);
		if (!option)
			return AE_ERROR;
		parse_data->option = option;
		break;
684

B
Bjorn Helgaas 已提交
685 686 687
	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
		/*only one EndDependentFn is allowed */
		if (!parse_data->option_independent) {
688 689
			dev_warn(&dev->dev, "more than one EndDependentFn "
				 "in _PRS\n");
B
Bjorn Helgaas 已提交
690 691 692 693
			return AE_ERROR;
		}
		parse_data->option = parse_data->option_independent;
		parse_data->option_independent = NULL;
694
		dev_dbg(&dev->dev, "end dependent options\n");
B
Bjorn Helgaas 已提交
695
		break;
696

B
Bjorn Helgaas 已提交
697
	case ACPI_RESOURCE_TYPE_IO:
698
		pnpacpi_parse_port_option(dev, option, &res->data.io);
B
Bjorn Helgaas 已提交
699
		break;
700

B
Bjorn Helgaas 已提交
701
	case ACPI_RESOURCE_TYPE_FIXED_IO:
702 703
		pnpacpi_parse_fixed_port_option(dev, option,
					        &res->data.fixed_io);
B
Bjorn Helgaas 已提交
704
		break;
705

B
Bjorn Helgaas 已提交
706 707 708
	case ACPI_RESOURCE_TYPE_VENDOR:
	case ACPI_RESOURCE_TYPE_END_TAG:
		break;
709

B
Bjorn Helgaas 已提交
710
	case ACPI_RESOURCE_TYPE_MEMORY24:
711
		pnpacpi_parse_mem24_option(dev, option, &res->data.memory24);
B
Bjorn Helgaas 已提交
712
		break;
713

B
Bjorn Helgaas 已提交
714
	case ACPI_RESOURCE_TYPE_MEMORY32:
715
		pnpacpi_parse_mem32_option(dev, option, &res->data.memory32);
B
Bjorn Helgaas 已提交
716
		break;
717

B
Bjorn Helgaas 已提交
718
	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
719
		pnpacpi_parse_fixed_mem32_option(dev, option,
B
Bjorn Helgaas 已提交
720 721
						 &res->data.fixed_memory32);
		break;
722

B
Bjorn Helgaas 已提交
723 724 725
	case ACPI_RESOURCE_TYPE_ADDRESS16:
	case ACPI_RESOURCE_TYPE_ADDRESS32:
	case ACPI_RESOURCE_TYPE_ADDRESS64:
726
		pnpacpi_parse_address_option(dev, option, res);
B
Bjorn Helgaas 已提交
727
		break;
728

B
Bjorn Helgaas 已提交
729 730 731 732
	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
		break;

	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
733 734
		pnpacpi_parse_ext_irq_option(dev, option,
					     &res->data.extended_irq);
B
Bjorn Helgaas 已提交
735 736 737 738 739 740
		break;

	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
		break;

	default:
741 742
		dev_warn(&dev->dev, "unknown resource type %d in _PRS\n",
			 res->type);
B
Bjorn Helgaas 已提交
743
		return AE_ERROR;
L
Linus Torvalds 已提交
744
	}
B
Bjorn Helgaas 已提交
745

L
Linus Torvalds 已提交
746 747 748
	return AE_OK;
}

749
acpi_status __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)
L
Linus Torvalds 已提交
750
{
751
	acpi_handle handle = dev->data;
L
Linus Torvalds 已提交
752 753 754
	acpi_status status;
	struct acpipnp_parse_option_s parse_data;

755 756
	dev_dbg(&dev->dev, "parse resource options\n");

L
Linus Torvalds 已提交
757 758 759
	parse_data.option = pnp_register_independent_option(dev);
	if (!parse_data.option)
		return AE_ERROR;
M
Matthieu Castet 已提交
760
	parse_data.option_independent = parse_data.option;
L
Linus Torvalds 已提交
761
	parse_data.dev = dev;
B
Bob Moore 已提交
762
	status = acpi_walk_resources(handle, METHOD_NAME__PRS,
B
Bjorn Helgaas 已提交
763
				     pnpacpi_option_resource, &parse_data);
L
Linus Torvalds 已提交
764 765 766 767

	return status;
}

768
static int pnpacpi_supported_resource(struct acpi_resource *res)
L
Linus Torvalds 已提交
769
{
770
	switch (res->type) {
B
Bob Moore 已提交
771 772 773 774 775 776 777 778 779 780
	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:
781
	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
782
		return 1;
L
Linus Torvalds 已提交
783
	}
784 785 786 787 788 789 790
	return 0;
}

/*
 * Set resource
 */
static acpi_status pnpacpi_count_resources(struct acpi_resource *res,
B
Bjorn Helgaas 已提交
791
					   void *data)
792
{
793
	int *res_cnt = data;
794 795 796

	if (pnpacpi_supported_resource(res))
		(*res_cnt)++;
L
Linus Torvalds 已提交
797 798 799
	return AE_OK;
}

B
Bjorn Helgaas 已提交
800
static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data)
L
Linus Torvalds 已提交
801
{
802
	struct acpi_resource **resource = data;
803 804

	if (pnpacpi_supported_resource(res)) {
805
		(*resource)->type = res->type;
806
		(*resource)->length = sizeof(struct acpi_resource);
L
Linus Torvalds 已提交
807 808 809 810 811 812
		(*resource)++;
	}

	return AE_OK;
}

813
int pnpacpi_build_resource_template(struct pnp_dev *dev,
B
Bjorn Helgaas 已提交
814
				    struct acpi_buffer *buffer)
L
Linus Torvalds 已提交
815
{
816
	acpi_handle handle = dev->data;
L
Linus Torvalds 已提交
817 818 819 820
	struct acpi_resource *resource;
	int res_cnt = 0;
	acpi_status status;

B
Bob Moore 已提交
821
	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
B
Bjorn Helgaas 已提交
822
				     pnpacpi_count_resources, &res_cnt);
L
Linus Torvalds 已提交
823
	if (ACPI_FAILURE(status)) {
824
		dev_err(&dev->dev, "can't evaluate _CRS\n");
L
Linus Torvalds 已提交
825 826 827 828 829
		return -EINVAL;
	}
	if (!res_cnt)
		return -EINVAL;
	buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1;
830
	buffer->pointer = kzalloc(buffer->length - 1, GFP_KERNEL);
L
Linus Torvalds 已提交
831 832
	if (!buffer->pointer)
		return -ENOMEM;
833

L
Linus Torvalds 已提交
834
	resource = (struct acpi_resource *)buffer->pointer;
B
Bob Moore 已提交
835
	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
B
Bjorn Helgaas 已提交
836
				     pnpacpi_type_resources, &resource);
L
Linus Torvalds 已提交
837 838
	if (ACPI_FAILURE(status)) {
		kfree(buffer->pointer);
839
		dev_err(&dev->dev, "can't evaluate _CRS\n");
L
Linus Torvalds 已提交
840 841 842
		return -EINVAL;
	}
	/* resource will pointer the end resource now */
B
Bob Moore 已提交
843
	resource->type = ACPI_RESOURCE_TYPE_END_TAG;
L
Linus Torvalds 已提交
844 845 846 847

	return 0;
}

848 849
static void pnpacpi_encode_irq(struct pnp_dev *dev,
			       struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
850
			       struct resource *p)
L
Linus Torvalds 已提交
851
{
852
	struct acpi_resource_irq *irq = &resource->data.irq;
B
Bob Moore 已提交
853
	int triggering, polarity;
B
Bjorn Helgaas 已提交
854 855

	decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
856 857
	irq->triggering = triggering;
	irq->polarity = polarity;
B
Bob Moore 已提交
858
	if (triggering == ACPI_EDGE_SENSITIVE)
859
		irq->sharable = ACPI_EXCLUSIVE;
L
Linus Torvalds 已提交
860
	else
861 862 863
		irq->sharable = ACPI_SHARED;
	irq->interrupt_count = 1;
	irq->interrupts[0] = p->start;
864 865 866 867 868

	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 已提交
869 870
}

871 872
static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
				   struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
873
				   struct resource *p)
L
Linus Torvalds 已提交
874
{
875
	struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq;
B
Bob Moore 已提交
876
	int triggering, polarity;
B
Bjorn Helgaas 已提交
877 878

	decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
879 880 881
	extended_irq->producer_consumer = ACPI_CONSUMER;
	extended_irq->triggering = triggering;
	extended_irq->polarity = polarity;
B
Bob Moore 已提交
882
	if (triggering == ACPI_EDGE_SENSITIVE)
883
		extended_irq->sharable = ACPI_EXCLUSIVE;
L
Linus Torvalds 已提交
884
	else
885 886 887
		extended_irq->sharable = ACPI_SHARED;
	extended_irq->interrupt_count = 1;
	extended_irq->interrupts[0] = p->start;
888 889 890 891 892

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

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

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

	switch (p->flags & IORESOURCE_DMA_TYPE_MASK) {
B
Bjorn Helgaas 已提交
917
	case IORESOURCE_DMA_8BIT:
918
		dma->transfer = ACPI_TRANSFER_8;
B
Bjorn Helgaas 已提交
919 920
		break;
	case IORESOURCE_DMA_8AND16BIT:
921
		dma->transfer = ACPI_TRANSFER_8_16;
B
Bjorn Helgaas 已提交
922 923
		break;
	default:
924
		dma->transfer = ACPI_TRANSFER_16;
925 926
	}

927 928 929
	dma->bus_master = !!(p->flags & IORESOURCE_DMA_MASTER);
	dma->channel_count = 1;
	dma->channels[0] = p->start;
930 931 932 933

	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 已提交
934 935
}

936 937
static void pnpacpi_encode_io(struct pnp_dev *dev,
			      struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
938
			      struct resource *p)
L
Linus Torvalds 已提交
939
{
940 941
	struct acpi_resource_io *io = &resource->data.io;

L
Linus Torvalds 已提交
942
	/* Note: pnp_assign_port will copy pnp_port->flags into p->flags */
943
	io->io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ?
B
Bjorn Helgaas 已提交
944
	    ACPI_DECODE_16 : ACPI_DECODE_10;
945 946 947 948
	io->minimum = p->start;
	io->maximum = p->end;
	io->alignment = 0;	/* Correct? */
	io->address_length = p->end - p->start + 1;
949 950 951 952

	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 已提交
953 954
}

955 956
static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
				    struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
957
				    struct resource *p)
L
Linus Torvalds 已提交
958
{
959 960 961 962
	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;
963 964 965

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

968 969
static void pnpacpi_encode_mem24(struct pnp_dev *dev,
				 struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
970
				 struct resource *p)
L
Linus Torvalds 已提交
971
{
972 973
	struct acpi_resource_memory24 *memory24 = &resource->data.memory24;

L
Linus Torvalds 已提交
974
	/* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */
975
	memory24->write_protect =
B
Bjorn Helgaas 已提交
976 977
	    (p->flags & IORESOURCE_MEM_WRITEABLE) ?
	    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
978 979 980 981
	memory24->minimum = p->start;
	memory24->maximum = p->end;
	memory24->alignment = 0;
	memory24->address_length = p->end - p->start + 1;
982 983 984 985

	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 已提交
986 987
}

988 989
static void pnpacpi_encode_mem32(struct pnp_dev *dev,
				 struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
990
				 struct resource *p)
L
Linus Torvalds 已提交
991
{
992 993 994
	struct acpi_resource_memory32 *memory32 = &resource->data.memory32;

	memory32->write_protect =
B
Bjorn Helgaas 已提交
995 996
	    (p->flags & IORESOURCE_MEM_WRITEABLE) ?
	    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
997 998 999 1000
	memory32->minimum = p->start;
	memory32->maximum = p->end;
	memory32->alignment = 0;
	memory32->address_length = p->end - p->start + 1;
1001 1002 1003 1004

	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 已提交
1005 1006
}

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

	fixed_memory32->write_protect =
B
Bjorn Helgaas 已提交
1014 1015
	    (p->flags & IORESOURCE_MEM_WRITEABLE) ?
	    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
1016 1017
	fixed_memory32->address = p->start;
	fixed_memory32->address_length = p->end - p->start + 1;
1018 1019 1020 1021 1022

	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 已提交
1023 1024
}

1025
int pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer)
L
Linus Torvalds 已提交
1026 1027 1028
{
	int i = 0;
	/* pnpacpi_build_resource_template allocates extra mem */
B
Bjorn Helgaas 已提交
1029
	int res_cnt = (buffer->length - 1) / sizeof(struct acpi_resource) - 1;
1030
	struct acpi_resource *resource = buffer->pointer;
L
Linus Torvalds 已提交
1031 1032
	int port = 0, irq = 0, dma = 0, mem = 0;

1033
	dev_dbg(&dev->dev, "encode %d resources\n", res_cnt);
L
Linus Torvalds 已提交
1034
	while (i < res_cnt) {
B
Bjorn Helgaas 已提交
1035
		switch (resource->type) {
B
Bob Moore 已提交
1036
		case ACPI_RESOURCE_TYPE_IRQ:
1037
			pnpacpi_encode_irq(dev, resource,
1038
			       pnp_get_resource(dev, IORESOURCE_IRQ, irq));
L
Linus Torvalds 已提交
1039 1040 1041
			irq++;
			break;

B
Bob Moore 已提交
1042
		case ACPI_RESOURCE_TYPE_DMA:
1043
			pnpacpi_encode_dma(dev, resource,
1044
				pnp_get_resource(dev, IORESOURCE_DMA, dma));
B
Bjorn Helgaas 已提交
1045
			dma++;
L
Linus Torvalds 已提交
1046
			break;
B
Bob Moore 已提交
1047
		case ACPI_RESOURCE_TYPE_IO:
1048
			pnpacpi_encode_io(dev, resource,
1049
				pnp_get_resource(dev, IORESOURCE_IO, port));
B
Bjorn Helgaas 已提交
1050
			port++;
L
Linus Torvalds 已提交
1051
			break;
B
Bob Moore 已提交
1052
		case ACPI_RESOURCE_TYPE_FIXED_IO:
1053
			pnpacpi_encode_fixed_io(dev, resource,
1054
				pnp_get_resource(dev, IORESOURCE_IO, port));
B
Bjorn Helgaas 已提交
1055
			port++;
L
Linus Torvalds 已提交
1056
			break;
B
Bob Moore 已提交
1057
		case ACPI_RESOURCE_TYPE_MEMORY24:
1058
			pnpacpi_encode_mem24(dev, resource,
1059
				pnp_get_resource(dev, IORESOURCE_MEM, mem));
B
Bjorn Helgaas 已提交
1060
			mem++;
L
Linus Torvalds 已提交
1061
			break;
B
Bob Moore 已提交
1062
		case ACPI_RESOURCE_TYPE_MEMORY32:
1063
			pnpacpi_encode_mem32(dev, resource,
1064
				pnp_get_resource(dev, IORESOURCE_MEM, mem));
B
Bjorn Helgaas 已提交
1065
			mem++;
L
Linus Torvalds 已提交
1066
			break;
B
Bob Moore 已提交
1067
		case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
1068
			pnpacpi_encode_fixed_mem32(dev, resource,
1069
				pnp_get_resource(dev, IORESOURCE_MEM, mem));
B
Bjorn Helgaas 已提交
1070
			mem++;
L
Linus Torvalds 已提交
1071
			break;
1072
		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
1073
			pnpacpi_encode_ext_irq(dev, resource,
1074
				pnp_get_resource(dev, IORESOURCE_IRQ, irq));
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
			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 已提交
1086
		default:	/* other type */
1087 1088
			dev_warn(&dev->dev, "can't encode unknown resource "
				 "type %d\n", resource->type);
L
Linus Torvalds 已提交
1089 1090
			return -EINVAL;
		}
B
Bjorn Helgaas 已提交
1091 1092
		resource++;
		i++;
L
Linus Torvalds 已提交
1093 1094 1095
	}
	return 0;
}