rsparser.c 28.4 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5
/*
 * pnpacpi -- PnP ACPI driver
 *
 * Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr>
 * Copyright (c) 2004 Li Shaohua <shaohua.li@intel.com>
B
Bob Moore 已提交
6
 *
L
Linus Torvalds 已提交
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
 * 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>
#include "pnpacpi.h"

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

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

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

	if (shareable)
		flags |= IORESOURCE_IRQ_SHAREABLE;

	return flags;
L
Linus Torvalds 已提交
55 56
}

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

79
static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
B
Bjorn Helgaas 已提交
80 81
						u32 gsi, int triggering,
						int polarity, int shareable)
L
Linus Torvalds 已提交
82
{
83
	struct pnp_resource_table *res = &dev->res;
L
Linus Torvalds 已提交
84
	int i = 0;
85
	int irq;
86
	int p, t;
87
	static unsigned char warned;
88 89 90 91

	if (!valid_IRQ(gsi))
		return;

L
Linus Torvalds 已提交
92
	while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) &&
B
Bjorn Helgaas 已提交
93
	       i < PNP_MAX_IRQ)
L
Linus Torvalds 已提交
94
		i++;
95 96 97 98 99 100
	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;
		}
101
		return;
102
	}
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
	/*
	 * 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) {
			pnp_warn("IRQ %d override to %s, %s",
				gsi, t ? "edge":"level", p ? "low":"high");
			triggering = t;
			polarity = p;
		}
	}

B
Bjorn Helgaas 已提交
120
	res->irq_resource[i].flags = IORESOURCE_IRQ;	// Also clears _UNSET flag
121
	res->irq_resource[i].flags |= irq_flags(triggering, polarity, shareable);
B
Bob Moore 已提交
122
	irq = acpi_register_gsi(gsi, triggering, polarity);
123 124 125
	if (irq < 0) {
		res->irq_resource[i].flags |= IORESOURCE_DISABLED;
		return;
L
Linus Torvalds 已提交
126
	}
127 128 129 130

	res->irq_resource[i].start = irq;
	res->irq_resource[i].end = irq;
	pcibios_penalize_isa_irq(irq, 1);
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
static void pnpacpi_parse_allocated_dmaresource(struct pnp_dev *dev,
177
						u32 dma, int flags)
L
Linus Torvalds 已提交
178
{
179
	struct pnp_resource_table *res = &dev->res;
L
Linus Torvalds 已提交
180
	int i = 0;
181
	static unsigned char warned;
B
Bjorn Helgaas 已提交
182

183
	while (i < PNP_MAX_DMA &&
B
Bjorn Helgaas 已提交
184
	       !(res->dma_resource[i].flags & IORESOURCE_UNSET))
L
Linus Torvalds 已提交
185 186
		i++;
	if (i < PNP_MAX_DMA) {
B
Bjorn Helgaas 已提交
187
		res->dma_resource[i].flags = IORESOURCE_DMA;	// Also clears _UNSET flag
188
		res->dma_resource[i].flags |= flags;
L
Linus Torvalds 已提交
189 190 191 192
		if (dma == -1) {
			res->dma_resource[i].flags |= IORESOURCE_DISABLED;
			return;
		}
193 194
		res->dma_resource[i].start = dma;
		res->dma_resource[i].end = dma;
195
	} else if (!warned) {
196
		printk(KERN_WARNING "pnpacpi: exceeded the max number of DMA "
197
				"resources: %d \n", PNP_MAX_DMA);
198
		warned = 1;
L
Linus Torvalds 已提交
199 200 201
	}
}

202
static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev,
B
Bjorn Helgaas 已提交
203
					       u64 io, u64 len, int io_decode)
L
Linus Torvalds 已提交
204
{
205
	struct pnp_resource_table *res = &dev->res;
L
Linus Torvalds 已提交
206
	int i = 0;
207
	static unsigned char warned;
B
Bjorn Helgaas 已提交
208

L
Linus Torvalds 已提交
209
	while (!(res->port_resource[i].flags & IORESOURCE_UNSET) &&
B
Bjorn Helgaas 已提交
210
	       i < PNP_MAX_PORT)
L
Linus Torvalds 已提交
211 212
		i++;
	if (i < PNP_MAX_PORT) {
B
Bjorn Helgaas 已提交
213
		res->port_resource[i].flags = IORESOURCE_IO;	// Also clears _UNSET flag
214 215
		if (io_decode == ACPI_DECODE_16)
			res->port_resource[i].flags |= PNP_PORT_FLAG_16BITADDR;
B
Bjorn Helgaas 已提交
216
		if (len <= 0 || (io + len - 1) >= 0x10003) {
L
Linus Torvalds 已提交
217 218 219
			res->port_resource[i].flags |= IORESOURCE_DISABLED;
			return;
		}
220 221
		res->port_resource[i].start = io;
		res->port_resource[i].end = io + len - 1;
222
	} else if (!warned) {
223
		printk(KERN_WARNING "pnpacpi: exceeded the max number of IO "
224
				"resources: %d \n", PNP_MAX_PORT);
225
		warned = 1;
L
Linus Torvalds 已提交
226 227 228
	}
}

229
static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
B
Bjorn Helgaas 已提交
230 231
						u64 mem, u64 len,
						int write_protect)
L
Linus Torvalds 已提交
232
{
233
	struct pnp_resource_table *res = &dev->res;
L
Linus Torvalds 已提交
234
	int i = 0;
235
	static unsigned char warned;
B
Bjorn Helgaas 已提交
236

L
Linus Torvalds 已提交
237
	while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) &&
B
Bjorn Helgaas 已提交
238
	       (i < PNP_MAX_MEM))
L
Linus Torvalds 已提交
239 240
		i++;
	if (i < PNP_MAX_MEM) {
B
Bjorn Helgaas 已提交
241
		res->mem_resource[i].flags = IORESOURCE_MEM;	// Also clears _UNSET flag
L
Linus Torvalds 已提交
242 243 244 245
		if (len <= 0) {
			res->mem_resource[i].flags |= IORESOURCE_DISABLED;
			return;
		}
B
Bjorn Helgaas 已提交
246
		if (write_protect == ACPI_READ_WRITE_MEMORY)
247 248
			res->mem_resource[i].flags |= IORESOURCE_MEM_WRITEABLE;

249 250
		res->mem_resource[i].start = mem;
		res->mem_resource[i].end = mem + len - 1;
251
	} else if (!warned) {
252
		printk(KERN_WARNING "pnpacpi: exceeded the max number of mem "
253
				"resources: %d\n", PNP_MAX_MEM);
254
		warned = 1;
L
Linus Torvalds 已提交
255 256 257
	}
}

258
static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
B
Bjorn Helgaas 已提交
259
						  struct acpi_resource *res)
260 261 262 263 264 265 266
{
	struct acpi_resource_address64 addr, *p = &addr;
	acpi_status status;

	status = acpi_resource_to_address64(res, p);
	if (!ACPI_SUCCESS(status)) {
		pnp_warn("PnPACPI: failed to convert resource type %d",
B
Bjorn Helgaas 已提交
267
			 res->type);
268 269 270
		return;
	}

271 272 273
	if (p->producer_consumer == ACPI_PRODUCER)
		return;

274
	if (p->resource_type == ACPI_MEMORY_RANGE)
275
		pnpacpi_parse_allocated_memresource(dev,
B
Bjorn Helgaas 已提交
276 277
			p->minimum, p->address_length,
			p->info.mem.write_protect);
278
	else if (p->resource_type == ACPI_IO_RANGE)
279
		pnpacpi_parse_allocated_ioresource(dev,
B
Bjorn Helgaas 已提交
280 281 282
			p->minimum, p->address_length,
			p->granularity == 0xfff ? ACPI_DECODE_10 :
				ACPI_DECODE_16);
283
}
L
Linus Torvalds 已提交
284 285

static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
B
Bjorn Helgaas 已提交
286
					      void *data)
L
Linus Torvalds 已提交
287
{
288
	struct pnp_dev *dev = data;
289 290 291 292 293 294 295 296
	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;
297
	int i;
L
Linus Torvalds 已提交
298

299
	switch (res->type) {
B
Bob Moore 已提交
300
	case ACPI_RESOURCE_TYPE_IRQ:
301 302 303 304
		/*
		 * Per spec, only one interrupt per descriptor is allowed in
		 * _CRS, but some firmware violates this, so parse them all.
		 */
