2 * resource.c - Contains functions for registering and analyzing resource information
4 * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz>
5 * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
6 * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
7 * Bjorn Helgaas <bjorn.helgaas@hp.com>
10 #include <linux/module.h>
11 #include <linux/errno.h>
12 #include <linux/interrupt.h>
13 #include <linux/kernel.h>
17 #include <linux/pci.h>
18 #include <linux/ioport.h>
19 #include <linux/init.h>
21 #include <linux/pnp.h>
24 static int pnp_reserve_irq
[16] = {[0 ... 15] = -1 }; /* reserve (don't use) some IRQ */
25 static int pnp_reserve_dma
[8] = {[0 ... 7] = -1 }; /* reserve (don't use) some DMA */
26 static int pnp_reserve_io
[16] = {[0 ... 15] = -1 }; /* reserve (don't use) some I/O region */
27 static int pnp_reserve_mem
[16] = {[0 ... 15] = -1 }; /* reserve (don't use) some memory region */
33 struct pnp_option
*pnp_build_option(struct pnp_dev
*dev
, unsigned long type
,
34 unsigned int option_flags
)
36 struct pnp_option
*option
;
38 option
= kzalloc(sizeof(struct pnp_option
), GFP_KERNEL
);
42 option
->flags
= option_flags
;
45 list_add_tail(&option
->list
, &dev
->options
);
49 int pnp_register_irq_resource(struct pnp_dev
*dev
, unsigned int option_flags
,
50 pnp_irq_mask_t
*map
, unsigned char flags
)
52 struct pnp_option
*option
;
55 option
= pnp_build_option(dev
, IORESOURCE_IRQ
, option_flags
);
67 for (i
= 0; i
< 16; i
++)
68 if (test_bit(i
, irq
->map
.bits
))
69 pcibios_penalize_isa_irq(i
, 0);
73 dbg_pnp_show_option(dev
, option
);
77 int pnp_register_dma_resource(struct pnp_dev
*dev
, unsigned int option_flags
,
78 unsigned char map
, unsigned char flags
)
80 struct pnp_option
*option
;
83 option
= pnp_build_option(dev
, IORESOURCE_DMA
, option_flags
);
91 dbg_pnp_show_option(dev
, option
);
95 int pnp_register_port_resource(struct pnp_dev
*dev
, unsigned int option_flags
,
96 resource_size_t min
, resource_size_t max
,
97 resource_size_t align
, resource_size_t size
,
100 struct pnp_option
*option
;
101 struct pnp_port
*port
;
103 option
= pnp_build_option(dev
, IORESOURCE_IO
, option_flags
);
107 port
= &option
->u
.port
;
114 dbg_pnp_show_option(dev
, option
);
118 int pnp_register_mem_resource(struct pnp_dev
*dev
, unsigned int option_flags
,
119 resource_size_t min
, resource_size_t max
,
120 resource_size_t align
, resource_size_t size
,
123 struct pnp_option
*option
;
126 option
= pnp_build_option(dev
, IORESOURCE_MEM
, option_flags
);
130 mem
= &option
->u
.mem
;
137 dbg_pnp_show_option(dev
, option
);
141 void pnp_free_options(struct pnp_dev
*dev
)
143 struct pnp_option
*option
, *tmp
;
145 list_for_each_entry_safe(option
, tmp
, &dev
->options
, list
) {
146 list_del(&option
->list
);
152 * resource validity checking
155 #define length(start, end) (*(end) - *(start) + 1)
157 /* Two ranges conflict if one doesn't end before the other starts */
158 #define ranged_conflict(starta, enda, startb, endb) \
159 !((*(enda) < *(startb)) || (*(endb) < *(starta)))
161 #define cannot_compare(flags) \
162 ((flags) & IORESOURCE_DISABLED)
164 int pnp_check_port(struct pnp_dev
*dev
, struct resource
*res
)
167 struct pnp_dev
*tdev
;
168 struct resource
*tres
;
169 resource_size_t
*port
, *end
, *tport
, *tend
;
174 /* if the resource doesn't exist, don't complain about it */
175 if (cannot_compare(res
->flags
))
178 /* check if the resource is already in use, skip if the
179 * device is active because it itself may be in use */
181 if (__check_region(&ioport_resource
, *port
, length(port
, end
)))
185 /* check if the resource is reserved */
186 for (i
= 0; i
< 8; i
++) {
187 int rport
= pnp_reserve_io
[i
<< 1];
188 int rend
= pnp_reserve_io
[(i
<< 1) + 1] + rport
- 1;
189 if (ranged_conflict(port
, end
, &rport
, &rend
))
193 /* check for internal conflicts */
194 for (i
= 0; (tres
= pnp_get_resource(dev
, IORESOURCE_IO
, i
)); i
++) {
195 if (tres
!= res
&& tres
->flags
& IORESOURCE_IO
) {
196 tport
= &tres
->start
;
198 if (ranged_conflict(port
, end
, tport
, tend
))
203 /* check for conflicts with other pnp devices */
204 pnp_for_each_dev(tdev
) {
208 (tres
= pnp_get_resource(tdev
, IORESOURCE_IO
, i
));
210 if (tres
->flags
& IORESOURCE_IO
) {
211 if (cannot_compare(tres
->flags
))
213 tport
= &tres
->start
;
215 if (ranged_conflict(port
, end
, tport
, tend
))
224 int pnp_check_mem(struct pnp_dev
*dev
, struct resource
*res
)
227 struct pnp_dev
*tdev
;
228 struct resource
*tres
;
229 resource_size_t
*addr
, *end
, *taddr
, *tend
;
234 /* if the resource doesn't exist, don't complain about it */
235 if (cannot_compare(res
->flags
))
238 /* check if the resource is already in use, skip if the
239 * device is active because it itself may be in use */
241 if (check_mem_region(*addr
, length(addr
, end
)))
245 /* check if the resource is reserved */
246 for (i
= 0; i
< 8; i
++) {
247 int raddr
= pnp_reserve_mem
[i
<< 1];
248 int rend
= pnp_reserve_mem
[(i
<< 1) + 1] + raddr
- 1;
249 if (ranged_conflict(addr
, end
, &raddr
, &rend
))
253 /* check for internal conflicts */
254 for (i
= 0; (tres
= pnp_get_resource(dev
, IORESOURCE_MEM
, i
)); i
++) {
255 if (tres
!= res
&& tres
->flags
& IORESOURCE_MEM
) {
256 taddr
= &tres
->start
;
258 if (ranged_conflict(addr
, end
, taddr
, tend
))
263 /* check for conflicts with other pnp devices */
264 pnp_for_each_dev(tdev
) {
268 (tres
= pnp_get_resource(tdev
, IORESOURCE_MEM
, i
));
270 if (tres
->flags
& IORESOURCE_MEM
) {
271 if (cannot_compare(tres
->flags
))
273 taddr
= &tres
->start
;
275 if (ranged_conflict(addr
, end
, taddr
, tend
))
284 static irqreturn_t
pnp_test_handler(int irq
, void *dev_id
)
290 static int pci_dev_uses_irq(struct pnp_dev
*pnp
, struct pci_dev
*pci
,
296 if (pci
->irq
== irq
) {
297 pnp_dbg(&pnp
->dev
, " device %s using irq %d\n",
303 * See pci_setup_device() and ata_pci_sff_activate_host() for
304 * similar IDE legacy detection.
306 pci_read_config_dword(pci
, PCI_CLASS_REVISION
, &class);
307 class >>= 8; /* discard revision ID */
308 progif
= class & 0xff;
311 if (class == PCI_CLASS_STORAGE_IDE
) {
313 * Unless both channels are native-PCI mode only,
314 * treat the compatibility IRQs as busy.
316 if ((progif
& 0x5) != 0x5)
317 if (pci_get_legacy_ide_irq(pci
, 0) == irq
||
318 pci_get_legacy_ide_irq(pci
, 1) == irq
) {
319 pnp_dbg(&pnp
->dev
, " legacy IDE device %s "
320 "using irq %d\n", pci_name(pci
), irq
);
329 static int pci_uses_irq(struct pnp_dev
*pnp
, unsigned int irq
)
332 struct pci_dev
*pci
= NULL
;
334 for_each_pci_dev(pci
) {
335 if (pci_dev_uses_irq(pnp
, pci
, irq
)) {
344 int pnp_check_irq(struct pnp_dev
*dev
, struct resource
*res
)
347 struct pnp_dev
*tdev
;
348 struct resource
*tres
;
349 resource_size_t
*irq
;
353 /* if the resource doesn't exist, don't complain about it */
354 if (cannot_compare(res
->flags
))
357 /* check if the resource is valid */
358 if (*irq
< 0 || *irq
> 15)
361 /* check if the resource is reserved */
362 for (i
= 0; i
< 16; i
++) {
363 if (pnp_reserve_irq
[i
] == *irq
)
367 /* check for internal conflicts */
368 for (i
= 0; (tres
= pnp_get_resource(dev
, IORESOURCE_IRQ
, i
)); i
++) {
369 if (tres
!= res
&& tres
->flags
& IORESOURCE_IRQ
) {
370 if (tres
->start
== *irq
)
375 /* check if the resource is being used by a pci device */
376 if (pci_uses_irq(dev
, *irq
))
379 /* check if the resource is already in use, skip if the
380 * device is active because it itself may be in use */
382 if (request_irq(*irq
, pnp_test_handler
,
383 IRQF_DISABLED
| IRQF_PROBE_SHARED
, "pnp", NULL
))
385 free_irq(*irq
, NULL
);
388 /* check for conflicts with other pnp devices */
389 pnp_for_each_dev(tdev
) {
393 (tres
= pnp_get_resource(tdev
, IORESOURCE_IRQ
, i
));
395 if (tres
->flags
& IORESOURCE_IRQ
) {
396 if (cannot_compare(tres
->flags
))
398 if (tres
->start
== *irq
)
407 int pnp_check_dma(struct pnp_dev
*dev
, struct resource
*res
)
411 struct pnp_dev
*tdev
;
412 struct resource
*tres
;
413 resource_size_t
*dma
;
417 /* if the resource doesn't exist, don't complain about it */
418 if (cannot_compare(res
->flags
))
421 /* check if the resource is valid */
422 if (*dma
< 0 || *dma
== 4 || *dma
> 7)
425 /* check if the resource is reserved */
426 for (i
= 0; i
< 8; i
++) {
427 if (pnp_reserve_dma
[i
] == *dma
)
431 /* check for internal conflicts */
432 for (i
= 0; (tres
= pnp_get_resource(dev
, IORESOURCE_DMA
, i
)); i
++) {
433 if (tres
!= res
&& tres
->flags
& IORESOURCE_DMA
) {
434 if (tres
->start
== *dma
)
439 /* check if the resource is already in use, skip if the
440 * device is active because it itself may be in use */
442 if (request_dma(*dma
, "pnp"))
447 /* check for conflicts with other pnp devices */
448 pnp_for_each_dev(tdev
) {
452 (tres
= pnp_get_resource(tdev
, IORESOURCE_DMA
, i
));
454 if (tres
->flags
& IORESOURCE_DMA
) {
455 if (cannot_compare(tres
->flags
))
457 if (tres
->start
== *dma
)
465 /* IA64 does not have legacy DMA */
470 unsigned long pnp_resource_type(struct resource
*res
)
472 return res
->flags
& (IORESOURCE_IO
| IORESOURCE_MEM
|
473 IORESOURCE_IRQ
| IORESOURCE_DMA
);
476 struct resource
*pnp_get_resource(struct pnp_dev
*dev
,
477 unsigned long type
, unsigned int num
)
479 struct pnp_resource
*pnp_res
;
480 struct resource
*res
;
482 list_for_each_entry(pnp_res
, &dev
->resources
, list
) {
484 if (pnp_resource_type(res
) == type
&& num
-- == 0)
489 EXPORT_SYMBOL(pnp_get_resource
);
491 static struct pnp_resource
*pnp_new_resource(struct pnp_dev
*dev
)
493 struct pnp_resource
*pnp_res
;
495 pnp_res
= kzalloc(sizeof(struct pnp_resource
), GFP_KERNEL
);
499 list_add_tail(&pnp_res
->list
, &dev
->resources
);
503 struct pnp_resource
*pnp_add_irq_resource(struct pnp_dev
*dev
, int irq
,
506 struct pnp_resource
*pnp_res
;
507 struct resource
*res
;
509 pnp_res
= pnp_new_resource(dev
);
511 dev_err(&dev
->dev
, "can't add resource for IRQ %d\n", irq
);
516 res
->flags
= IORESOURCE_IRQ
| flags
;
520 pnp_dbg(&dev
->dev
, " add irq %d flags %#x\n", irq
, flags
);
524 struct pnp_resource
*pnp_add_dma_resource(struct pnp_dev
*dev
, int dma
,
527 struct pnp_resource
*pnp_res
;
528 struct resource
*res
;
530 pnp_res
= pnp_new_resource(dev
);
532 dev_err(&dev
->dev
, "can't add resource for DMA %d\n", dma
);
537 res
->flags
= IORESOURCE_DMA
| flags
;
541 pnp_dbg(&dev
->dev
, " add dma %d flags %#x\n", dma
, flags
);
545 struct pnp_resource
*pnp_add_io_resource(struct pnp_dev
*dev
,
546 resource_size_t start
,
547 resource_size_t end
, int flags
)
549 struct pnp_resource
*pnp_res
;
550 struct resource
*res
;
552 pnp_res
= pnp_new_resource(dev
);
554 dev_err(&dev
->dev
, "can't add resource for IO %#llx-%#llx\n",
555 (unsigned long long) start
,
556 (unsigned long long) end
);
561 res
->flags
= IORESOURCE_IO
| flags
;
565 pnp_dbg(&dev
->dev
, " add io %#llx-%#llx flags %#x\n",
566 (unsigned long long) start
, (unsigned long long) end
, flags
);
570 struct pnp_resource
*pnp_add_mem_resource(struct pnp_dev
*dev
,
571 resource_size_t start
,
572 resource_size_t end
, int flags
)
574 struct pnp_resource
*pnp_res
;
575 struct resource
*res
;
577 pnp_res
= pnp_new_resource(dev
);
579 dev_err(&dev
->dev
, "can't add resource for MEM %#llx-%#llx\n",
580 (unsigned long long) start
,
581 (unsigned long long) end
);
586 res
->flags
= IORESOURCE_MEM
| flags
;
590 pnp_dbg(&dev
->dev
, " add mem %#llx-%#llx flags %#x\n",
591 (unsigned long long) start
, (unsigned long long) end
, flags
);
596 * Determine whether the specified resource is a possible configuration
599 int pnp_possible_config(struct pnp_dev
*dev
, int type
, resource_size_t start
,
600 resource_size_t size
)
602 struct pnp_option
*option
;
603 struct pnp_port
*port
;
608 list_for_each_entry(option
, &dev
->options
, list
) {
609 if (option
->type
!= type
)
612 switch (option
->type
) {
614 port
= &option
->u
.port
;
615 if (port
->min
== start
&& port
->size
== size
)
619 mem
= &option
->u
.mem
;
620 if (mem
->min
== start
&& mem
->size
== size
)
624 irq
= &option
->u
.irq
;
625 if (start
< PNP_IRQ_NR
&&
626 test_bit(start
, irq
->map
.bits
))
630 dma
= &option
->u
.dma
;
631 if (dma
->map
& (1 << start
))
639 EXPORT_SYMBOL(pnp_possible_config
);
641 int pnp_range_reserved(resource_size_t start
, resource_size_t end
)
644 struct pnp_resource
*pnp_res
;
645 resource_size_t
*dev_start
, *dev_end
;
647 pnp_for_each_dev(dev
) {
648 list_for_each_entry(pnp_res
, &dev
->resources
, list
) {
649 dev_start
= &pnp_res
->res
.start
;
650 dev_end
= &pnp_res
->res
.end
;
651 if (ranged_conflict(&start
, &end
, dev_start
, dev_end
))
657 EXPORT_SYMBOL(pnp_range_reserved
);
659 /* format is: pnp_reserve_irq=irq1[,irq2] .... */
660 static int __init
pnp_setup_reserve_irq(char *str
)
664 for (i
= 0; i
< 16; i
++)
665 if (get_option(&str
, &pnp_reserve_irq
[i
]) != 2)
670 __setup("pnp_reserve_irq=", pnp_setup_reserve_irq
);
672 /* format is: pnp_reserve_dma=dma1[,dma2] .... */
673 static int __init
pnp_setup_reserve_dma(char *str
)
677 for (i
= 0; i
< 8; i
++)
678 if (get_option(&str
, &pnp_reserve_dma
[i
]) != 2)
683 __setup("pnp_reserve_dma=", pnp_setup_reserve_dma
);
685 /* format is: pnp_reserve_io=io1,size1[,io2,size2] .... */
686 static int __init
pnp_setup_reserve_io(char *str
)
690 for (i
= 0; i
< 16; i
++)
691 if (get_option(&str
, &pnp_reserve_io
[i
]) != 2)
696 __setup("pnp_reserve_io=", pnp_setup_reserve_io
);
698 /* format is: pnp_reserve_mem=mem1,size1[,mem2,size2] .... */
699 static int __init
pnp_setup_reserve_mem(char *str
)
703 for (i
= 0; i
< 16; i
++)
704 if (get_option(&str
, &pnp_reserve_mem
[i
]) != 2)
709 __setup("pnp_reserve_mem=", pnp_setup_reserve_mem
);