rsparser.c 22.5 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
 */
B
Bob Moore 已提交
35
static int irq_flags(int triggering, int polarity)
L
Linus Torvalds 已提交
36 37
{
	int flag;
B
Bob Moore 已提交
38 39
	if (triggering == ACPI_LEVEL_SENSITIVE) {
		if(polarity == ACPI_ACTIVE_LOW)
L
Linus Torvalds 已提交
40 41 42 43 44
			flag = IORESOURCE_IRQ_LOWLEVEL;
		else
			flag = IORESOURCE_IRQ_HIGHLEVEL;
	}
	else {
B
Bob Moore 已提交
45
		if(polarity == ACPI_ACTIVE_LOW)
L
Linus Torvalds 已提交
46 47 48 49 50 51 52
			flag = IORESOURCE_IRQ_LOWEDGE;
		else
			flag = IORESOURCE_IRQ_HIGHEDGE;
	}
	return flag;
}

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

static void
76
pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, u32 gsi,
B
Bob Moore 已提交
77
	int triggering, int polarity)
L
Linus Torvalds 已提交
78 79
{
	int i = 0;
80 81 82 83 84
	int irq;

	if (!valid_IRQ(gsi))
		return;

L
Linus Torvalds 已提交
85 86 87
	while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) &&
			i < PNP_MAX_IRQ)
		i++;
88 89 90 91
	if (i >= PNP_MAX_IRQ)
		return;

	res->irq_resource[i].flags = IORESOURCE_IRQ;  // Also clears _UNSET flag
B
Bob Moore 已提交
92
	irq = acpi_register_gsi(gsi, triggering, polarity);
93 94 95
	if (irq < 0) {
		res->irq_resource[i].flags |= IORESOURCE_DISABLED;
		return;
L
Linus Torvalds 已提交
96
	}
97 98 99 100

	res->irq_resource[i].start = irq;
	res->irq_resource[i].end = irq;
	pcibios_penalize_isa_irq(irq, 1);
L
Linus Torvalds 已提交
101 102 103
}

static void
104
pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, u32 dma)
L
Linus Torvalds 已提交
105 106
{
	int i = 0;
107 108
	while (i < PNP_MAX_DMA &&
			!(res->dma_resource[i].flags & IORESOURCE_UNSET))
L
Linus Torvalds 已提交
109 110 111 112 113 114 115
		i++;
	if (i < PNP_MAX_DMA) {
		res->dma_resource[i].flags = IORESOURCE_DMA;  // Also clears _UNSET flag
		if (dma == -1) {
			res->dma_resource[i].flags |= IORESOURCE_DISABLED;
			return;
		}
116 117
		res->dma_resource[i].start = dma;
		res->dma_resource[i].end = dma;
L
Linus Torvalds 已提交
118 119 120 121 122
	}
}

static void
pnpacpi_parse_allocated_ioresource(struct pnp_resource_table * res,
123
	u32 io, u32 len)
L
Linus Torvalds 已提交
124 125 126 127 128 129 130 131 132 133 134
{
	int i = 0;
	while (!(res->port_resource[i].flags & IORESOURCE_UNSET) &&
			i < PNP_MAX_PORT)
		i++;
	if (i < PNP_MAX_PORT) {
		res->port_resource[i].flags = IORESOURCE_IO;  // Also clears _UNSET flag
		if (len <= 0 || (io + len -1) >= 0x10003) {
			res->port_resource[i].flags |= IORESOURCE_DISABLED;
			return;
		}
135 136
		res->port_resource[i].start = io;
		res->port_resource[i].end = io + len - 1;
L
Linus Torvalds 已提交
137 138 139 140 141
	}
}

static void
pnpacpi_parse_allocated_memresource(struct pnp_resource_table * res,
142
	u64 mem, u64 len)
L
Linus Torvalds 已提交
143 144 145 146 147 148 149 150 151 152 153
{
	int i = 0;
	while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) &&
			(i < PNP_MAX_MEM))
		i++;
	if (i < PNP_MAX_MEM) {
		res->mem_resource[i].flags = IORESOURCE_MEM;  // Also clears _UNSET flag
		if (len <= 0) {
			res->mem_resource[i].flags |= IORESOURCE_DISABLED;
			return;
		}
154 155
		res->mem_resource[i].start = mem;
		res->mem_resource[i].end = mem + len - 1;
L
Linus Torvalds 已提交
156 157 158 159 160 161 162 163
	}
}