305 306
		irq = &res->data.irq;
		for (i = 0; i < irq->interrupt_count; i++) {
307
			pnpacpi_parse_allocated_irqresource(dev,
308 309 310 311
				irq->interrupts[i],
				irq->triggering,
				irq->polarity,
				irq->sharable);
L
Linus Torvalds 已提交
312 313 314
		}
		break;

B
Bob Moore 已提交
315
	case ACPI_RESOURCE_TYPE_DMA:
316 317
		dma = &res->data.dma;
		if (dma->channel_count > 0)
318
			pnpacpi_parse_allocated_dmaresource(dev,
319
				dma->channels[0],
320 321
				dma_flags(dma->type, dma->bus_master,
					  dma->transfer));
L
Linus Torvalds 已提交
322
		break;
323

B
Bob Moore 已提交
324
	case ACPI_RESOURCE_TYPE_IO:
325
		io = &res->data.io;
326
		pnpacpi_parse_allocated_ioresource(dev,
327 328 329
			io->minimum,
			io->address_length,
			io->io_decode);
L
Linus Torvalds 已提交
330
		break;
331 332 333 334 335

	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
		break;

B
Bob Moore 已提交
336
	case ACPI_RESOURCE_TYPE_FIXED_IO:
337
		fixed_io = &res->data.fixed_io;
