xref: /linux/drivers/pnp/pnpacpi/rsparser.c (revision 2b8232ce512105e28453f301d1510de8363bccd1)
1 /*
2  * pnpacpi -- PnP ACPI driver
3  *
4  * Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr>
5  * Copyright (c) 2004 Li Shaohua <shaohua.li@intel.com>
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the
9  * Free Software Foundation; either version 2, or (at your option) any
10  * later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 #include <linux/kernel.h>
22 #include <linux/acpi.h>
23 #include <linux/pci.h>
24 #include "pnpacpi.h"
25 
26 #ifdef CONFIG_IA64
27 #define valid_IRQ(i) (1)
28 #else
29 #define valid_IRQ(i) (((i) != 0) && ((i) != 2))
30 #endif
31 
32 /*
33  * Allocated Resources
34  */
35 static int irq_flags(int triggering, int polarity)
36 {
37 	if (triggering == ACPI_LEVEL_SENSITIVE) {
38 		if (polarity == ACPI_ACTIVE_LOW)
39 			return IORESOURCE_IRQ_LOWLEVEL;
40 		else
41 			return IORESOURCE_IRQ_HIGHLEVEL;
42 	} else {
43 		if (polarity == ACPI_ACTIVE_LOW)
44 			return IORESOURCE_IRQ_LOWEDGE;
45 		else
46 			return IORESOURCE_IRQ_HIGHEDGE;
47 	}
48 }
49 
50 static void decode_irq_flags(int flag, int *triggering, int *polarity)
51 {
52 	switch (flag) {
53 	case IORESOURCE_IRQ_LOWLEVEL:
54 		*triggering = ACPI_LEVEL_SENSITIVE;
55 		*polarity = ACPI_ACTIVE_LOW;
56 		break;
57 	case IORESOURCE_IRQ_HIGHLEVEL:
58 		*triggering = ACPI_LEVEL_SENSITIVE;
59 		*polarity = ACPI_ACTIVE_HIGH;
60 		break;
61 	case IORESOURCE_IRQ_LOWEDGE:
62 		*triggering = ACPI_EDGE_SENSITIVE;
63 		*polarity = ACPI_ACTIVE_LOW;
64 		break;
65 	case IORESOURCE_IRQ_HIGHEDGE:
66 		*triggering = ACPI_EDGE_SENSITIVE;
67 		*polarity = ACPI_ACTIVE_HIGH;
68 		break;
69 	}
70 }
71 
72 static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res,
73 						u32 gsi, int triggering,
74 						int polarity, int shareable)
75 {
76 	int i = 0;
77 	int irq;
78 
79 	if (!valid_IRQ(gsi))
80 		return;
81 
82 	while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) &&
83 	       i < PNP_MAX_IRQ)
84 		i++;
85 	if (i >= PNP_MAX_IRQ)
86 		return;
87 
88 	res->irq_resource[i].flags = IORESOURCE_IRQ;	// Also clears _UNSET flag
89 	res->irq_resource[i].flags |= irq_flags(triggering, polarity);
90 	irq = acpi_register_gsi(gsi, triggering, polarity);
91 	if (irq < 0) {
92 		res->irq_resource[i].flags |= IORESOURCE_DISABLED;
93 		return;
94 	}
95 
96 	if (shareable)
97 		res->irq_resource[i].flags |= IORESOURCE_IRQ_SHAREABLE;
98 
99 	res->irq_resource[i].start = irq;
100 	res->irq_resource[i].end = irq;
101 	pcibios_penalize_isa_irq(irq, 1);
102 }
103 
104 static int dma_flags(int type, int bus_master, int transfer)
105 {
106 	int flags = 0;
107 
108 	if (bus_master)
109 		flags |= IORESOURCE_DMA_MASTER;
110 	switch (type) {
111 	case ACPI_COMPATIBILITY:
112 		flags |= IORESOURCE_DMA_COMPATIBLE;
113 		break;
114 	case ACPI_TYPE_A:
115 		flags |= IORESOURCE_DMA_TYPEA;
116 		break;
117 	case ACPI_TYPE_B:
118 		flags |= IORESOURCE_DMA_TYPEB;
119 		break;
120 	case ACPI_TYPE_F:
121 		flags |= IORESOURCE_DMA_TYPEF;
122 		break;
123 	default:
124 		/* Set a default value ? */
125 		flags |= IORESOURCE_DMA_COMPATIBLE;
126 		pnp_err("Invalid DMA type");
127 	}
128 	switch (transfer) {
129 	case ACPI_TRANSFER_8:
130 		flags |= IORESOURCE_DMA_8BIT;
131 		break;
132 	case ACPI_TRANSFER_8_16:
133 		flags |= IORESOURCE_DMA_8AND16BIT;
134 		break;
135 	case ACPI_TRANSFER_16:
136 		flags |= IORESOURCE_DMA_16BIT;
137 		break;
138 	default:
139 		/* Set a default value ? */
140 		flags |= IORESOURCE_DMA_8AND16BIT;
141 		pnp_err("Invalid DMA transfer type");
142 	}
143 
144 	return flags;
145 }
146 
147 static void pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res,
148 						u32 dma, int type,
149 						int bus_master, int transfer)
150 {
151 	int i = 0;
152 
153 	while (i < PNP_MAX_DMA &&
154 	       !(res->dma_resource[i].flags & IORESOURCE_UNSET))
155 		i++;
156 	if (i < PNP_MAX_DMA) {
157 		res->dma_resource[i].flags = IORESOURCE_DMA;	// Also clears _UNSET flag
158 		res->dma_resource[i].flags |=
159 		    dma_flags(type, bus_master, transfer);
160 		if (dma == -1) {
161 			res->dma_resource[i].flags |= IORESOURCE_DISABLED;
162 			return;
163 		}
164 		res->dma_resource[i].start = dma;
165 		res->dma_resource[i].end = dma;
166 	}
167 }
168 
169 static void pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res,
170 					       u64 io, u64 len, int io_decode)
171 {
172 	int i = 0;
173 
174 	while (!(res->port_resource[i].flags & IORESOURCE_UNSET) &&
175 	       i < PNP_MAX_PORT)
176 		i++;
177 	if (i < PNP_MAX_PORT) {
178 		res->port_resource[i].flags = IORESOURCE_IO;	// Also clears _UNSET flag
179 		if (io_decode == ACPI_DECODE_16)
180 			res->port_resource[i].flags |= PNP_PORT_FLAG_16BITADDR;
181 		if (len <= 0 || (io + len - 1) >= 0x10003) {
182 			res->port_resource[i].flags |= IORESOURCE_DISABLED;
183 			return;
184 		}
185 		res->port_resource[i].start = io;
186 		res->port_resource[i].end = io + len - 1;
187 	}
188 }
189 
190 static void pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res,
191 						u64 mem, u64 len,
192 						int write_protect)
193 {
194 	int i = 0;
195 
196 	while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) &&
197 	       (i < PNP_MAX_MEM))
198 		i++;
199 	if (i < PNP_MAX_MEM) {
200 		res->mem_resource[i].flags = IORESOURCE_MEM;	// Also clears _UNSET flag
201 		if (len <= 0) {
202 			res->mem_resource[i].flags |= IORESOURCE_DISABLED;
203 			return;
204 		}
205 		if (write_protect == ACPI_READ_WRITE_MEMORY)
206 			res->mem_resource[i].flags |= IORESOURCE_MEM_WRITEABLE;
207 
208 		res->mem_resource[i].start = mem;
209 		res->mem_resource[i].end = mem + len - 1;
210 	}
211 }
212 
213 static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table,
214 						  struct acpi_resource *res)
215 {
216 	struct acpi_resource_address64 addr, *p = &addr;
217 	acpi_status status;
218 
219 	status = acpi_resource_to_address64(res, p);
220 	if (!ACPI_SUCCESS(status)) {
221 		pnp_warn("PnPACPI: failed to convert resource type %d",
222 			 res->type);
223 		return;
224 	}
225 
226 	if (p->producer_consumer == ACPI_PRODUCER)
227 		return;
228 
229 	if (p->resource_type == ACPI_MEMORY_RANGE)
230 		pnpacpi_parse_allocated_memresource(res_table,
231 			p->minimum, p->address_length,
232 			p->info.mem.write_protect);
233 	else if (p->resource_type == ACPI_IO_RANGE)
234 		pnpacpi_parse_allocated_ioresource(res_table,
235 			p->minimum, p->address_length,
236 			p->granularity == 0xfff ? ACPI_DECODE_10 :
237 				ACPI_DECODE_16);
238 }
239 
240 static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
241 					      void *data)
242 {
243 	struct pnp_resource_table *res_table = data;
244 	int i;
245 
246 	switch (res->type) {
247 	case ACPI_RESOURCE_TYPE_IRQ:
248 		/*
249 		 * Per spec, only one interrupt per descriptor is allowed in
250 		 * _CRS, but some firmware violates this, so parse them all.
251 		 */
252 		for (i = 0; i < res->data.irq.interrupt_count; i++) {
253 			pnpacpi_parse_allocated_irqresource(res_table,
254 				res->data.irq.interrupts[i],
255 				res->data.irq.triggering,
256 				res->data.irq.polarity,
257 				res->data.irq.sharable);
258 		}
259 		break;
260 
261 	case ACPI_RESOURCE_TYPE_DMA:
262 		if (res->data.dma.channel_count > 0)
263 			pnpacpi_parse_allocated_dmaresource(res_table,
264 				res->data.dma.channels[0],
265 				res->data.dma.type,
266 				res->data.dma.bus_master,
267 				res->data.dma.transfer);
268 		break;
269 
270 	case ACPI_RESOURCE_TYPE_IO:
271 		pnpacpi_parse_allocated_ioresource(res_table,
272 			res->data.io.minimum,
273 			res->data.io.address_length,
274 			res->data.io.io_decode);
275 		break;
276 
277 	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
278 	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
279 		break;
280 
281 	case ACPI_RESOURCE_TYPE_FIXED_IO:
282 		pnpacpi_parse_allocated_ioresource(res_table,
283 			res->data.fixed_io.address,
284 			res->data.fixed_io.address_length,
285 			ACPI_DECODE_10);
286 		break;
287 
288 	case ACPI_RESOURCE_TYPE_VENDOR:
289 		break;
290 
291 	case ACPI_RESOURCE_TYPE_END_TAG:
292 		break;
293 
294 	case ACPI_RESOURCE_TYPE_MEMORY24:
295 		pnpacpi_parse_allocated_memresource(res_table,
296 			res->data.memory24.minimum,
297 			res->data.memory24.address_length,
298 			res->data.memory24.write_protect);
299 		break;
300 	case ACPI_RESOURCE_TYPE_MEMORY32:
301 		pnpacpi_parse_allocated_memresource(res_table,
302 			res->data.memory32.minimum,
303 			res->data.memory32.address_length,
304 			res->data.memory32.write_protect);
305 		break;
306 	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
307 		pnpacpi_parse_allocated_memresource(res_table,
308 			res->data.fixed_memory32.address,
309 			res->data.fixed_memory32.address_length,
310 			res->data.fixed_memory32.write_protect);
311 		break;
312 	case ACPI_RESOURCE_TYPE_ADDRESS16:
313 	case ACPI_RESOURCE_TYPE_ADDRESS32:
314 	case ACPI_RESOURCE_TYPE_ADDRESS64:
315 		pnpacpi_parse_allocated_address_space(res_table, res);
316 		break;
317 
318 	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
319 		if (res->data.ext_address64.producer_consumer == ACPI_PRODUCER)
320 			return AE_OK;
321 		break;
322 
323 	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
324 		if (res->data.extended_irq.producer_consumer == ACPI_PRODUCER)
325 			return AE_OK;
326 
327 		for (i = 0; i < res->data.extended_irq.interrupt_count; i++) {
328 			pnpacpi_parse_allocated_irqresource(res_table,
329 				res->data.extended_irq.interrupts[i],
330 				res->data.extended_irq.triggering,
331 				res->data.extended_irq.polarity,
332 				res->data.extended_irq.sharable);
333 		}
334 		break;
335 
336 	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
337 		break;
338 
339 	default:
340 		pnp_warn("PnPACPI: unknown resource type %d", res->type);
341 		return AE_ERROR;
342 	}
343 
344 	return AE_OK;
345 }
346 
347 acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle,
348 					     struct pnp_resource_table * res)
349 {
350 	/* Blank the resource table values */
351 	pnp_init_resource_table(res);
352 
353 	return acpi_walk_resources(handle, METHOD_NAME__CRS,
354 				   pnpacpi_allocated_resource, res);
355 }
356 
357 static void pnpacpi_parse_dma_option(struct pnp_option *option,
358 				     struct acpi_resource_dma *p)
359 {
360 	int i;
361 	struct pnp_dma *dma;
362 
363 	if (p->channel_count == 0)
364 		return;
365 	dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
366 	if (!dma)
367 		return;
368 
369 	for (i = 0; i < p->channel_count; i++)
370 		dma->map |= 1 << p->channels[i];
371 
372 	dma->flags = dma_flags(p->type, p->bus_master, p->transfer);
373 
374 	pnp_register_dma_resource(option, dma);
375 }
376 
377 static void pnpacpi_parse_irq_option(struct pnp_option *option,
378 				     struct acpi_resource_irq *p)
379 {
380 	int i;
381 	struct pnp_irq *irq;
382 
383 	if (p->interrupt_count == 0)
384 		return;
385 	irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
386 	if (!irq)
387 		return;
388 
389 	for (i = 0; i < p->interrupt_count; i++)
390 		if (p->interrupts[i])
391 			__set_bit(p->interrupts[i], irq->map);
392 	irq->flags = irq_flags(p->triggering, p->polarity);
393 
394 	pnp_register_irq_resource(option, irq);
395 }
396 
397 static void pnpacpi_parse_ext_irq_option(struct pnp_option *option,
398 					 struct acpi_resource_extended_irq *p)
399 {
400 	int i;
401 	struct pnp_irq *irq;
402 
403 	if (p->interrupt_count == 0)
404 		return;
405 	irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
406 	if (!irq)
407 		return;
408 
409 	for (i = 0; i < p->interrupt_count; i++)
410 		if (p->interrupts[i])
411 			__set_bit(p->interrupts[i], irq->map);
412 	irq->flags = irq_flags(p->triggering, p->polarity);
413 
414 	pnp_register_irq_resource(option, irq);
415 }
416 
417 static void pnpacpi_parse_port_option(struct pnp_option *option,
418 				      struct acpi_resource_io *io)
419 {
420 	struct pnp_port *port;
421 
422 	if (io->address_length == 0)
423 		return;
424 	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
425 	if (!port)
426 		return;
427 	port->min = io->minimum;
428 	port->max = io->maximum;
429 	port->align = io->alignment;
430 	port->size = io->address_length;
431 	port->flags = ACPI_DECODE_16 == io->io_decode ?
432 	    PNP_PORT_FLAG_16BITADDR : 0;
433 	pnp_register_port_resource(option, port);
434 }
435 
436 static void pnpacpi_parse_fixed_port_option(struct pnp_option *option,
437 					    struct acpi_resource_fixed_io *io)
438 {
439 	struct pnp_port *port;
440 
441 	if (io->address_length == 0)
442 		return;
443 	port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
444 	if (!port)
445 		return;
446 	port->min = port->max = io->address;
447 	port->size = io->address_length;
448 	port->align = 0;
449 	port->flags = PNP_PORT_FLAG_FIXED;
450 	pnp_register_port_resource(option, port);
451 }
452 
453 static void pnpacpi_parse_mem24_option(struct pnp_option *option,
454 				       struct acpi_resource_memory24 *p)
455 {
456 	struct pnp_mem *mem;
457 
458 	if (p->address_length == 0)
459 		return;
460 	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
461 	if (!mem)
462 		return;
463 	mem->min = p->minimum;
464 	mem->max = p->maximum;
465 	mem->align = p->alignment;
466 	mem->size = p->address_length;
467 
468 	mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
469 	    IORESOURCE_MEM_WRITEABLE : 0;
470 
471 	pnp_register_mem_resource(option, mem);
472 }
473 
474 static void pnpacpi_parse_mem32_option(struct pnp_option *option,
475 				       struct acpi_resource_memory32 *p)
476 {
477 	struct pnp_mem *mem;
478 
479 	if (p->address_length == 0)
480 		return;
481 	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
482 	if (!mem)
483 		return;
484 	mem->min = p->minimum;
485 	mem->max = p->maximum;
486 	mem->align = p->alignment;
487 	mem->size = p->address_length;
488 
489 	mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
490 	    IORESOURCE_MEM_WRITEABLE : 0;
491 
492 	pnp_register_mem_resource(option, mem);
493 }
494 
495 static void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option,
496 					 struct acpi_resource_fixed_memory32 *p)
497 {
498 	struct pnp_mem *mem;
499 
500 	if (p->address_length == 0)
501 		return;
502 	mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
503 	if (!mem)
504 		return;
505 	mem->min = mem->max = p->address;
506 	mem->size = p->address_length;
507 	mem->align = 0;
508 
509 	mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
510 	    IORESOURCE_MEM_WRITEABLE : 0;
511 
512 	pnp_register_mem_resource(option, mem);
513 }
514 
515 static void pnpacpi_parse_address_option(struct pnp_option *option,
516 					 struct acpi_resource *r)
517 {
518 	struct acpi_resource_address64 addr, *p = &addr;
519 	acpi_status status;
520 	struct pnp_mem *mem;
521 	struct pnp_port *port;
522 
523 	status = acpi_resource_to_address64(r, p);
524 	if (!ACPI_SUCCESS(status)) {
525 		pnp_warn("PnPACPI: failed to convert resource type %d",
526 			 r->type);
527 		return;
528 	}
529 
530 	if (p->address_length == 0)
531 		return;
532 
533 	if (p->resource_type == ACPI_MEMORY_RANGE) {
534 		mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
535 		if (!mem)
536 			return;
537 		mem->min = mem->max = p->minimum;
538 		mem->size = p->address_length;
539 		mem->align = 0;
540 		mem->flags = (p->info.mem.write_protect ==
541 			      ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE
542 		    : 0;
543 		pnp_register_mem_resource(option, mem);
544 	} else if (p->resource_type == ACPI_IO_RANGE) {
545 		port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
546 		if (!port)
547 			return;
548 		port->min = port->max = p->minimum;
549 		port->size = p->address_length;
550 		port->align = 0;
551 		port->flags = PNP_PORT_FLAG_FIXED;
552 		pnp_register_port_resource(option, port);
553 	}
554 }
555 
556 struct acpipnp_parse_option_s {
557 	struct pnp_option *option;
558 	struct pnp_option *option_independent;
559 	struct pnp_dev *dev;
560 };
561 
562 static acpi_status pnpacpi_option_resource(struct acpi_resource *res,
563 					   void *data)
564 {
565 	int priority = 0;
566 	struct acpipnp_parse_option_s *parse_data = data;
567 	struct pnp_dev *dev = parse_data->dev;
568 	struct pnp_option *option = parse_data->option;
569 
570 	switch (res->type) {
571 	case ACPI_RESOURCE_TYPE_IRQ:
572 		pnpacpi_parse_irq_option(option, &res->data.irq);
573 		break;
574 
575 	case ACPI_RESOURCE_TYPE_DMA:
576 		pnpacpi_parse_dma_option(option, &res->data.dma);
577 		break;
578 
579 	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
580 		switch (res->data.start_dpf.compatibility_priority) {
581 		case ACPI_GOOD_CONFIGURATION:
582 			priority = PNP_RES_PRIORITY_PREFERRED;
583 			break;
584 
585 		case ACPI_ACCEPTABLE_CONFIGURATION:
586 			priority = PNP_RES_PRIORITY_ACCEPTABLE;
587 			break;
588 
589 		case ACPI_SUB_OPTIMAL_CONFIGURATION:
590 			priority = PNP_RES_PRIORITY_FUNCTIONAL;
591 			break;
592 		default:
593 			priority = PNP_RES_PRIORITY_INVALID;
594 			break;
595 		}
596 		/* TBD: Consider performance/robustness bits */
597 		option = pnp_register_dependent_option(dev, priority);
598 		if (!option)
599 			return AE_ERROR;
600 		parse_data->option = option;
601 		break;
602 
603 	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
604 		/*only one EndDependentFn is allowed */
605 		if (!parse_data->option_independent) {
606 			pnp_warn("PnPACPI: more than one EndDependentFn");
607 			return AE_ERROR;
608 		}
609 		parse_data->option = parse_data->option_independent;
610 		parse_data->option_independent = NULL;
611 		break;
612 
613 	case ACPI_RESOURCE_TYPE_IO:
614 		pnpacpi_parse_port_option(option, &res->data.io);
615 		break;
616 
617 	case ACPI_RESOURCE_TYPE_FIXED_IO:
618 		pnpacpi_parse_fixed_port_option(option, &res->data.fixed_io);
619 		break;
620 
621 	case ACPI_RESOURCE_TYPE_VENDOR:
622 	case ACPI_RESOURCE_TYPE_END_TAG:
623 		break;
624 
625 	case ACPI_RESOURCE_TYPE_MEMORY24:
626 		pnpacpi_parse_mem24_option(option, &res->data.memory24);
627 		break;
628 
629 	case ACPI_RESOURCE_TYPE_MEMORY32:
630 		pnpacpi_parse_mem32_option(option, &res->data.memory32);
631 		break;
632 
633 	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
634 		pnpacpi_parse_fixed_mem32_option(option,
635 						 &res->data.fixed_memory32);
636 		break;
637 
638 	case ACPI_RESOURCE_TYPE_ADDRESS16:
639 	case ACPI_RESOURCE_TYPE_ADDRESS32:
640 	case ACPI_RESOURCE_TYPE_ADDRESS64:
641 		pnpacpi_parse_address_option(option, res);
642 		break;
643 
644 	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
645 		break;
646 
647 	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
648 		pnpacpi_parse_ext_irq_option(option, &res->data.extended_irq);
649 		break;
650 
651 	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
652 		break;
653 
654 	default:
655 		pnp_warn("PnPACPI: unknown resource type %d", res->type);
656 		return AE_ERROR;
657 	}
658 
659 	return AE_OK;
660 }
661 
662 acpi_status pnpacpi_parse_resource_option_data(acpi_handle handle,
663 					       struct pnp_dev * dev)
664 {
665 	acpi_status status;
666 	struct acpipnp_parse_option_s parse_data;
667 
668 	parse_data.option = pnp_register_independent_option(dev);
669 	if (!parse_data.option)
670 		return AE_ERROR;
671 	parse_data.option_independent = parse_data.option;
672 	parse_data.dev = dev;
673 	status = acpi_walk_resources(handle, METHOD_NAME__PRS,
674 				     pnpacpi_option_resource, &parse_data);
675 
676 	return status;
677 }
678 
679 static int pnpacpi_supported_resource(struct acpi_resource *res)
680 {
681 	switch (res->type) {
682 	case ACPI_RESOURCE_TYPE_IRQ:
683 	case ACPI_RESOURCE_TYPE_DMA:
684 	case ACPI_RESOURCE_TYPE_IO:
685 	case ACPI_RESOURCE_TYPE_FIXED_IO:
686 	case ACPI_RESOURCE_TYPE_MEMORY24:
687 	case ACPI_RESOURCE_TYPE_MEMORY32:
688 	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
689 	case ACPI_RESOURCE_TYPE_ADDRESS16:
690 	case ACPI_RESOURCE_TYPE_ADDRESS32:
691 	case ACPI_RESOURCE_TYPE_ADDRESS64:
692 	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
693 		return 1;
694 	}
695 	return 0;
696 }
697 
698 /*
699  * Set resource
700  */
701 static acpi_status pnpacpi_count_resources(struct acpi_resource *res,
702 					   void *data)
703 {
704 	int *res_cnt = data;
705 
706 	if (pnpacpi_supported_resource(res))
707 		(*res_cnt)++;
708 	return AE_OK;
709 }
710 
711 static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data)
712 {
713 	struct acpi_resource **resource = data;
714 
715 	if (pnpacpi_supported_resource(res)) {
716 		(*resource)->type = res->type;
717 		(*resource)->length = sizeof(struct acpi_resource);
718 		(*resource)++;
719 	}
720 
721 	return AE_OK;
722 }
723 
724 int pnpacpi_build_resource_template(acpi_handle handle,
725 				    struct acpi_buffer *buffer)
726 {
727 	struct acpi_resource *resource;
728 	int res_cnt = 0;
729 	acpi_status status;
730 
731 	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
732 				     pnpacpi_count_resources, &res_cnt);
733 	if (ACPI_FAILURE(status)) {
734 		pnp_err("Evaluate _CRS failed");
735 		return -EINVAL;
736 	}
737 	if (!res_cnt)
738 		return -EINVAL;
739 	buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1;
740 	buffer->pointer = kzalloc(buffer->length - 1, GFP_KERNEL);
741 	if (!buffer->pointer)
742 		return -ENOMEM;
743 	pnp_dbg("Res cnt %d", res_cnt);
744 	resource = (struct acpi_resource *)buffer->pointer;
745 	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
746 				     pnpacpi_type_resources, &resource);
747 	if (ACPI_FAILURE(status)) {
748 		kfree(buffer->pointer);
749 		pnp_err("Evaluate _CRS failed");
750 		return -EINVAL;
751 	}
752 	/* resource will pointer the end resource now */
753 	resource->type = ACPI_RESOURCE_TYPE_END_TAG;
754 
755 	return 0;
756 }
757 
758 static void pnpacpi_encode_irq(struct acpi_resource *resource,
759 			       struct resource *p)
760 {
761 	int triggering, polarity;
762 
763 	decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
764 	resource->data.irq.triggering = triggering;
765 	resource->data.irq.polarity = polarity;
766 	if (triggering == ACPI_EDGE_SENSITIVE)
767 		resource->data.irq.sharable = ACPI_EXCLUSIVE;
768 	else
769 		resource->data.irq.sharable = ACPI_SHARED;
770 	resource->data.irq.interrupt_count = 1;
771 	resource->data.irq.interrupts[0] = p->start;
772 }
773 
774 static void pnpacpi_encode_ext_irq(struct acpi_resource *resource,
775 				   struct resource *p)
776 {
777 	int triggering, polarity;
778 
779 	decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
780 	resource->data.extended_irq.producer_consumer = ACPI_CONSUMER;
781 	resource->data.extended_irq.triggering = triggering;
782 	resource->data.extended_irq.polarity = polarity;
783 	if (triggering == ACPI_EDGE_SENSITIVE)
784 		resource->data.irq.sharable = ACPI_EXCLUSIVE;
785 	else
786 		resource->data.irq.sharable = ACPI_SHARED;
787 	resource->data.extended_irq.interrupt_count = 1;
788 	resource->data.extended_irq.interrupts[0] = p->start;
789 }
790 
791 static void pnpacpi_encode_dma(struct acpi_resource *resource,
792 			       struct resource *p)
793 {
794 	/* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
795 	switch (p->flags & IORESOURCE_DMA_SPEED_MASK) {
796 	case IORESOURCE_DMA_TYPEA:
797 		resource->data.dma.type = ACPI_TYPE_A;
798 		break;
799 	case IORESOURCE_DMA_TYPEB:
800 		resource->data.dma.type = ACPI_TYPE_B;
801 		break;
802 	case IORESOURCE_DMA_TYPEF:
803 		resource->data.dma.type = ACPI_TYPE_F;
804 		break;
805 	default:
806 		resource->data.dma.type = ACPI_COMPATIBILITY;
807 	}
808 
809 	switch (p->flags & IORESOURCE_DMA_TYPE_MASK) {
810 	case IORESOURCE_DMA_8BIT:
811 		resource->data.dma.transfer = ACPI_TRANSFER_8;
812 		break;
813 	case IORESOURCE_DMA_8AND16BIT:
814 		resource->data.dma.transfer = ACPI_TRANSFER_8_16;
815 		break;
816 	default:
817 		resource->data.dma.transfer = ACPI_TRANSFER_16;
818 	}
819 
820 	resource->data.dma.bus_master = !!(p->flags & IORESOURCE_DMA_MASTER);
821 	resource->data.dma.channel_count = 1;
822 	resource->data.dma.channels[0] = p->start;
823 }
824 
825 static void pnpacpi_encode_io(struct acpi_resource *resource,
826 			      struct resource *p)
827 {
828 	/* Note: pnp_assign_port will copy pnp_port->flags into p->flags */
829 	resource->data.io.io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ?
830 	    ACPI_DECODE_16 : ACPI_DECODE_10;
831 	resource->data.io.minimum = p->start;
832 	resource->data.io.maximum = p->end;
833 	resource->data.io.alignment = 0;	/* Correct? */
834 	resource->data.io.address_length = p->end - p->start + 1;
835 }
836 
837 static void pnpacpi_encode_fixed_io(struct acpi_resource *resource,
838 				    struct resource *p)
839 {
840 	resource->data.fixed_io.address = p->start;
841 	resource->data.fixed_io.address_length = p->end - p->start + 1;
842 }
843 
844 static void pnpacpi_encode_mem24(struct acpi_resource *resource,
845 				 struct resource *p)
846 {
847 	/* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */
848 	resource->data.memory24.write_protect =
849 	    (p->flags & IORESOURCE_MEM_WRITEABLE) ?
850 	    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
851 	resource->data.memory24.minimum = p->start;
852 	resource->data.memory24.maximum = p->end;
853 	resource->data.memory24.alignment = 0;
854 	resource->data.memory24.address_length = p->end - p->start + 1;
855 }
856 
857 static void pnpacpi_encode_mem32(struct acpi_resource *resource,
858 				 struct resource *p)
859 {
860 	resource->data.memory32.write_protect =
861 	    (p->flags & IORESOURCE_MEM_WRITEABLE) ?
862 	    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
863 	resource->data.memory32.minimum = p->start;
864 	resource->data.memory32.maximum = p->end;
865 	resource->data.memory32.alignment = 0;
866 	resource->data.memory32.address_length = p->end - p->start + 1;
867 }
868 
869 static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource,
870 				       struct resource *p)
871 {
872 	resource->data.fixed_memory32.write_protect =
873 	    (p->flags & IORESOURCE_MEM_WRITEABLE) ?
874 	    ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
875 	resource->data.fixed_memory32.address = p->start;
876 	resource->data.fixed_memory32.address_length = p->end - p->start + 1;
877 }
878 
879 int pnpacpi_encode_resources(struct pnp_resource_table *res_table,
880 			     struct acpi_buffer *buffer)
881 {
882 	int i = 0;
883 	/* pnpacpi_build_resource_template allocates extra mem */
884 	int res_cnt = (buffer->length - 1) / sizeof(struct acpi_resource) - 1;
885 	struct acpi_resource *resource = buffer->pointer;
886 	int port = 0, irq = 0, dma = 0, mem = 0;
887 
888 	pnp_dbg("res cnt %d", res_cnt);
889 	while (i < res_cnt) {
890 		switch (resource->type) {
891 		case ACPI_RESOURCE_TYPE_IRQ:
892 			pnp_dbg("Encode irq");
893 			pnpacpi_encode_irq(resource,
894 					   &res_table->irq_resource[irq]);
895 			irq++;
896 			break;
897 
898 		case ACPI_RESOURCE_TYPE_DMA:
899 			pnp_dbg("Encode dma");
900 			pnpacpi_encode_dma(resource,
901 					   &res_table->dma_resource[dma]);
902 			dma++;
903 			break;
904 		case ACPI_RESOURCE_TYPE_IO:
905 			pnp_dbg("Encode io");
906 			pnpacpi_encode_io(resource,
907 					  &res_table->port_resource[port]);
908 			port++;
909 			break;
910 		case ACPI_RESOURCE_TYPE_FIXED_IO:
911 			pnp_dbg("Encode fixed io");
912 			pnpacpi_encode_fixed_io(resource,
913 						&res_table->
914 						port_resource[port]);
915 			port++;
916 			break;
917 		case ACPI_RESOURCE_TYPE_MEMORY24:
918 			pnp_dbg("Encode mem24");
919 			pnpacpi_encode_mem24(resource,
920 					     &res_table->mem_resource[mem]);
921 			mem++;
922 			break;
923 		case ACPI_RESOURCE_TYPE_MEMORY32:
924 			pnp_dbg("Encode mem32");
925 			pnpacpi_encode_mem32(resource,
926 					     &res_table->mem_resource[mem]);
927 			mem++;
928 			break;
929 		case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
930 			pnp_dbg("Encode fixed mem32");
931 			pnpacpi_encode_fixed_mem32(resource,
932 						   &res_table->
933 						   mem_resource[mem]);
934 			mem++;
935 			break;
936 		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
937 			pnp_dbg("Encode ext irq");
938 			pnpacpi_encode_ext_irq(resource,
939 					       &res_table->irq_resource[irq]);
940 			irq++;
941 			break;
942 		case ACPI_RESOURCE_TYPE_START_DEPENDENT:
943 		case ACPI_RESOURCE_TYPE_END_DEPENDENT:
944 		case ACPI_RESOURCE_TYPE_VENDOR:
945 		case ACPI_RESOURCE_TYPE_END_TAG:
946 		case ACPI_RESOURCE_TYPE_ADDRESS16:
947 		case ACPI_RESOURCE_TYPE_ADDRESS32:
948 		case ACPI_RESOURCE_TYPE_ADDRESS64:
949 		case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
950 		case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
951 		default:	/* other type */
952 			pnp_warn("unknown resource type %d", resource->type);
953 			return -EINVAL;
954 		}
955 		resource++;
956 		i++;
957 	}
958 	return 0;
959 }
960