static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
	void *data)
{
	struct pnp_resource_table * res_table = (struct pnp_resource_table *)data;
164
	int i;
L
Linus Torvalds 已提交
165

166
	switch (res->type) {
B
Bob Moore 已提交
167
	case ACPI_RESOURCE_TYPE_IRQ:
168 169 170 171
		/*
		 * Per spec, only one interrupt per descriptor is allowed in
		 * _CRS, but some firmware violates this, so parse them all.
		 */
B
Bob Moore 已提交
172
		for (i = 0; i < res->data.irq.interrupt_count; i++) {
173 174
			pnpacpi_parse_allocated_irqresource(res_table,
				res->data.irq.interrupts[i],
B
Bob Moore 已提交
175 176
				res->data.irq.triggering,
				res->data.irq.polarity);
L
Linus Torvalds 已提交
177 178 179
		}
		break;

B
Bob Moore 已提交
180 181
	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
		for (i = 0; i < res->data.extended_irq.interrupt_count; i++) {
182 183
			pnpacpi_parse_allocated_irqresource(res_table,
				res->data.extended_irq.interrupts[i],
B
Bob Moore 已提交
184 185
				res->data.extended_irq.triggering,
				res->data.extended_irq.polarity);
L
Linus Torvalds 已提交
186 187
		}
		break;
B
Bob Moore 已提交
188 189 190
	case ACPI_RESOURCE_TYPE_DMA:
		if (res->data.dma.channel_count > 0)
			pnpacpi_parse_allocated_dmaresource(res_table,
L
Linus Torvalds 已提交
191 192
					res->data.dma.channels[0]);
		break;
B
Bob Moore 已提交
193 194 195 196
	case ACPI_RESOURCE_TYPE_IO:
		pnpacpi_parse_allocated_ioresource(res_table,
				res->data.io.minimum,
				res->data.io.address_length);
L
Linus Torvalds 已提交
197
		break;
B
Bob Moore 已提交
198 199 200 201
	case ACPI_RESOURCE_TYPE_FIXED_IO:
		pnpacpi_parse_allocated_ioresource(res_table,
				res->data.fixed_io.address,
				res->data.fixed_io.address_length);
L
Linus Torvalds 已提交
202
		break;
B
Bob Moore 已提交
203 204 205 206
	case ACPI_RESOURCE_TYPE_MEMORY24:
		pnpacpi_parse_allocated_memresource(res_table,
				res->data.memory24.minimum,
				res->data.memory24.address_length);
L
Linus Torvalds 已提交
207
		break;
B
Bob Moore 已提交
208 209 210 211
	case ACPI_RESOURCE_TYPE_MEMORY32:
		pnpacpi_parse_allocated_memresource(res_table,
				res->data.memory32.minimum,
				res->data.memory32.address_length);
L
Linus Torvalds 已提交
212
		break;
B
Bob Moore 已提交
213 214 215 216
	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
		pnpacpi_parse_allocated_memresource(res_table,
				res->data.fixed_memory32.address,
				res->data.fixed_memory32.address_length);
L
Linus Torvalds 已提交
217
		break;
B
Bob Moore 已提交
218 219 220
	case ACPI_RESOURCE_TYPE_ADDRESS16:
		pnpacpi_parse_allocated_memresource(res_table,
				res->data.address16.minimum,
L
Linus Torvalds 已提交
221 222
				res->data.address16.address_length);
		break;
B
Bob Moore 已提交
223 224 225
	case ACPI_RESOURCE_TYPE_ADDRESS32:
		pnpacpi_parse_allocated_memresource(res_table,
				res->data.address32.minimum,
L
Linus Torvalds 已提交
226 227
				res->data.address32.address_length);
		break;
B
Bob Moore 已提交
228 229 230
	case ACPI_RESOURCE_TYPE_ADDRESS64:
		pnpacpi_parse_allocated_memresource(res_table,
		res->data.address64.minimum,
L
Linus Torvalds 已提交
231 232
		res->data.address64.address_length);
		break;
B
Bob Moore 已提交
233
	case ACPI_RESOURCE_TYPE_VENDOR:
L
Linus Torvalds 已提交
234 235
		break;
	default:
236
		pnp_warn("PnPACPI: unknown resource type %d", res->type);
L
Linus Torvalds 已提交
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
		return AE_ERROR;
	}
			
	return AE_OK;
}

acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle, struct pnp_resource_table * res)
{
	/* Blank the resource table values */
	pnp_init_resource_table(res);

	return acpi_walk_resources(handle, METHOD_NAME__CRS, pnpacpi_allocated_resource, res);
}

static void pnpacpi_parse_dma_option(struct pnp_option *option, struct acpi_resource_dma *p)
{
	int i;
	struct pnp_dma * dma;

B
Bob Moore 已提交
256
	if (p->channel_count == 0)
L
Linus Torvalds 已提交
257
		return;
258
	dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL);