338
		pnpacpi_parse_allocated_ioresource(dev,
339 340
			fixed_io->address,
			fixed_io->address_length,
B
Bjorn Helgaas 已提交
341
			ACPI_DECODE_10);
L
Linus Torvalds 已提交
342
		break;
343 344 345 346 347 348 349

	case ACPI_RESOURCE_TYPE_VENDOR:
		break;

	case ACPI_RESOURCE_TYPE_END_TAG:
		break;

B
Bob Moore 已提交
350
	case ACPI_RESOURCE_TYPE_MEMORY24:
351
		memory24 = &res->data.memory24;
352
		pnpacpi_parse_allocated_memresource(dev,
353 354 355
			memory24->minimum,
			memory24->address_length,
			memory24->write_protect);
L
Linus Torvalds 已提交
356
		break;
B
Bob Moore 已提交
357
	case ACPI_RESOURCE_TYPE_MEMORY32:
358
		memory32 = &res->data.memory32;
359
		pnpacpi_parse_allocated_memresource(dev,
360 361 362
			memory32->minimum,
			memory32->address_length,
			memory32->write_protect);
L
Linus Torvalds 已提交
363
		break;
B
Bob Moore 已提交
364
	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
365
		fixed_memory32 = &res->data.fixed_memory32;
366
		pnpacpi_parse_allocated_memresource(dev,
367 368 369
			fixed_memory32->address,
			fixed_memory32->address_length,
			fixed_memory32->write_protect);
L
Linus Torvalds 已提交
370
		break;
B
Bob Moore 已提交
371 372 373
	case ACPI_RESOURCE_TYPE_ADDRESS16:
	case ACPI_RESOURCE_TYPE_ADDRESS32:
	case ACPI_RESOURCE_TYPE_ADDRESS64:
374
		pnpacpi_parse_allocated_address_space(dev, res);
L
Linus Torvalds 已提交
375
		break;
376 377

	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
378 379
		if (res->data.ext_address64.producer_consumer == ACPI_PRODUCER)
			return AE_OK;
380 381 382
		break;

	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
383 384
		extended_irq = &res->data.extended_irq;
		if (extended_irq->producer_consumer == ACPI_PRODUCER)
385 386
			return AE_OK;

387
		for (i = 0; i < extended_irq->interrupt_count; i++) {
388
			pnpacpi_parse_allocated_irqresource(dev,
389 390 391 392
				extended_irq->interrupts[i],
				extended_irq->triggering,
				extended_irq->polarity,
				extended_irq->sharable);
393 394 395 396
		}
		break;

	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
L
Linus Torvalds 已提交
397
		break;
398

L
Linus Torvalds 已提交
399
	default:
400
		pnp_warn("PnPACPI: unknown resource type %d", res->type);
L
Linus Torvalds 已提交
401 402
		return AE_ERROR;
	}
B
Bjorn Helgaas 已提交
403

L
Linus Torvalds 已提交
404 405 406
	return AE_OK;
}

407
acpi_status pnpacpi_parse_allocated_resource(struct pnp_dev *dev)
L
Linus Torvalds 已提交
408
{
409 410
	acpi_handle handle = dev->data;

411 412
	dev_dbg(&dev->dev, "parse allocated resources\n");

L
Linus Torvalds 已提交
413
	/* Blank the resource table values */
414
	pnp_init_resource_table(&dev->res);
L
Linus Torvalds 已提交
415

B
Bjorn Helgaas 已提交
416
	return acpi_walk_resources(handle, METHOD_NAME__CRS,
417
				   pnpacpi_allocated_resource, dev);
L
Linus Torvalds 已提交
418 419
}

420 421
static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev,
					    struct pnp_option *option,
422
					    struct acpi_resource_dma *p)
L
Linus Torvalds 已提交
423 424
{
	int i;
B
Bjorn Helgaas 已提交
425
	struct pnp_dma *dma;
L
Linus Torvalds 已提交
426

B
Bob Moore 已提交
427
	if (p->channel_count == 0)
L
Linus Torvalds 已提交
428
		return;
429
	dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
L
Linus Torvalds 已提交
430 431 432
	if (!dma)
		return;

B
Bjorn Helgaas 已提交
433
	for (i = 0; i < p->channel_count; i++)
L
Linus Torvalds 已提交
434
		dma->map |= 1 << p->channels[i];
435 436

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

438
	pnp_register_dma_resource(dev, option, dma);
L
Linus Torvalds 已提交
439 440
}

