2 * resource.c - Contains functions for registering and analyzing resource information
4 * based on isapnp.c resource management (c) Jaroslav Kysela <perex@suse.cz>
5 * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
8 #include <linux/module.h>
9 #include <linux/errno.h>
10 #include <linux/interrupt.h>
11 #include <linux/kernel.h>
15 #include <linux/pci.h>
16 #include <linux/ioport.h>
17 #include <linux/init.h>
19 #include <linux/pnp.h>
22 static int pnp_reserve_irq
[16] = {[0 ... 15] = -1 }; /* reserve (don't use) some IRQ */
23 static int pnp_reserve_dma
[8] = {[0 ... 7] = -1 }; /* reserve (don't use) some DMA */
24 static int pnp_reserve_io
[16] = {[0 ... 15] = -1 }; /* reserve (don't use) some I/O region */
25 static int pnp_reserve_mem
[16] = {[0 ... 15] = -1 }; /* reserve (don't use) some memory region */
31 static struct pnp_option
*pnp_build_option(int priority
)
33 struct pnp_option
*option
= pnp_alloc(sizeof(struct pnp_option
));
38 option
->priority
= priority
& 0xff;
39 /* make sure the priority is valid */
40 if (option
->priority
> PNP_RES_PRIORITY_FUNCTIONAL
)
41 option
->priority
= PNP_RES_PRIORITY_INVALID
;
46 struct pnp_option
*pnp_register_independent_option(struct pnp_dev
*dev
)
48 struct pnp_option
*option
;
53 option
= pnp_build_option(PNP_RES_PRIORITY_PREFERRED
);
55 /* this should never happen but if it does we'll try to continue */
57 pnp_err("independent resource already registered");
58 dev
->independent
= option
;
62 struct pnp_option
*pnp_register_dependent_option(struct pnp_dev
*dev
,
65 struct pnp_option
*option
;
70 option
= pnp_build_option(priority
);
73 struct pnp_option
*parent
= dev
->dependent
;
75 parent
= parent
->next
;
76 parent
->next
= option
;
78 dev
->dependent
= option
;
82 int pnp_register_irq_resource(struct pnp_option
*option
, struct pnp_irq
*data
)
92 while (ptr
&& ptr
->next
)
103 for (i
= 0; i
< 16; i
++)
104 if (test_bit(i
, data
->map
))
105 pcibios_penalize_isa_irq(i
, 0);
111 int pnp_register_dma_resource(struct pnp_option
*option
, struct pnp_dma
*data
)
121 while (ptr
&& ptr
->next
)
131 int pnp_register_port_resource(struct pnp_option
*option
, struct pnp_port
*data
)
133 struct pnp_port
*ptr
;
141 while (ptr
&& ptr
->next
)
151 int pnp_register_mem_resource(struct pnp_option
*option
, struct pnp_mem
*data
)
161 while (ptr
&& ptr
->next
)
170 static void pnp_free_port(struct pnp_port
*port
)
172 struct pnp_port
*next
;
181 static void pnp_free_irq(struct pnp_irq
*irq
)
183 struct pnp_irq
*next
;
192 static void pnp_free_dma(struct pnp_dma
*dma
)
194 struct pnp_dma
*next
;
203 static void pnp_free_mem(struct pnp_mem
*mem
)
205 struct pnp_mem
*next
;
214 void pnp_free_option(struct pnp_option
*option
)
216 struct pnp_option
*next
;
220 pnp_free_port(option
->port
);
221 pnp_free_irq(option
->irq
);
222 pnp_free_dma(option
->dma
);
223 pnp_free_mem(option
->mem
);
230 * resource validity checking
233 #define length(start, end) (*(end) - *(start) + 1)
235 /* Two ranges conflict if one doesn't end before the other starts */
236 #define ranged_conflict(starta, enda, startb, endb) \
237 !((*(enda) < *(startb)) || (*(endb) < *(starta)))
239 #define cannot_compare(flags) \
240 ((flags) & (IORESOURCE_UNSET | IORESOURCE_DISABLED))
242 int pnp_check_port(struct pnp_dev
*dev
, int idx
)
245 struct pnp_dev
*tdev
;
246 resource_size_t
*port
, *end
, *tport
, *tend
;
248 port
= &dev
->res
.port_resource
[idx
].start
;
249 end
= &dev
->res
.port_resource
[idx
].end
;
251 /* if the resource doesn't exist, don't complain about it */
252 if (cannot_compare(dev
->res
.port_resource
[idx
].flags
))
255 /* check if the resource is already in use, skip if the
256 * device is active because it itself may be in use */
258 if (__check_region(&ioport_resource
, *port
, length(port
, end
)))
262 /* check if the resource is reserved */
263 for (tmp
= 0; tmp
< 8; tmp
++) {
264 int rport
= pnp_reserve_io
[tmp
<< 1];
265 int rend
= pnp_reserve_io
[(tmp
<< 1) + 1] + rport
- 1;
266 if (ranged_conflict(port
, end
, &rport
, &rend
))
270 /* check for internal conflicts */
271 for (tmp
= 0; tmp
< PNP_MAX_PORT
&& tmp
!= idx
; tmp
++) {
272 if (dev
->res
.port_resource
[tmp
].flags
& IORESOURCE_IO
) {
273 tport
= &dev
->res
.port_resource
[tmp
].start
;
274 tend
= &dev
->res
.port_resource
[tmp
].end
;
275 if (ranged_conflict(port
, end
, tport
, tend
))
280 /* check for conflicts with other pnp devices */
281 pnp_for_each_dev(tdev
) {
284 for (tmp
= 0; tmp
< PNP_MAX_PORT
; tmp
++) {
285 if (tdev
->res
.port_resource
[tmp
].flags
& IORESOURCE_IO
) {
287 (tdev
->res
.port_resource
[tmp
].flags
))
289 tport
= &tdev
->res
.port_resource
[tmp
].start
;
290 tend
= &tdev
->res
.port_resource
[tmp
].end
;
291 if (ranged_conflict(port
, end
, tport
, tend
))
300 int pnp_check_mem(struct pnp_dev
*dev
, int idx
)
303 struct pnp_dev
*tdev
;
304 resource_size_t
*addr
, *end
, *taddr
, *tend
;
306 addr
= &dev
->res
.mem_resource
[idx
].start
;
307 end
= &dev
->res
.mem_resource
[idx
].end
;
309 /* if the resource doesn't exist, don't complain about it */
310 if (cannot_compare(dev
->res
.mem_resource
[idx
].flags
))
313 /* check if the resource is already in use, skip if the
314 * device is active because it itself may be in use */
316 if (check_mem_region(*addr
, length(addr
, end
)))
320 /* check if the resource is reserved */
321 for (tmp
= 0; tmp
< 8; tmp
++) {
322 int raddr
= pnp_reserve_mem
[tmp
<< 1];
323 int rend
= pnp_reserve_mem
[(tmp
<< 1) + 1] + raddr
- 1;
324 if (ranged_conflict(addr
, end
, &raddr
, &rend
))
328 /* check for internal conflicts */
329 for (tmp
= 0; tmp
< PNP_MAX_MEM
&& tmp
!= idx
; tmp
++) {
330 if (dev
->res
.mem_resource
[tmp
].flags
& IORESOURCE_MEM
) {
331 taddr
= &dev
->res
.mem_resource
[tmp
].start
;
332 tend
= &dev
->res
.mem_resource
[tmp
].end
;
333 if (ranged_conflict(addr
, end
, taddr
, tend
))
338 /* check for conflicts with other pnp devices */
339 pnp_for_each_dev(tdev
) {
342 for (tmp
= 0; tmp
< PNP_MAX_MEM
; tmp
++) {
343 if (tdev
->res
.mem_resource
[tmp
].flags
& IORESOURCE_MEM
) {
345 (tdev
->res
.mem_resource
[tmp
].flags
))
347 taddr
= &tdev
->res
.mem_resource
[tmp
].start
;
348 tend
= &tdev
->res
.mem_resource
[tmp
].end
;
349 if (ranged_conflict(addr
, end
, taddr
, tend
))
358 static irqreturn_t
pnp_test_handler(int irq
, void *dev_id
)
363 int pnp_check_irq(struct pnp_dev
*dev
, int idx
)
366 struct pnp_dev
*tdev
;
367 resource_size_t
*irq
= &dev
->res
.irq_resource
[idx
].start
;
369 /* if the resource doesn't exist, don't complain about it */
370 if (cannot_compare(dev
->res
.irq_resource
[idx
].flags
))
373 /* check if the resource is valid */
374 if (*irq
< 0 || *irq
> 15)
377 /* check if the resource is reserved */
378 for (tmp
= 0; tmp
< 16; tmp
++) {
379 if (pnp_reserve_irq
[tmp
] == *irq
)
383 /* check for internal conflicts */
384 for (tmp
= 0; tmp
< PNP_MAX_IRQ
&& tmp
!= idx
; tmp
++) {
385 if (dev
->res
.irq_resource
[tmp
].flags
& IORESOURCE_IRQ
) {
386 if (dev
->res
.irq_resource
[tmp
].start
== *irq
)
392 /* check if the resource is being used by a pci device */
394 struct pci_dev
*pci
= NULL
;
395 for_each_pci_dev(pci
) {
396 if (pci
->irq
== *irq
)
402 /* check if the resource is already in use, skip if the
403 * device is active because it itself may be in use */
405 if (request_irq(*irq
, pnp_test_handler
,
406 IRQF_DISABLED
| IRQF_PROBE_SHARED
, "pnp", NULL
))
408 free_irq(*irq
, NULL
);
411 /* check for conflicts with other pnp devices */
412 pnp_for_each_dev(tdev
) {
415 for (tmp
= 0; tmp
< PNP_MAX_IRQ
; tmp
++) {
416 if (tdev
->res
.irq_resource
[tmp
].flags
& IORESOURCE_IRQ
) {
418 (tdev
->res
.irq_resource
[tmp
].flags
))
420 if ((tdev
->res
.irq_resource
[tmp
].start
== *irq
))
429 int pnp_check_dma(struct pnp_dev
*dev
, int idx
)
433 struct pnp_dev
*tdev
;
434 resource_size_t
*dma
= &dev
->res
.dma_resource
[idx
].start
;
436 /* if the resource doesn't exist, don't complain about it */
437 if (cannot_compare(dev
->res
.dma_resource
[idx
].flags
))
440 /* check if the resource is valid */
441 if (*dma
< 0 || *dma
== 4 || *dma
> 7)
444 /* check if the resource is reserved */
445 for (tmp
= 0; tmp
< 8; tmp
++) {
446 if (pnp_reserve_dma
[tmp
] == *dma
)
450 /* check for internal conflicts */
451 for (tmp
= 0; tmp
< PNP_MAX_DMA
&& tmp
!= idx
; tmp
++) {
452 if (dev
->res
.dma_resource
[tmp
].flags
& IORESOURCE_DMA
) {
453 if (dev
->res
.dma_resource
[tmp
].start
== *dma
)
458 /* check if the resource is already in use, skip if the
459 * device is active because it itself may be in use */
461 if (request_dma(*dma
, "pnp"))
466 /* check for conflicts with other pnp devices */
467 pnp_for_each_dev(tdev
) {
470 for (tmp
= 0; tmp
< PNP_MAX_DMA
; tmp
++) {
471 if (tdev
->res
.dma_resource
[tmp
].flags
& IORESOURCE_DMA
) {
473 (tdev
->res
.dma_resource
[tmp
].flags
))
475 if ((tdev
->res
.dma_resource
[tmp
].start
== *dma
))
483 /* IA64 does not have legacy DMA */
488 /* format is: pnp_reserve_irq=irq1[,irq2] .... */
489 static int __init
pnp_setup_reserve_irq(char *str
)
493 for (i
= 0; i
< 16; i
++)
494 if (get_option(&str
, &pnp_reserve_irq
[i
]) != 2)
499 __setup("pnp_reserve_irq=", pnp_setup_reserve_irq
);
501 /* format is: pnp_reserve_dma=dma1[,dma2] .... */
502 static int __init
pnp_setup_reserve_dma(char *str
)
506 for (i
= 0; i
< 8; i
++)
507 if (get_option(&str
, &pnp_reserve_dma
[i
]) != 2)
512 __setup("pnp_reserve_dma=", pnp_setup_reserve_dma
);
514 /* format is: pnp_reserve_io=io1,size1[,io2,size2] .... */
515 static int __init
pnp_setup_reserve_io(char *str
)
519 for (i
= 0; i
< 16; i
++)
520 if (get_option(&str
, &pnp_reserve_io
[i
]) != 2)
525 __setup("pnp_reserve_io=", pnp_setup_reserve_io
);
527 /* format is: pnp_reserve_mem=mem1,size1[,mem2,size2] .... */
528 static int __init
pnp_setup_reserve_mem(char *str
)
532 for (i
= 0; i
< 16; i
++)
533 if (get_option(&str
, &pnp_reserve_mem
[i
]) != 2)
538 __setup("pnp_reserve_mem=", pnp_setup_reserve_mem
);