L
Linus Torvalds 已提交
259 260 261
	if (!dma)
		return;

B
Bob Moore 已提交
262
	for(i = 0; i < p->channel_count; i++)
L
Linus Torvalds 已提交
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
		dma->map |= 1 << p->channels[i];
	dma->flags = 0;
	if (p->bus_master)
		dma->flags |= IORESOURCE_DMA_MASTER;
	switch (p->type) {
	case ACPI_COMPATIBILITY:
		dma->flags |= IORESOURCE_DMA_COMPATIBLE;
		break;
	case ACPI_TYPE_A:
		dma->flags |= IORESOURCE_DMA_TYPEA;
		break;
	case ACPI_TYPE_B:
		dma->flags |= IORESOURCE_DMA_TYPEB;
		break;
	case ACPI_TYPE_F:
		dma->flags |= IORESOURCE_DMA_TYPEF;
		break;
	default:
		/* Set a default value ? */
		dma->flags |= IORESOURCE_DMA_COMPATIBLE;
		pnp_err("Invalid DMA type");
	}
	switch (p->transfer) {
	case ACPI_TRANSFER_8:
		dma->flags |= IORESOURCE_DMA_8BIT;
		break;
	case ACPI_TRANSFER_8_16:
		dma->flags |= IORESOURCE_DMA_8AND16BIT;
		break;
	case ACPI_TRANSFER_16:
		dma->flags |= IORESOURCE_DMA_16BIT;
		break;
	default:
		/* Set a default value ? */
		dma->flags |= IORESOURCE_DMA_8AND16BIT;
		pnp_err("Invalid DMA transfer type");
	}

	pnp_register_dma_resource(option,dma);
	return;
}

	
static void pnpacpi_parse_irq_option(struct pnp_option *option,
	struct acpi_resource_irq *p)
{
	int i;
	struct pnp_irq * irq;
	
B
Bob Moore 已提交
312
	if (p->interrupt_count == 0)
L
Linus Torvalds 已提交
313
		return;
314
	irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
L
Linus Torvalds 已提交
315 316 317
	if (!irq)
		return;

B
Bob Moore 已提交
318
	for(i = 0; i < p->interrupt_count; i++)
L
Linus Torvalds 已提交
319 320
		if (p->interrupts[i])
			__set_bit(p->interrupts[i], irq->map);
B
Bob Moore 已提交
321
	irq->flags = irq_flags(p->triggering, p->polarity);
L
Linus Torvalds 已提交
322 323 324 325 326 327

	pnp_register_irq_resource(option, irq);
	return;
}

static void pnpacpi_parse_ext_irq_option(struct pnp_option *option,
B
Bob Moore 已提交
328
	struct acpi_resource_extended_irq *p)
L
Linus Torvalds 已提交
329 330 331 332
{
	int i;
	struct pnp_irq * irq;

B
Bob Moore 已提交
333
	if (p->interrupt_count == 0)
L
Linus Torvalds 已提交
334
		return;
335
	irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
L
Linus Torvalds 已提交
336 337 338
	if (!irq)
		return;

B
Bob Moore 已提交
339
	for(i = 0; i < p->interrupt_count; i++)
L
Linus Torvalds 已提交
340 341
		if (p->interrupts[i])
			__set_bit(p->interrupts[i], irq->map);
B
Bob Moore 已提交
342
	irq->flags = irq_flags(p->triggering, p->polarity);
L
Linus Torvalds 已提交
343 344 345 346 347 348 349 350 351 352 353

	pnp_register_irq_resource(option, irq);
	return;
}

static void
pnpacpi_parse_port_option(struct pnp_option *option,
	struct acpi_resource_io *io)
{
	struct pnp_port * port;

B
Bob Moore 已提交
354
	if (io->address_length == 0)
L
Linus Torvalds 已提交
355
		return;
356
	port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
L
Linus Torvalds 已提交
357 358
	if (!port)
		return;
B
Bob Moore 已提交
359 360
	port->min = io->minimum;
	port->max = io->maximum;
L
Linus Torvalds 已提交
361
	port->align = io->alignment;
B
Bob Moore 已提交
362 363
	port->size = io->address_length;
	port->flags = ACPI_DECODE_16 == io->io_decode ?
L
Linus Torvalds 已提交
364 365 366 367 368 369 370 371 372 373 374
		PNP_PORT_FLAG_16BITADDR : 0;
	pnp_register_port_resource(option,port);
	return;
}