441 442
static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
					    struct pnp_option *option,
443
					    struct acpi_resource_irq *p)
L
Linus Torvalds 已提交
444 445
{
	int i;
B
Bjorn Helgaas 已提交
446 447
	struct pnp_irq *irq;

B
Bob Moore 已提交
448
	if (p->interrupt_count == 0)
L
Linus Torvalds 已提交
449
		return;
450
	irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
L
Linus Torvalds 已提交
451 452 453
	if (!irq)
		return;

B
Bjorn Helgaas 已提交
454
	for (i = 0; i < p->interrupt_count; i++)
L
Linus Torvalds 已提交
455 456
		if (p->interrupts[i])
			__set_bit(p->interrupts[i], irq->map);
457
	irq->flags = irq_flags(p->triggering, p->polarity, p->sharable);
L
Linus Torvalds 已提交
458

459
	pnp_register_irq_resource(dev, option, irq);
L
Linus Torvalds 已提交
460 461
}

462 463
static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
						struct pnp_option *option,
464
					struct acpi_resource_extended_irq *p)
L
Linus Torvalds 已提交
465 466
{
	int i;
B
Bjorn Helgaas 已提交
467
	struct pnp_irq *irq;
L
Linus Torvalds 已提交
468

B
Bob Moore 已提交
469
	if (p->interrupt_count == 0)
L
Linus Torvalds 已提交
470
		return;
471
	irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
L
Linus Torvalds 已提交
472 473 474
	if (!irq)
		return;

B
Bjorn Helgaas 已提交
475
	for (i = 0; i < p->interrupt_count; i++)
L
Linus Torvalds 已提交
476 477
		if (p->interrupts[i])
			__set_bit(p->interrupts[i], irq->map);
478
	irq->flags = irq_flags(p->triggering, p->polarity, p->sharable);
L
Linus Torvalds 已提交
479

480
	pnp_register_irq_resource(dev, option, irq);
L
Linus Torvalds 已提交
481 482
}

483 484
static __init void pnpacpi_parse_port_option(struct pnp_dev *dev,
					     struct pnp_option *option,
485
					     struct acpi_resource_io *io)
L
Linus Torvalds 已提交
486
{
B
Bjorn Helgaas 已提交
487
	struct pnp_port *port;
L
Linus Torvalds 已提交
488

B
Bob Moore 已提交
489
	if (io->address_length == 0)
L
Linus Torvalds 已提交
490
		return;
491
	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
L
Linus Torvalds 已提交
492 493
	if (!port)
		return;
B
Bob Moore 已提交
494 495
	port->min = io->minimum;
	port->max = io->maximum;
L
Linus Torvalds 已提交
496
	port->align = io->alignment;
B
Bob Moore 已提交
497 498
	port->size = io->address_length;
	port->flags = ACPI_DECODE_16 == io->io_decode ?
B
Bjorn Helgaas 已提交
499
	    PNP_PORT_FLAG_16BITADDR : 0;
500
	pnp_register_port_resource(dev, option, port);
L
Linus Torvalds 已提交
501 502
}

503 504
static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev,
						   struct pnp_option *option,
505
					struct acpi_resource_fixed_io *io)
L
Linus Torvalds 已提交
506
{
B
Bjorn Helgaas 已提交
507
	struct pnp_port *port;
L
Linus Torvalds 已提交
508

B
Bob Moore 已提交
509
	if (io->address_length == 0)
L
Linus Torvalds 已提交
510
		return;
511
	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
L
Linus Torvalds 已提交
512 513
	if (!port)
		return;
B
Bob Moore 已提交
514 515
	port->min = port->max = io->address;
	port->size = io->address_length;
L
Linus Torvalds 已提交
516 517
	port->align = 0;
	port->flags = PNP_PORT_FLAG_FIXED;
518
	pnp_register_port_resource(dev, option, port);
L
Linus Torvalds 已提交
519 520
}

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

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

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

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

543 544
static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev,
					      struct pnp_option *option,
545
					      struct acpi_resource_memory32 *p)
L
Linus Torvalds 已提交
546
{
B
Bjorn Helgaas 已提交
547
	struct pnp_mem *mem;
L
Linus Torvalds 已提交
548

B
Bob Moore 已提交
549
	if (p->address_length == 0)
L
Linus Torvalds 已提交
550
		return;
551
	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
L
Linus Torvalds 已提交
552 553
	if (!mem)
		return;
B
Bob Moore 已提交
554 555
	mem->min = p->minimum;
	mem->max = p->maximum;
L
Linus Torvalds 已提交
556
	mem->align = p->alignment;
B
Bob Moore 已提交
557
	mem->size = p->address_length;
L
Linus Torvalds 已提交
558

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

562
	pnp_register_mem_resource(dev, option, mem);
L
Linus Torvalds 已提交
563 564
}

565 566
static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev,
						    struct pnp_option *option,
567
					struct acpi_resource_fixed_memory32 *p)
L
Linus Torvalds 已提交
568
{
B
Bjorn Helgaas 已提交
569
	struct pnp_mem *mem;
L
Linus Torvalds 已提交
570

B
Bob Moore 已提交
571
	if (p->address_length == 0)
L
Linus Torvalds 已提交
572
		return;
573
	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
L
Linus Torvalds 已提交
574 575
	if (!mem)
		return;
B
Bob Moore 已提交
576 577
	mem->min = mem->max = p->address;
	mem->size = p->address_length;
L
Linus Torvalds 已提交
578 579
	mem->align = 0;

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

583
	pnp_register_mem_resource(dev, option, mem);
L
Linus Torvalds 已提交
584 585
}

586 587
static __init void pnpacpi_parse_address_option(struct pnp_dev *dev,
						struct pnp_option *option,
588
						struct acpi_resource *r)
589 590 591
{
	struct acpi_resource_address64 addr, *p = &addr;
	acpi_status status;
B
Bjorn Helgaas 已提交
592 593
	struct pnp_mem *mem;
	struct pnp_port *port;
594 595 596

	status = acpi_resource_to_address64(r, p);
	if (!ACPI_SUCCESS(status)) {
B
Bjorn Helgaas 已提交
597 598
		pnp_warn("PnPACPI: failed to convert resource type %d",
			 r->type);
599 600 601 602 603 604 605
		return;
	}

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

	if (p->resource_type == ACPI_MEMORY_RANGE) {
606
		mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
607 608
		if (!mem)
			return;
L
Len Brown 已提交
609
		mem->min = mem->max = p->minimum;
610 611
		mem->size = p->address_length;
		mem->align = 0;
L
Len Brown 已提交
612
		mem->flags = (p->info.mem.write_protect ==
B
Bjorn Helgaas 已提交
613 614
			      ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE
		    : 0;
615
		pnp_register_mem_resource(dev, option, mem);
616
	} else if (p->resource_type == ACPI_IO_RANGE) {
617
		port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
618 619
		if (!port)
			return;
L
Len Brown 已提交
620
		port->min = port->max = p->minimum;
621 622 623
		port->size = p->address_length;
		port->align = 0;
		port->flags = PNP_PORT_FLAG_FIXED;
624
		pnp_register_port_resource(dev, option, port);
625 626 627
	}
}

L
Linus Torvalds 已提交
628 629
struct acpipnp_parse_option_s {
	struct pnp_option *option;
M
Matthieu Castet 已提交
630
	struct pnp_option *option_independent;
L
Linus Torvalds 已提交
631 632 633
	struct pnp_dev *dev;
};

634 635
static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
						  void *data)