static void
pnpacpi_parse_fixed_port_option(struct pnp_option *option,
	struct acpi_resource_fixed_io *io)
{
	struct pnp_port * port;

B
Bob Moore 已提交
375
	if (io->address_length == 0)
L
Linus Torvalds 已提交
376
		return;
377
	port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
L
Linus Torvalds 已提交
378 379
	if (!port)
		return;
B
Bob Moore 已提交
380 381
	port->min = port->max = io->address;
	port->size = io->address_length;
L
Linus Torvalds 已提交
382 383 384 385 386 387 388 389
	port->align = 0;
	port->flags = PNP_PORT_FLAG_FIXED;
	pnp_register_port_resource(option,port);
	return;
}

static void
pnpacpi_parse_mem24_option(struct pnp_option *option,
B
Bob Moore 已提交
390
	struct acpi_resource_memory24 *p)
L
Linus Torvalds 已提交
391 392 393
{
	struct pnp_mem * mem;

B
Bob Moore 已提交
394
	if (p->address_length == 0)
L
Linus Torvalds 已提交
395
		return;
396
	mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
L
Linus Torvalds 已提交
397 398
	if (!mem)
		return;
B
Bob Moore 已提交
399 400
	mem->min = p->minimum;
	mem->max = p->maximum;
L
Linus Torvalds 已提交
401
	mem->align = p->alignment;
B
Bob Moore 已提交
402
	mem->size = p->address_length;
L
Linus Torvalds 已提交
403 404 405 406 407 408 409 410 411 412

	mem->flags = (ACPI_READ_WRITE_MEMORY == p->read_write_attribute) ?
			IORESOURCE_MEM_WRITEABLE : 0;

	pnp_register_mem_resource(option,mem);
	return;
}

static void
pnpacpi_parse_mem32_option(struct pnp_option *option,
B
Bob Moore 已提交
413
	struct acpi_resource_memory32 *p)
L
Linus Torvalds 已提交
414 415 416
{
	struct pnp_mem * mem;

B
Bob Moore 已提交
417
	if (p->address_length == 0)
L
Linus Torvalds 已提交
418
		return;
419
	mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
L
Linus Torvalds 已提交
420 421
	if (!mem)
		return;
B
Bob Moore 已提交
422 423
	mem->min = p->minimum;
	mem->max = p->maximum;
L
Linus Torvalds 已提交
424
	mem->align = p->alignment;
B
Bob Moore 已提交
425
	mem->size = p->address_length;
L
Linus Torvalds 已提交
426 427 428 429 430 431 432 433 434 435

	mem->flags = (ACPI_READ_WRITE_MEMORY == p->read_write_attribute) ?
			IORESOURCE_MEM_WRITEABLE : 0;

	pnp_register_mem_resource(option,mem);
	return;
}

static void
pnpacpi_parse_fixed_mem32_option(struct pnp_option *option,
B
Bob Moore 已提交
436
	struct acpi_resource_fixed_memory32 *p)
L
Linus Torvalds 已提交
437 438 439
{
	struct pnp_mem * mem;

B
Bob Moore 已提交
440
	if (p->address_length == 0)
L
Linus Torvalds 已提交
441
		return;
442
	mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL);
L
Linus Torvalds 已提交
443 444
	if (!mem)
		return;
B
Bob Moore 已提交
445 446
	mem->min = mem->max = p->address;
	mem->size = p->address_length;
L
Linus Torvalds 已提交
447 448 449 450 451 452 453 454 455 456 457
	mem->align = 0;

	mem->flags = (ACPI_READ_WRITE_MEMORY == p->read_write_attribute) ?
			IORESOURCE_MEM_WRITEABLE : 0;

	pnp_register_mem_resource(option,mem);
	return;
}

struct acpipnp_parse_option_s {
	struct pnp_option *option;
M
Matthieu Castet 已提交
458
	struct pnp_option *option_independent;
L
Linus Torvalds 已提交
459 460 461
	struct pnp_dev *dev;
};