L
Linus Torvalds 已提交
636 637
{
	int priority = 0;
638
	struct acpipnp_parse_option_s *parse_data = data;
L
Linus Torvalds 已提交
639 640 641
	struct pnp_dev *dev = parse_data->dev;
	struct pnp_option *option = parse_data->option;

642
	switch (res->type) {
B
Bjorn Helgaas 已提交
643
	case ACPI_RESOURCE_TYPE_IRQ:
644
		pnpacpi_parse_irq_option(dev, option, &res->data.irq);
B
Bjorn Helgaas 已提交
645
		break;
646

B
Bjorn Helgaas 已提交
647
	case ACPI_RESOURCE_TYPE_DMA:
648
		pnpacpi_parse_dma_option(dev, option, &res->data.dma);
B
Bjorn Helgaas 已提交
649
		break;
650

B
Bjorn Helgaas 已提交
651 652 653 654
	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 已提交
655
			break;
656

B
Bjorn Helgaas 已提交
657 658
		case ACPI_ACCEPTABLE_CONFIGURATION:
			priority = PNP_RES_PRIORITY_ACCEPTABLE;
M
Matthieu Castet 已提交
659
			break;
660

B
Bjorn Helgaas 已提交
661 662
		case ACPI_SUB_OPTIMAL_CONFIGURATION:
			priority = PNP_RES_PRIORITY_FUNCTIONAL;
663
			break;
B
Bjorn Helgaas 已提交
664 665
		default:
			priority = PNP_RES_PRIORITY_INVALID;
666
			break;
B
Bjorn Helgaas 已提交
667
		}
B
Bjorn Helgaas 已提交
668
		/* TBD: Consider performance/robustness bits */
B
Bjorn Helgaas 已提交
669 670 671 672 673
		option = pnp_register_dependent_option(dev, priority);
		if (!option)
			return AE_ERROR;
		parse_data->option = option;
		break;
674

B
Bjorn Helgaas 已提交
675 676 677 678 679 680 681 682
	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
		/*only one EndDependentFn is allowed */
		if (!parse_data->option_independent) {
			pnp_warn("PnPACPI: more than one EndDependentFn");
			return AE_ERROR;
		}
		parse_data->option = parse_data->option_independent;
		parse_data->option_independent = NULL;
683
		dev_dbg(&dev->dev, "end dependent options\n");
B
Bjorn Helgaas 已提交
684
		break;
685

B
Bjorn Helgaas 已提交
686
	case ACPI_RESOURCE_TYPE_IO:
687
		pnpacpi_parse_port_option(dev, option, &res->data.io);
B
Bjorn Helgaas 已提交
688
		break;
689

B
Bjorn Helgaas 已提交
690
	case ACPI_RESOURCE_TYPE_FIXED_IO:
691 692
		pnpacpi_parse_fixed_port_option(dev, option,
					        &res->data.fixed_io);
B
Bjorn Helgaas 已提交
693
		break;
694

B
Bjorn Helgaas 已提交
695 696 697
	case ACPI_RESOURCE_TYPE_VENDOR:
	case ACPI_RESOURCE_TYPE_END_TAG:
		break;
698

B
Bjorn Helgaas 已提交
699
	case ACPI_RESOURCE_TYPE_MEMORY24:
700
		pnpacpi_parse_mem24_option(dev, option, &res->data.memory24);
B
Bjorn Helgaas 已提交
701
		break;
702

B
Bjorn Helgaas 已提交
703
	case ACPI_RESOURCE_TYPE_MEMORY32:
704
		pnpacpi_parse_mem32_option(dev, option, &res->data.memory32);
B
Bjorn Helgaas 已提交
705
		break;
706

B
Bjorn Helgaas 已提交
707
	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
708
		pnpacpi_parse_fixed_mem32_option(dev, option,
B
Bjorn Helgaas 已提交
709 710
						 &res->data.fixed_memory32);
		break;
711

B
Bjorn Helgaas 已提交
712 713 714
	case ACPI_RESOURCE_TYPE_ADDRESS16:
	case ACPI_RESOURCE_TYPE_ADDRESS32:
	case ACPI_RESOURCE_TYPE_ADDRESS64:
715
		pnpacpi_parse_address_option(dev, option, res);
B
Bjorn Helgaas 已提交
716
		break;
717

B
Bjorn Helgaas 已提交
718 719 720 721
	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
		break;

	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
722 723
		pnpacpi_parse_ext_irq_option(dev, option,
					     &res->data.extended_irq);
B
Bjorn Helgaas 已提交
724 725 726 727 728 729 730 731
		break;

	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
		break;

	default:
		pnp_warn("PnPACPI: unknown resource type %d", res->type);
		return AE_ERROR;
L
Linus Torvalds 已提交
732
	}
B
Bjorn Helgaas 已提交
733

L
Linus Torvalds 已提交
734 735 736
	return AE_OK;
}

737
acpi_status __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)
L
Linus Torvalds 已提交
738
{
739
	acpi_handle handle = dev->data;
L
Linus Torvalds 已提交
740 741 742
	acpi_status status;
	struct acpipnp_parse_option_s parse_data;

743 744
	dev_dbg(&dev->dev, "parse resource options\n");

L
Linus Torvalds 已提交
745 746 747
	parse_data.option = pnp_register_independent_option(dev);
	if (!parse_data.option)
		return AE_ERROR;
M
Matthieu Castet 已提交
748
	parse_data.option_independent = parse_data.option;
L
Linus Torvalds 已提交
749
	parse_data.dev = dev;
B
Bob Moore 已提交
750
	status = acpi_walk_resources(handle, METHOD_NAME__PRS,
B
Bjorn Helgaas 已提交
751
				     pnpacpi_option_resource, &parse_data);
L
Linus Torvalds 已提交
752 753 754 755

	return status;
}

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

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

	if (pnpacpi_supported_resource(res))
		(*res_cnt)++;