B
Bob Moore 已提交
462
static acpi_status pnpacpi_option_resource(struct acpi_resource *res,
L
Linus Torvalds 已提交
463 464 465 466 467 468 469
	void *data)
{
	int priority = 0;
	struct acpipnp_parse_option_s *parse_data = (struct acpipnp_parse_option_s *)data;
	struct pnp_dev *dev = parse_data->dev;
	struct pnp_option *option = parse_data->option;

470
	switch (res->type) {
B
Bob Moore 已提交
471
		case ACPI_RESOURCE_TYPE_IRQ:
L
Linus Torvalds 已提交
472 473
			pnpacpi_parse_irq_option(option, &res->data.irq);
			break;
B
Bob Moore 已提交
474
		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
L
Linus Torvalds 已提交
475 476 477
			pnpacpi_parse_ext_irq_option(option,
				&res->data.extended_irq);
			break;
B
Bob Moore 已提交
478
		case ACPI_RESOURCE_TYPE_DMA:
L
Linus Torvalds 已提交
479 480
			pnpacpi_parse_dma_option(option, &res->data.dma);	
			break;
B
Bob Moore 已提交
481
		case ACPI_RESOURCE_TYPE_IO:
L
Linus Torvalds 已提交
482 483
			pnpacpi_parse_port_option(option, &res->data.io);
			break;
B
Bob Moore 已提交
484
		case ACPI_RESOURCE_TYPE_FIXED_IO:
L
Linus Torvalds 已提交
485 486 487
			pnpacpi_parse_fixed_port_option(option,
				&res->data.fixed_io);
			break;
B
Bob Moore 已提交
488
		case ACPI_RESOURCE_TYPE_MEMORY24:
L
Linus Torvalds 已提交
489 490
			pnpacpi_parse_mem24_option(option, &res->data.memory24);
			break;
B
Bob Moore 已提交
491
		case ACPI_RESOURCE_TYPE_MEMORY32:
L
Linus Torvalds 已提交
492 493
			pnpacpi_parse_mem32_option(option, &res->data.memory32);
			break;
B
Bob Moore 已提交
494
		case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
L
Linus Torvalds 已提交
495 496 497
			pnpacpi_parse_fixed_mem32_option(option,
				&res->data.fixed_memory32);
			break;
B
Bob Moore 已提交
498
		case ACPI_RESOURCE_TYPE_START_DEPENDENT:
L
Linus Torvalds 已提交
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
			switch (res->data.start_dpf.compatibility_priority) {
				case ACPI_GOOD_CONFIGURATION:
					priority = PNP_RES_PRIORITY_PREFERRED;
					break;
					
				case ACPI_ACCEPTABLE_CONFIGURATION:
					priority = PNP_RES_PRIORITY_ACCEPTABLE;
					break;

				case ACPI_SUB_OPTIMAL_CONFIGURATION:
					priority = PNP_RES_PRIORITY_FUNCTIONAL;
					break;
				default:
					priority = PNP_RES_PRIORITY_INVALID;
					break;
			}
			/* TBD: Considering performace/robustness bits */
			option = pnp_register_dependent_option(dev, priority);
			if (!option)
				return AE_ERROR;
			parse_data->option = option;	
			break;
B
Bob Moore 已提交
521
		case ACPI_RESOURCE_TYPE_END_DEPENDENT:
M
Matthieu Castet 已提交
522 523 524 525 526 527 528 529
			/*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;
			break;
L
Linus Torvalds 已提交
530
		default:
531
			pnp_warn("PnPACPI: unknown resource type %d", res->type);
L
Linus Torvalds 已提交
532 533 534 535 536 537
			return AE_ERROR;
	}
			
	return AE_OK;
}

B
Bob Moore 已提交
538
acpi_status pnpacpi_parse_resource_option_data(acpi_handle handle,
L
Linus Torvalds 已提交
539 540 541 542 543 544 545 546
	struct pnp_dev *dev)
{
	acpi_status status;
	struct acpipnp_parse_option_s parse_data;

	parse_data.option = pnp_register_independent_option(dev);
	if (!parse_data.option)
		return AE_ERROR;
M
Matthieu Castet 已提交
547
	parse_data.option_independent = parse_data.option;
L
Linus Torvalds 已提交
548
	parse_data.dev = dev;
B
Bob Moore 已提交
549
	status = acpi_walk_resources(handle, METHOD_NAME__PRS,
L
Linus Torvalds 已提交
550 551 552 553 554 555 556 557 558 559 560 561
		pnpacpi_option_resource, &parse_data);

	return status;
}

/*
 * Set resource
 */
static acpi_status pnpacpi_count_resources(struct acpi_resource *res,
	void *data)
{
	int *res_cnt = (int *)data;
562
	switch (res->type) {
B
Bob Moore 已提交
563 564 565 566 567 568 569 570
	case ACPI_RESOURCE_TYPE_IRQ:
	case ACPI_RESOURCE_TYPE_EXTENDED_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:
L
Linus Torvalds 已提交
571
#if 0
B
Bob Moore 已提交
572 573 574
	case ACPI_RESOURCE_TYPE_ADDRESS16:
	case ACPI_RESOURCE_TYPE_ADDRESS32:
	case ACPI_RESOURCE_TYPE_ADDRESS64:
L
Linus Torvalds 已提交
575 576 577 578 579 580 581 582 583 584 585 586
#endif
		(*res_cnt) ++;
	default:
		return AE_OK;
	}
	return AE_OK;
}

static acpi_status pnpacpi_type_resources(struct acpi_resource *res,
	void *data)
{
	struct acpi_resource **resource = (struct acpi_resource **)data;	
587
	switch (res->type) {
B
Bob Moore 已提交
588 589 590 591 592 593 594 595
	case ACPI_RESOURCE_TYPE_IRQ:
	case ACPI_RESOURCE_TYPE_EXTENDED_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:
L
Linus Torvalds 已提交
596
#if 0
B
Bob Moore 已提交
597 598 599
	case ACPI_RESOURCE_TYPE_ADDRESS16:
	case ACPI_RESOURCE_TYPE_ADDRESS32:
	case ACPI_RESOURCE_TYPE_ADDRESS64:
L
Linus Torvalds 已提交
600
#endif
601
		(*resource)->type = res->type;
L
Linus Torvalds 已提交
602 603 604 605 606 607 608 609
		(*resource)++;
	default:
		return AE_OK;
	}

	return AE_OK;
}

B
Bob Moore 已提交
610
int pnpacpi_build_resource_template(acpi_handle handle,
L
Linus Torvalds 已提交
611 612 613 614 615 616
	struct acpi_buffer *buffer)
{
	struct acpi_resource *resource;
	int res_cnt = 0;
	acpi_status status;

B
Bob Moore 已提交
617
	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
L
Linus Torvalds 已提交
618 619 620 621 622 623 624 625
		pnpacpi_count_resources, &res_cnt);
	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;
626
	buffer->pointer = kcalloc(1, buffer->length - 1, GFP_KERNEL);
L
Linus Torvalds 已提交
627 628 629 630
	if (!buffer->pointer)
		return -ENOMEM;
	pnp_dbg("Res cnt %d", res_cnt);
	resource = (struct acpi_resource *)buffer->pointer;
B
Bob Moore 已提交
631
	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
L
Linus Torvalds 已提交
632 633 634 635 636 637 638
		pnpacpi_type_resources, &resource);
	if (ACPI_FAILURE(status)) {
		kfree(buffer->pointer);
		pnp_err("Evaluate _CRS failed");
		return -EINVAL;
	}
	/* resource will pointer the end resource now */
B
Bob Moore 已提交
639
	resource->type = ACPI_RESOURCE_TYPE_END_TAG;
L
Linus Torvalds 已提交
640 641 642 643

	return 0;
}