L
Linus Torvalds 已提交
785 786 787
	return AE_OK;
}

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

	if (pnpacpi_supported_resource(res)) {
793
		(*resource)->type = res->type;
794
		(*resource)->length = sizeof(struct acpi_resource);
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 812 813 814 815 816 817
	if (ACPI_FAILURE(status)) {
		pnp_err("Evaluate _CRS failed");
		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 827 828 829 830
	if (ACPI_FAILURE(status)) {
		kfree(buffer->pointer);
		pnp_err("Evaluate _CRS failed");
		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;
B
Bob Moore 已提交
841
	int triggering, polarity;
B
Bjorn Helgaas 已提交
842 843

	decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
844 845
	irq->triggering = triggering;
	irq->polarity = polarity;
B
Bob Moore 已提交
846
	if (triggering == ACPI_EDGE_SENSITIVE)
847
		irq->sharable = ACPI_EXCLUSIVE;
L
Linus Torvalds 已提交
848
	else
849 850 851
		irq->sharable = ACPI_SHARED;
	irq->interrupt_count = 1;
	irq->interrupts[0] = p->start;
852 853 854 855 856

	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 已提交
857 858
}

859 860
static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
				   struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
861
				   struct resource *p)
L
Linus Torvalds 已提交
862
{
863
	struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq;
B
Bob Moore 已提交
864
	int triggering, polarity;
B
Bjorn Helgaas 已提交
865 866

	decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
867 868 869
	extended_irq->producer_consumer = ACPI_CONSUMER;
	extended_irq->triggering = triggering;
	extended_irq->polarity = polarity;
B
Bob Moore 已提交
870
	if (triggering == ACPI_EDGE_SENSITIVE)
871
		extended_irq->sharable = ACPI_EXCLUSIVE;
L
Linus Torvalds 已提交
872
	else
873 874 875
		extended_irq->sharable = ACPI_SHARED;
	extended_irq->interrupt_count = 1;
	extended_irq->interrupts[0] = p->start;
876 877 878 879 880

	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 已提交
881 882
}

883 884
static void pnpacpi_encode_dma(struct pnp_dev *dev,
			       struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
885
			       struct resource *p)
L
Linus Torvalds 已提交
886
{
887 888
	struct acpi_resource_dma *dma = &resource->data.dma;

L
Linus Torvalds 已提交
889
	/* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
890
	switch (p->flags & IORESOURCE_DMA_SPEED_MASK) {
B
Bjorn Helgaas 已提交
891
	case IORESOURCE_DMA_TYPEA:
892
		dma->type = ACPI_TYPE_A;
B
Bjorn Helgaas 已提交
893 894
		break;
	case IORESOURCE_DMA_TYPEB:
895
		dma->type = ACPI_TYPE_B;
B
Bjorn Helgaas 已提交
896 897
		break;
	case IORESOURCE_DMA_TYPEF:
898
		dma->type = ACPI_TYPE_F;
B
Bjorn Helgaas 已提交
899 900
		break;
	default:
901
		dma->type = ACPI_COMPATIBILITY;
902 903 904
	}

	switch (p->flags & IORESOURCE_DMA_TYPE_MASK) {
B
Bjorn Helgaas 已提交
905
	case IORESOURCE_DMA_8BIT:
906
		dma->transfer = ACPI_TRANSFER_8;
B
Bjorn Helgaas 已提交
907 908
		break;
	case IORESOURCE_DMA_8AND16BIT:
909
		dma->transfer = ACPI_TRANSFER_8_16;
B
Bjorn Helgaas 已提交
910 911
		break;
	default:
912
		dma->transfer = ACPI_TRANSFER_16;
913 914
	}

915 916 917
	dma->bus_master = !!(p->flags & IORESOURCE_DMA_MASTER);
	dma->channel_count = 1;
	dma->channels[0] = p->start;
918 919 920 921

	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 已提交
922 923
}

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

L
Linus Torvalds 已提交
930
	/* Note: pnp_assign_port will copy pnp_port->flags into p->flags */
931
	io->io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ?
B
Bjorn Helgaas 已提交
932
	    ACPI_DECODE_16 : ACPI_DECODE_10;
933 934 935 936
	io->minimum = p->start;
	io->maximum = p->end;
	io->alignment = 0;	/* Correct? */
	io->address_length = p->end - p->start + 1;
937 938 939 940

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

943 944
static void pnpacpi_encode_fixed_io(struct pnp_dev *dev,
				    struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
945
				    struct resource *p)
L
Linus Torvalds 已提交
946
{
947 948 949 950
	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;
951 952 953

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

956 957
static void pnpacpi_encode_mem24(struct pnp_dev *dev,
				 struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
958
				 struct resource *p)
L
Linus Torvalds 已提交
959
{
960 961
	struct acpi_resource_memory24 *memory24 = &resource->data.memory24;

L
Linus Torvalds 已提交
962
	/* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */
963
	memory24->write_protect =
B
Bjorn Helgaas 已提交
964 965
	    (p->flags & IORESOURCE_MEM_WRITEABLE) ?
	    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
966 967 968 969
	memory24->minimum = p->start;
	memory24->maximum = p->end;
	memory24->alignment = 0;
	memory24->address_length = p->end - p->start + 1;
970 971 972 973

	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 已提交
974 975
}

976 977
static void pnpacpi_encode_mem32(struct pnp_dev *dev,
				 struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
978
				 struct resource *p)
L
Linus Torvalds 已提交
979
{
980 981 982
	struct acpi_resource_memory32 *memory32 = &resource->data.memory32;

	memory32->write_protect =
B
Bjorn Helgaas 已提交
983 984
	    (p->flags & IORESOURCE_MEM_WRITEABLE) ?
	    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
985 986 987 988
	memory32->minimum = p->start;
	memory32->maximum = p->end;
	memory32->alignment = 0;
	memory32->address_length = p->end - p->start + 1;
989 990 991 992

	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 已提交
993 994
}

995 996
static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev,
				       struct acpi_resource *resource,
B
Bjorn Helgaas 已提交
997
				       struct resource *p)
L
Linus Torvalds 已提交
998
{
999 1000 1001
	struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32;

	fixed_memory32->write_protect =
B
Bjorn Helgaas 已提交
1002 1003
	    (p->flags & IORESOURCE_MEM_WRITEABLE) ?
	    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
1004 1005
	fixed_memory32->address = p->start;
	fixed_memory32->address_length = p->end - p->start + 1;
1006 1007 1008 1009 1010

	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 已提交
1011 1012
}

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

1022
	dev_dbg(&dev->dev, "encode %d resources\n", res_cnt);
L
Linus Torvalds 已提交
1023
	while (i < res_cnt) {
B
Bjorn Helgaas 已提交
1024
		switch (resource->type) {
B
Bob Moore 已提交
1025
		case ACPI_RESOURCE_TYPE_IRQ:
1026
			pnpacpi_encode_irq(dev, resource,
B
Bjorn Helgaas 已提交
1027
					   &res_table->irq_resource[irq]);
L
Linus Torvalds 已提交
1028 1029 1030
			irq++;
			break;

B
Bob Moore 已提交
1031
		case ACPI_RESOURCE_TYPE_DMA:
1032
			pnpacpi_encode_dma(dev, resource,
B
Bjorn Helgaas 已提交
1033
					   &res_table->dma_resource[dma]);
B
Bjorn Helgaas 已提交
1034
			dma++;
L
Linus Torvalds 已提交
1035
			break;
B
Bob Moore 已提交
1036
		case ACPI_RESOURCE_TYPE_IO:
1037
			pnpacpi_encode_io(dev, resource,
B
Bjorn Helgaas 已提交
1038
					  &res_table->port_resource[port]);
B
Bjorn Helgaas 已提交
1039
			port++;
L
Linus Torvalds 已提交
1040
			break;
B
Bob Moore 已提交
1041
		case ACPI_RESOURCE_TYPE_FIXED_IO:
1042
			pnpacpi_encode_fixed_io(dev, resource,
B
Bjorn Helgaas 已提交
1043 1044
						&res_table->
						port_resource[port]);
B
Bjorn Helgaas 已提交
1045
			port++;
L
Linus Torvalds 已提交
1046
			break;
B
Bob Moore 已提交
1047
		case ACPI_RESOURCE_TYPE_MEMORY24:
1048
			pnpacpi_encode_mem24(dev, resource,
B
Bjorn Helgaas 已提交
1049
					     &res_table->mem_resource[mem]);
B
Bjorn Helgaas 已提交
1050
			mem++;
L
Linus Torvalds 已提交
1051
			break;
B
Bob Moore 已提交
1052
		case ACPI_RESOURCE_TYPE_MEMORY32:
1053
			pnpacpi_encode_mem32(dev, resource,
B
Bjorn Helgaas 已提交
1054
					     &res_table->mem_resource[mem]);
B
Bjorn Helgaas 已提交
1055
			mem++;
L
Linus Torvalds 已提交
1056
			break;
B
Bob Moore 已提交
1057
		case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
1058
			pnpacpi_encode_fixed_mem32(dev, resource,
B
Bjorn Helgaas 已提交
1059 1060
						   &res_table->
						   mem_resource[mem]);
B
Bjorn Helgaas 已提交
1061
			mem++;
L
Linus Torvalds 已提交
1062
			break;
1063
		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
1064
			pnpacpi_encode_ext_irq(dev, resource,
B
Bjorn Helgaas 已提交
1065
					       &res_table->irq_resource[irq]);
1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076
			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 已提交
1077
		default:	/* other type */
1078
			pnp_warn("unknown resource type %d", resource->type);
L
Linus Torvalds 已提交
1079 1080
			return -EINVAL;
		}
B
Bjorn Helgaas 已提交
1081 1082
		resource++;
		i++;
L
Linus Torvalds 已提交
1083 1084 1085
	}
	return 0;
}