B
Bob Moore 已提交
644
static void pnpacpi_encode_irq(struct acpi_resource *resource,
L
Linus Torvalds 已提交
645 646
	struct resource *p)
{
B
Bob Moore 已提交
647
	int triggering, polarity;
L
Linus Torvalds 已提交
648
	
B
Bob Moore 已提交
649 650 651
	decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering,
		&polarity);
	resource->type = ACPI_RESOURCE_TYPE_IRQ;
L
Linus Torvalds 已提交
652
	resource->length = sizeof(struct acpi_resource);
B
Bob Moore 已提交
653 654 655 656
	resource->data.irq.triggering = triggering;
	resource->data.irq.polarity = polarity;
	if (triggering == ACPI_EDGE_SENSITIVE)
		resource->data.irq.sharable = ACPI_EXCLUSIVE;
L
Linus Torvalds 已提交
657
	else
B
Bob Moore 已提交
658 659
		resource->data.irq.sharable = ACPI_SHARED;
	resource->data.irq.interrupt_count = 1;
L
Linus Torvalds 已提交
660 661 662 663 664 665
	resource->data.irq.interrupts[0] = p->start;
}

static void pnpacpi_encode_ext_irq(struct acpi_resource *resource,
	struct resource *p)
{
B
Bob Moore 已提交
666
	int triggering, polarity;
L
Linus Torvalds 已提交
667
	
B
Bob Moore 已提交
668 669 670
	decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering,
		&polarity);
	resource->type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
L
Linus Torvalds 已提交
671 672
	resource->length = sizeof(struct acpi_resource);
	resource->data.extended_irq.producer_consumer = ACPI_CONSUMER;
B
Bob Moore 已提交
673 674 675 676
	resource->data.extended_irq.triggering = triggering;
	resource->data.extended_irq.polarity = polarity;
	if (triggering == ACPI_EDGE_SENSITIVE)
		resource->data.irq.sharable = ACPI_EXCLUSIVE;
L
Linus Torvalds 已提交
677
	else
B
Bob Moore 已提交
678 679
		resource->data.irq.sharable = ACPI_SHARED;
	resource->data.extended_irq.interrupt_count = 1;
L
Linus Torvalds 已提交
680 681 682 683 684 685
	resource->data.extended_irq.interrupts[0] = p->start;
}

static void pnpacpi_encode_dma(struct acpi_resource *resource,
	struct resource *p)
{
B
Bob Moore 已提交
686
	resource->type = ACPI_RESOURCE_TYPE_DMA;
L
Linus Torvalds 已提交
687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703
	resource->length = sizeof(struct acpi_resource);
	/* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
	if (p->flags & IORESOURCE_DMA_COMPATIBLE)
		resource->data.dma.type = ACPI_COMPATIBILITY;
	else if (p->flags & IORESOURCE_DMA_TYPEA)
		resource->data.dma.type = ACPI_TYPE_A;
	else if (p->flags & IORESOURCE_DMA_TYPEB)
		resource->data.dma.type = ACPI_TYPE_B;
	else if (p->flags & IORESOURCE_DMA_TYPEF)
		resource->data.dma.type = ACPI_TYPE_F;
	if (p->flags & IORESOURCE_DMA_8BIT)
		resource->data.dma.transfer = ACPI_TRANSFER_8;
	else if (p->flags & IORESOURCE_DMA_8AND16BIT)
		resource->data.dma.transfer = ACPI_TRANSFER_8_16;
	else if (p->flags & IORESOURCE_DMA_16BIT)
		resource->data.dma.transfer = ACPI_TRANSFER_16;
	resource->data.dma.bus_master = p->flags & IORESOURCE_DMA_MASTER;
B
Bob Moore 已提交
704
	resource->data.dma.channel_count = 1;
L
Linus Torvalds 已提交
705 706 707 708 709 710
	resource->data.dma.channels[0] = p->start;
}

static void pnpacpi_encode_io(struct acpi_resource *resource,
	struct resource *p)
{
B
Bob Moore 已提交
711
	resource->type = ACPI_RESOURCE_TYPE_IO;
L
Linus Torvalds 已提交
712 713 714
	resource->length = sizeof(struct acpi_resource);
	/* Note: pnp_assign_port will copy pnp_port->flags into p->flags */
	resource->data.io.io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR)?
B
Bob Moore 已提交
715 716 717
		ACPI_DECODE_16 : ACPI_DECODE_10;
	resource->data.io.minimum = p->start;
	resource->data.io.maximum = p->end;
L
Linus Torvalds 已提交
718
	resource->data.io.alignment = 0; /* Correct? */
B
Bob Moore 已提交
719
	resource->data.io.address_length = p->end - p->start + 1;
L
Linus Torvalds 已提交
720 721 722 723 724
}

static void pnpacpi_encode_fixed_io(struct acpi_resource *resource,
	struct resource *p)
{
B
Bob Moore 已提交
725
	resource->type = ACPI_RESOURCE_TYPE_FIXED_IO;
L
Linus Torvalds 已提交
726
	resource->length = sizeof(struct acpi_resource);
B
Bob Moore 已提交
727 728
	resource->data.fixed_io.address = p->start;
	resource->data.fixed_io.address_length = p->end - p->start + 1;
L
Linus Torvalds 已提交
729 730 731 732 733
}

static void pnpacpi_encode_mem24(struct acpi_resource *resource,
	struct resource *p)
{
B
Bob Moore 已提交
734
	resource->type = ACPI_RESOURCE_TYPE_MEMORY24;
L
Linus Torvalds 已提交
735 736 737 738 739
	resource->length = sizeof(struct acpi_resource);
	/* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */
	resource->data.memory24.read_write_attribute =
		(p->flags & IORESOURCE_MEM_WRITEABLE) ?
		ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
B
Bob Moore 已提交
740 741
	resource->data.memory24.minimum = p->start;
	resource->data.memory24.maximum = p->end;
L
Linus Torvalds 已提交
742
	resource->data.memory24.alignment = 0;
B
Bob Moore 已提交
743
	resource->data.memory24.address_length = p->end - p->start + 1;
L
Linus Torvalds 已提交
744 745 746 747 748
}

static void pnpacpi_encode_mem32(struct acpi_resource *resource,
	struct resource *p)
{
B
Bob Moore 已提交
749
	resource->type = ACPI_RESOURCE_TYPE_MEMORY32;
L
Linus Torvalds 已提交
750 751 752 753
	resource->length = sizeof(struct acpi_resource);
	resource->data.memory32.read_write_attribute =
		(p->flags & IORESOURCE_MEM_WRITEABLE) ?
		ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
B
Bob Moore 已提交
754 755
	resource->data.memory32.minimum = p->start;
	resource->data.memory32.maximum = p->end;
L
Linus Torvalds 已提交
756
	resource->data.memory32.alignment = 0;
B
Bob Moore 已提交
757
	resource->data.memory32.address_length = p->end - p->start + 1;
L
Linus Torvalds 已提交
758 759 760 761 762
}

static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource,
	struct resource *p)
{
B
Bob Moore 已提交
763
	resource->type = ACPI_RESOURCE_TYPE_FIXED_MEMORY32;
L
Linus Torvalds 已提交
764 765 766 767
	resource->length = sizeof(struct acpi_resource);
	resource->data.fixed_memory32.read_write_attribute =
		(p->flags & IORESOURCE_MEM_WRITEABLE) ?
		ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
B
Bob Moore 已提交
768 769
	resource->data.fixed_memory32.address = p->start;
	resource->data.fixed_memory32.address_length = p->end - p->start + 1;
L
Linus Torvalds 已提交
770 771
}

B
Bob Moore 已提交
772
int pnpacpi_encode_resources(struct pnp_resource_table *res_table,
L
Linus Torvalds 已提交
773 774 775 776 777 778 779 780 781 782
	struct acpi_buffer *buffer)
{
	int i = 0;
	/* pnpacpi_build_resource_template allocates extra mem */
	int res_cnt = (buffer->length - 1)/sizeof(struct acpi_resource) - 1;
	struct acpi_resource *resource = (struct acpi_resource*)buffer->pointer;
	int port = 0, irq = 0, dma = 0, mem = 0;

	pnp_dbg("res cnt %d", res_cnt);
	while (i < res_cnt) {
783
		switch(resource->type) {
B
Bob Moore 已提交
784
		case ACPI_RESOURCE_TYPE_IRQ:
L
Linus Torvalds 已提交
785
			pnp_dbg("Encode irq");
B
Bob Moore 已提交
786
			pnpacpi_encode_irq(resource,
L
Linus Torvalds 已提交
787 788 789 790
				&res_table->irq_resource[irq]);
			irq++;
			break;

B
Bob Moore 已提交
791
		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
L
Linus Torvalds 已提交
792
			pnp_dbg("Encode ext irq");
B
Bob Moore 已提交
793
			pnpacpi_encode_ext_irq(resource,
L
Linus Torvalds 已提交
794 795 796
				&res_table->irq_resource[irq]);
			irq++;
			break;
B
Bob Moore 已提交
797
		case ACPI_RESOURCE_TYPE_DMA:
L
Linus Torvalds 已提交
798
			pnp_dbg("Encode dma");
B
Bob Moore 已提交
799
			pnpacpi_encode_dma(resource,
L
Linus Torvalds 已提交
800 801 802
				&res_table->dma_resource[dma]);
			dma ++;
			break;
B
Bob Moore 已提交
803
		case ACPI_RESOURCE_TYPE_IO:
L
Linus Torvalds 已提交
804
			pnp_dbg("Encode io");
B
Bob Moore 已提交
805
			pnpacpi_encode_io(resource,
L
Linus Torvalds 已提交
806 807 808
				&res_table->port_resource[port]);
			port ++;
			break;
B
Bob Moore 已提交
809
		case ACPI_RESOURCE_TYPE_FIXED_IO:
L
Linus Torvalds 已提交
810 811 812 813 814
			pnp_dbg("Encode fixed io");
			pnpacpi_encode_fixed_io(resource,
				&res_table->port_resource[port]);
			port ++;
			break;
B
Bob Moore 已提交
815
		case ACPI_RESOURCE_TYPE_MEMORY24:
L
Linus Torvalds 已提交
816 817 818 819 820
			pnp_dbg("Encode mem24");
			pnpacpi_encode_mem24(resource,
				&res_table->mem_resource[mem]);
			mem ++;
			break;
B
Bob Moore 已提交
821
		case ACPI_RESOURCE_TYPE_MEMORY32:
L
Linus Torvalds 已提交
822 823 824 825 826
			pnp_dbg("Encode mem32");
			pnpacpi_encode_mem32(resource,
				&res_table->mem_resource[mem]);
			mem ++;
			break;
B
Bob Moore 已提交
827
		case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
L
Linus Torvalds 已提交
828 829 830 831 832 833
			pnp_dbg("Encode fixed mem32");
			pnpacpi_encode_fixed_mem32(resource,
				&res_table->mem_resource[mem]);
			mem ++;
			break;
		default: /* other type */
834
			pnp_warn("unknown resource type %d", resource->type);
L
Linus Torvalds 已提交
835 836 837 838 839 840 841
			return -EINVAL;
		}
		resource ++;
		i ++;
	}
	return 0;
}