11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * resource.c - Contains functions for registering and analyzing resource information
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4c1017a4cdb68ae5368fbc9ee42c77f1f5dca8916Jaroslav Kysela * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz>
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
61f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
71f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas *	Bjorn Helgaas <bjorn.helgaas@hp.com>
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
115a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/dma.h>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/irq.h>
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pnp.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "base.h"
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2507d4e9af109221ab731c5aaf832e89776c64b013Bjorn Helgaasstatic int pnp_reserve_irq[16] = {[0 ... 15] = -1 };	/* reserve (don't use) some IRQ */
2607d4e9af109221ab731c5aaf832e89776c64b013Bjorn Helgaasstatic int pnp_reserve_dma[8] = {[0 ... 7] = -1 };	/* reserve (don't use) some DMA */
2707d4e9af109221ab731c5aaf832e89776c64b013Bjorn Helgaasstatic int pnp_reserve_io[16] = {[0 ... 15] = -1 };	/* reserve (don't use) some I/O region */
2807d4e9af109221ab731c5aaf832e89776c64b013Bjorn Helgaasstatic int pnp_reserve_mem[16] = {[0 ... 15] = -1 };	/* reserve (don't use) some memory region */
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * option registration
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaasstruct pnp_option *pnp_build_option(struct pnp_dev *dev, unsigned long type,
351f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas				    unsigned int option_flags)
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
371f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	struct pnp_option *option;
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
391f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	option = kzalloc(sizeof(struct pnp_option), GFP_KERNEL);
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!option)
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NULL;
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	option->flags = option_flags;
441f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	option->type = type;
4507d4e9af109221ab731c5aaf832e89776c64b013Bjorn Helgaas
461f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	list_add_tail(&option->list, &dev->options);
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return option;
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
501f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaasint pnp_register_irq_resource(struct pnp_dev *dev, unsigned int option_flags,
51c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas			      pnp_irq_mask_t *map, unsigned char flags)
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
531f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	struct pnp_option *option;
541f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	struct pnp_irq *irq;
5507d4e9af109221ab731c5aaf832e89776c64b013Bjorn Helgaas
561f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	option = pnp_build_option(dev, IORESOURCE_IRQ, option_flags);
571f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	if (!option)
58c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas		return -ENOMEM;
59c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas
601f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	irq = &option->u.irq;
612d29a7a794c5bae982955cd5dd0a76e766e57f39Bjorn Helgaas	irq->map = *map;
622d29a7a794c5bae982955cd5dd0a76e766e57f39Bjorn Helgaas	irq->flags = flags;
63c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PCI
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int i;
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < 16; i++)
692d29a7a794c5bae982955cd5dd0a76e766e57f39Bjorn Helgaas			if (test_bit(i, irq->map.bits))
70c9c3e457de24cca2ca688fa397d93a241f472048David Shaohua Li				pcibios_penalize_isa_irq(i, 0);
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
73c1caf06ccfd3a4efd4b489f89bcdabd2362f31d0Bjorn Helgaas
741f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	dbg_pnp_show_option(dev, option);
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
781f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaasint pnp_register_dma_resource(struct pnp_dev *dev, unsigned int option_flags,
79c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas			      unsigned char map, unsigned char flags)
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
811f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	struct pnp_option *option;
821f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	struct pnp_dma *dma;
83c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas
841f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	option = pnp_build_option(dev, IORESOURCE_DMA, option_flags);
851f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	if (!option)
86c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas		return -ENOMEM;
87c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas
881f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	dma = &option->u.dma;
892d29a7a794c5bae982955cd5dd0a76e766e57f39Bjorn Helgaas	dma->map = map;
902d29a7a794c5bae982955cd5dd0a76e766e57f39Bjorn Helgaas	dma->flags = flags;
9107d4e9af109221ab731c5aaf832e89776c64b013Bjorn Helgaas
921f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	dbg_pnp_show_option(dev, option);
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
961f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaasint pnp_register_port_resource(struct pnp_dev *dev, unsigned int option_flags,
97c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas			       resource_size_t min, resource_size_t max,
98c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas			       resource_size_t align, resource_size_t size,
99c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas			       unsigned char flags)
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1011f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	struct pnp_option *option;
1021f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	struct pnp_port *port;
103c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas
1041f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	option = pnp_build_option(dev, IORESOURCE_IO, option_flags);
1051f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	if (!option)
106c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas		return -ENOMEM;
107c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas
1081f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	port = &option->u.port;
1092d29a7a794c5bae982955cd5dd0a76e766e57f39Bjorn Helgaas	port->min = min;
1102d29a7a794c5bae982955cd5dd0a76e766e57f39Bjorn Helgaas	port->max = max;
1112d29a7a794c5bae982955cd5dd0a76e766e57f39Bjorn Helgaas	port->align = align;
1122d29a7a794c5bae982955cd5dd0a76e766e57f39Bjorn Helgaas	port->size = size;
1132d29a7a794c5bae982955cd5dd0a76e766e57f39Bjorn Helgaas	port->flags = flags;
11407d4e9af109221ab731c5aaf832e89776c64b013Bjorn Helgaas
1151f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	dbg_pnp_show_option(dev, option);
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1191f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaasint pnp_register_mem_resource(struct pnp_dev *dev, unsigned int option_flags,
120c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas			      resource_size_t min, resource_size_t max,
121c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas			      resource_size_t align, resource_size_t size,
122c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas			      unsigned char flags)
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1241f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	struct pnp_option *option;
1251f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	struct pnp_mem *mem;
126c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas
1271f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	option = pnp_build_option(dev, IORESOURCE_MEM, option_flags);
1281f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	if (!option)
129c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas		return -ENOMEM;
130c227536b4cc2600fc9d22ba0067f699165f6621fBjorn Helgaas
1311f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	mem = &option->u.mem;
1322d29a7a794c5bae982955cd5dd0a76e766e57f39Bjorn Helgaas	mem->min = min;
1332d29a7a794c5bae982955cd5dd0a76e766e57f39Bjorn Helgaas	mem->max = max;
1342d29a7a794c5bae982955cd5dd0a76e766e57f39Bjorn Helgaas	mem->align = align;
1352d29a7a794c5bae982955cd5dd0a76e766e57f39Bjorn Helgaas	mem->size = size;
1362d29a7a794c5bae982955cd5dd0a76e766e57f39Bjorn Helgaas	mem->flags = flags;
13707d4e9af109221ab731c5aaf832e89776c64b013Bjorn Helgaas
1381f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	dbg_pnp_show_option(dev, option);
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1421f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaasvoid pnp_free_options(struct pnp_dev *dev)
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1441f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	struct pnp_option *option, *tmp;
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1461f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	list_for_each_entry_safe(option, tmp, &dev->options, list) {
1471f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas		list_del(&option->list);
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(option);
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * resource validity checking
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define length(start, end) (*(end) - *(start) + 1)
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Two ranges conflict if one doesn't end before the other starts */
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ranged_conflict(starta, enda, startb, endb) \
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	!((*(enda) < *(startb)) || (*(endb) < *(starta)))
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define cannot_compare(flags) \
163aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas((flags) & IORESOURCE_DISABLED)
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
165f5d94ff014cb7e6212f40fc6644f3fd68507df33Bjorn Helgaasint pnp_check_port(struct pnp_dev *dev, struct resource *res)
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
167ecfa935a2f7ef89543608f3ca05340c158c9a236Bjorn Helgaas	int i;
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pnp_dev *tdev;
169f5d94ff014cb7e6212f40fc6644f3fd68507df33Bjorn Helgaas	struct resource *tres;
170b60ba8343b78b182c03cf239d4342785376c1ad1Greg Kroah-Hartman	resource_size_t *port, *end, *tport, *tend;
17107d4e9af109221ab731c5aaf832e89776c64b013Bjorn Helgaas
17230c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas	port = &res->start;
17330c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas	end = &res->end;
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* if the resource doesn't exist, don't complain about it */
17630c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas	if (cannot_compare(res->flags))
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 1;
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check if the resource is already in use, skip if the
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * device is active because it itself may be in use */
1819dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	if (!dev->active) {
1829dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		if (__check_region(&ioport_resource, *port, length(port, end)))
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check if the resource is reserved */
187ecfa935a2f7ef89543608f3ca05340c158c9a236Bjorn Helgaas	for (i = 0; i < 8; i++) {
188ecfa935a2f7ef89543608f3ca05340c158c9a236Bjorn Helgaas		int rport = pnp_reserve_io[i << 1];
189ecfa935a2f7ef89543608f3ca05340c158c9a236Bjorn Helgaas		int rend = pnp_reserve_io[(i << 1) + 1] + rport - 1;
1909dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		if (ranged_conflict(port, end, &rport, &rend))
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check for internal conflicts */
19595ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas	for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
19695ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas		if (tres != res && tres->flags & IORESOURCE_IO) {
19730c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas			tport = &tres->start;
19830c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas			tend = &tres->end;
1999dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas			if (ranged_conflict(port, end, tport, tend))
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return 0;
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check for conflicts with other pnp devices */
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pnp_for_each_dev(tdev) {
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (tdev == dev)
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
20895ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas		for (i = 0;
20995ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas		     (tres = pnp_get_resource(tdev, IORESOURCE_IO, i));
21095ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas		     i++) {
21195ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas			if (tres->flags & IORESOURCE_IO) {
21230c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas				if (cannot_compare(tres->flags))
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					continue;
21411439a6fd90b4861df64b4f983726e1c54977ab7Bjorn Helgaas				if (tres->flags & IORESOURCE_WINDOW)
21511439a6fd90b4861df64b4f983726e1c54977ab7Bjorn Helgaas					continue;
21630c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas				tport = &tres->start;
21730c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas				tend = &tres->end;
2189dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas				if (ranged_conflict(port, end, tport, tend))
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					return 0;
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 1;
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
227f5d94ff014cb7e6212f40fc6644f3fd68507df33Bjorn Helgaasint pnp_check_mem(struct pnp_dev *dev, struct resource *res)
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
229ecfa935a2f7ef89543608f3ca05340c158c9a236Bjorn Helgaas	int i;
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pnp_dev *tdev;
231f5d94ff014cb7e6212f40fc6644f3fd68507df33Bjorn Helgaas	struct resource *tres;
232b60ba8343b78b182c03cf239d4342785376c1ad1Greg Kroah-Hartman	resource_size_t *addr, *end, *taddr, *tend;
23307d4e9af109221ab731c5aaf832e89776c64b013Bjorn Helgaas
23430c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas	addr = &res->start;
23530c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas	end = &res->end;
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* if the resource doesn't exist, don't complain about it */
23830c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas	if (cannot_compare(res->flags))
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 1;
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check if the resource is already in use, skip if the
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * device is active because it itself may be in use */
2439dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	if (!dev->active) {
2449dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		if (check_mem_region(*addr, length(addr, end)))
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check if the resource is reserved */
249ecfa935a2f7ef89543608f3ca05340c158c9a236Bjorn Helgaas	for (i = 0; i < 8; i++) {
250ecfa935a2f7ef89543608f3ca05340c158c9a236Bjorn Helgaas		int raddr = pnp_reserve_mem[i << 1];
251ecfa935a2f7ef89543608f3ca05340c158c9a236Bjorn Helgaas		int rend = pnp_reserve_mem[(i << 1) + 1] + raddr - 1;
2529dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		if (ranged_conflict(addr, end, &raddr, &rend))
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check for internal conflicts */
25795ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas	for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
25895ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas		if (tres != res && tres->flags & IORESOURCE_MEM) {
25930c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas			taddr = &tres->start;
26030c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas			tend = &tres->end;
2619dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas			if (ranged_conflict(addr, end, taddr, tend))
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return 0;
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check for conflicts with other pnp devices */
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pnp_for_each_dev(tdev) {
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (tdev == dev)
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
27095ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas		for (i = 0;
27195ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas		     (tres = pnp_get_resource(tdev, IORESOURCE_MEM, i));
27295ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas		     i++) {
27395ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas			if (tres->flags & IORESOURCE_MEM) {
27430c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas				if (cannot_compare(tres->flags))
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					continue;
27611439a6fd90b4861df64b4f983726e1c54977ab7Bjorn Helgaas				if (tres->flags & IORESOURCE_WINDOW)
27711439a6fd90b4861df64b4f983726e1c54977ab7Bjorn Helgaas					continue;
27830c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas				taddr = &tres->start;
27930c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas				tend = &tres->end;
2809dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas				if (ranged_conflict(addr, end, taddr, tend))
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					return 0;
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 1;
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2897d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t pnp_test_handler(int irq, void *dev_id)
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return IRQ_HANDLED;
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29484684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas#ifdef CONFIG_PCI
29584684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaasstatic int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci,
29684684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas			    unsigned int irq)
29784684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas{
29884684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas	u32 class;
29984684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas	u8 progif;
30084684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas
30184684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas	if (pci->irq == irq) {
3022f53432c2aedbe79020e44525eb069d9138a01ddBjorn Helgaas		pnp_dbg(&pnp->dev, "  device %s using irq %d\n",
30384684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas			pci_name(pci), irq);
30484684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas		return 1;
30584684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas	}
30684684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas
30784684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas	/*
30884684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas	 * See pci_setup_device() and ata_pci_sff_activate_host() for
30984684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas	 * similar IDE legacy detection.
31084684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas	 */
31184684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas	pci_read_config_dword(pci, PCI_CLASS_REVISION, &class);
31284684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas	class >>= 8;		/* discard revision ID */
31384684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas	progif = class & 0xff;
31484684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas	class >>= 8;
31584684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas
31684684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas	if (class == PCI_CLASS_STORAGE_IDE) {
31784684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas		/*
31884684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas		 * Unless both channels are native-PCI mode only,
31984684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas		 * treat the compatibility IRQs as busy.
32084684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas		 */
32184684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas		if ((progif & 0x5) != 0x5)
32284684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas			if (pci_get_legacy_ide_irq(pci, 0) == irq ||
32384684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas			    pci_get_legacy_ide_irq(pci, 1) == irq) {
3242f53432c2aedbe79020e44525eb069d9138a01ddBjorn Helgaas				pnp_dbg(&pnp->dev, "  legacy IDE device %s "
32584684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas					"using irq %d\n", pci_name(pci), irq);
32684684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas				return 1;
32784684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas			}
32884684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas	}
32984684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas
33084684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas	return 0;
33184684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas}
33284684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas#endif
33384684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas
33484684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaasstatic int pci_uses_irq(struct pnp_dev *pnp, unsigned int irq)
33584684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas{
33684684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas#ifdef CONFIG_PCI
33784684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas	struct pci_dev *pci = NULL;
33884684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas
33984684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas	for_each_pci_dev(pci) {
34084684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas		if (pci_dev_uses_irq(pnp, pci, irq)) {
34184684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas			pci_dev_put(pci);
34284684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas			return 1;
34384684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas		}
34484684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas	}
34584684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas#endif
34684684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas	return 0;
34784684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas}
34884684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas
349f5d94ff014cb7e6212f40fc6644f3fd68507df33Bjorn Helgaasint pnp_check_irq(struct pnp_dev *dev, struct resource *res)
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
351ecfa935a2f7ef89543608f3ca05340c158c9a236Bjorn Helgaas	int i;
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pnp_dev *tdev;
353f5d94ff014cb7e6212f40fc6644f3fd68507df33Bjorn Helgaas	struct resource *tres;
35430c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas	resource_size_t *irq;
35530c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas
35630c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas	irq = &res->start;
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* if the resource doesn't exist, don't complain about it */
35930c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas	if (cannot_compare(res->flags))
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 1;
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check if the resource is valid */
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (*irq < 0 || *irq > 15)
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check if the resource is reserved */
367ecfa935a2f7ef89543608f3ca05340c158c9a236Bjorn Helgaas	for (i = 0; i < 16; i++) {
368ecfa935a2f7ef89543608f3ca05340c158c9a236Bjorn Helgaas		if (pnp_reserve_irq[i] == *irq)
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check for internal conflicts */
37395ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas	for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) {
37495ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas		if (tres != res && tres->flags & IORESOURCE_IRQ) {
37530c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas			if (tres->start == *irq)
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return 0;
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check if the resource is being used by a pci device */
38184684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas	if (pci_uses_irq(dev, *irq))
38284684c7469a2e6fcbf8c808ac5030ba2de14ff77Bjorn Helgaas		return 0;
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check if the resource is already in use, skip if the
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * device is active because it itself may be in use */
3869dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	if (!dev->active) {
3870cadaf45bd7c19f0bef49d1eebfff38a046b9ba4Andrew Morton		if (request_irq(*irq, pnp_test_handler,
3889dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas				IRQF_DISABLED | IRQF_PROBE_SHARED, "pnp", NULL))
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		free_irq(*irq, NULL);
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check for conflicts with other pnp devices */
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pnp_for_each_dev(tdev) {
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (tdev == dev)
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
39795ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas		for (i = 0;
39895ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas		     (tres = pnp_get_resource(tdev, IORESOURCE_IRQ, i));
39995ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas		     i++) {
40095ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas			if (tres->flags & IORESOURCE_IRQ) {
40130c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas				if (cannot_compare(tres->flags))
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					continue;
40330c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas				if (tres->start == *irq)
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					return 0;
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 1;
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
412586f83e2b4c080073b115c1a0fcc2757f52839b8David Rientjes#ifdef CONFIG_ISA_DMA_API
413f5d94ff014cb7e6212f40fc6644f3fd68507df33Bjorn Helgaasint pnp_check_dma(struct pnp_dev *dev, struct resource *res)
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
415ecfa935a2f7ef89543608f3ca05340c158c9a236Bjorn Helgaas	int i;
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pnp_dev *tdev;
417f5d94ff014cb7e6212f40fc6644f3fd68507df33Bjorn Helgaas	struct resource *tres;
41830c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas	resource_size_t *dma;
41930c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas
42030c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas	dma = &res->start;
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* if the resource doesn't exist, don't complain about it */
42330c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas	if (cannot_compare(res->flags))
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 1;
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check if the resource is valid */
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (*dma < 0 || *dma == 4 || *dma > 7)
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check if the resource is reserved */
431ecfa935a2f7ef89543608f3ca05340c158c9a236Bjorn Helgaas	for (i = 0; i < 8; i++) {
432ecfa935a2f7ef89543608f3ca05340c158c9a236Bjorn Helgaas		if (pnp_reserve_dma[i] == *dma)
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check for internal conflicts */
43795ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas	for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) {
43895ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas		if (tres != res && tres->flags & IORESOURCE_DMA) {
43930c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas			if (tres->start == *dma)
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return 0;
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check if the resource is already in use, skip if the
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * device is active because it itself may be in use */
4469dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas	if (!dev->active) {
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (request_dma(*dma, "pnp"))
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		free_dma(*dma);
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check for conflicts with other pnp devices */
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pnp_for_each_dev(tdev) {
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (tdev == dev)
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
45695ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas		for (i = 0;
45795ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas		     (tres = pnp_get_resource(tdev, IORESOURCE_DMA, i));
45895ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas		     i++) {
45995ab3669f7830682c7762e9c305a0c1dd44454ccBjorn Helgaas			if (tres->flags & IORESOURCE_DMA) {
46030c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas				if (cannot_compare(tres->flags))
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					continue;
46230c016a0c8d2aae10be6a87bb98f0e85db8b09d5Bjorn Helgaas				if (tres->start == *dma)
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					return 0;
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 1;
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
470586f83e2b4c080073b115c1a0fcc2757f52839b8David Rientjes#endif /* CONFIG_ISA_DMA_API */
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
472b563cf59c4d67da7d671788a9848416bfa4180abRene Hermanunsigned long pnp_resource_type(struct resource *res)
473940e98dbc616f1df7b63b73858a966969baf261dBjorn Helgaas{
474940e98dbc616f1df7b63b73858a966969baf261dBjorn Helgaas	return res->flags & (IORESOURCE_IO  | IORESOURCE_MEM |
4757e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas			     IORESOURCE_IRQ | IORESOURCE_DMA |
4767e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas			     IORESOURCE_BUS);
477940e98dbc616f1df7b63b73858a966969baf261dBjorn Helgaas}
478940e98dbc616f1df7b63b73858a966969baf261dBjorn Helgaas
4790a977f15469457d9a19eed992caf71995c674064Bjorn Helgaasstruct resource *pnp_get_resource(struct pnp_dev *dev,
480b563cf59c4d67da7d671788a9848416bfa4180abRene Herman				  unsigned long type, unsigned int num)
4810a977f15469457d9a19eed992caf71995c674064Bjorn Helgaas{
4820a977f15469457d9a19eed992caf71995c674064Bjorn Helgaas	struct pnp_resource *pnp_res;
483aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	struct resource *res;
4840a977f15469457d9a19eed992caf71995c674064Bjorn Helgaas
485aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	list_for_each_entry(pnp_res, &dev->resources, list) {
486aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		res = &pnp_res->res;
487aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		if (pnp_resource_type(res) == type && num-- == 0)
488aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas			return res;
489aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	}
4900a977f15469457d9a19eed992caf71995c674064Bjorn Helgaas	return NULL;
4910a977f15469457d9a19eed992caf71995c674064Bjorn Helgaas}
492b90eca0a61ebd010036242e29610bc6a909e3f19Bjorn HelgaasEXPORT_SYMBOL(pnp_get_resource);
493b90eca0a61ebd010036242e29610bc6a909e3f19Bjorn Helgaas
494aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaasstatic struct pnp_resource *pnp_new_resource(struct pnp_dev *dev)
495a50b6d7b8d7e1a8b13bd1be65a865b115e1190d9Bjorn Helgaas{
496a50b6d7b8d7e1a8b13bd1be65a865b115e1190d9Bjorn Helgaas	struct pnp_resource *pnp_res;
497a50b6d7b8d7e1a8b13bd1be65a865b115e1190d9Bjorn Helgaas
498aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	pnp_res = kzalloc(sizeof(struct pnp_resource), GFP_KERNEL);
499aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	if (!pnp_res)
500aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas		return NULL;
501aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas
502aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	list_add_tail(&pnp_res->list, &dev->resources);
503aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	return pnp_res;
504a50b6d7b8d7e1a8b13bd1be65a865b115e1190d9Bjorn Helgaas}
505a50b6d7b8d7e1a8b13bd1be65a865b115e1190d9Bjorn Helgaas
506dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaasstruct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
507dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas					  int flags)
508dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas{
509dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas	struct pnp_resource *pnp_res;
510dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas	struct resource *res;
511dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas
512aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	pnp_res = pnp_new_resource(dev);
513dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas	if (!pnp_res) {
51425d39c39d82d062f4be685146abd054a3bafdf12Bjorn Helgaas		dev_err(&dev->dev, "can't add resource for IRQ %d\n", irq);
515dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas		return NULL;
516dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas	}
517dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas
518dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas	res = &pnp_res->res;
519dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas	res->flags = IORESOURCE_IRQ | flags;
520dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas	res->start = irq;
521dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas	res->end = irq;
522dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas
523c1f3f2819667a238585c65bba96c8b16af39a442Bjorn Helgaas	dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
524dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas	return pnp_res;
525dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas}
526dbddd0383c59d588f8db5e773b062756e39117ecBjorn Helgaas
527dc16f5f2ede8cc2acf8ac22857a7fecf3a4296c2Bjorn Helgaasstruct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
528dc16f5f2ede8cc2acf8ac22857a7fecf3a4296c2Bjorn Helgaas					  int flags)
529dc16f5f2ede8cc2acf8ac22857a7fecf3a4296c2Bjorn Helgaas{
530dc16f5f2ede8cc2acf8ac22857a7fecf3a4296c2Bjorn Helgaas	struct pnp_resource *pnp_res;
531dc16f5f2ede8cc2acf8ac22857a7fecf3a4296c2Bjorn Helgaas	struct resource *res;
532dc16f5f2ede8cc2acf8ac22857a7fecf3a4296c2Bjorn Helgaas
533aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	pnp_res = pnp_new_resource(dev);
534dc16f5f2ede8cc2acf8ac22857a7fecf3a4296c2Bjorn Helgaas	if (!pnp_res) {
53525d39c39d82d062f4be685146abd054a3bafdf12Bjorn Helgaas		dev_err(&dev->dev, "can't add resource for DMA %d\n", dma);
536dc16f5f2ede8cc2acf8ac22857a7fecf3a4296c2Bjorn Helgaas		return NULL;
537dc16f5f2ede8cc2acf8ac22857a7fecf3a4296c2Bjorn Helgaas	}
538dc16f5f2ede8cc2acf8ac22857a7fecf3a4296c2Bjorn Helgaas
539dc16f5f2ede8cc2acf8ac22857a7fecf3a4296c2Bjorn Helgaas	res = &pnp_res->res;
540dc16f5f2ede8cc2acf8ac22857a7fecf3a4296c2Bjorn Helgaas	res->flags = IORESOURCE_DMA | flags;
541dc16f5f2ede8cc2acf8ac22857a7fecf3a4296c2Bjorn Helgaas	res->start = dma;
542dc16f5f2ede8cc2acf8ac22857a7fecf3a4296c2Bjorn Helgaas	res->end = dma;
543dc16f5f2ede8cc2acf8ac22857a7fecf3a4296c2Bjorn Helgaas
544c1f3f2819667a238585c65bba96c8b16af39a442Bjorn Helgaas	dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
545dc16f5f2ede8cc2acf8ac22857a7fecf3a4296c2Bjorn Helgaas	return pnp_res;
546dc16f5f2ede8cc2acf8ac22857a7fecf3a4296c2Bjorn Helgaas}
547dc16f5f2ede8cc2acf8ac22857a7fecf3a4296c2Bjorn Helgaas
548cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaasstruct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
549cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas					 resource_size_t start,
550cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas					 resource_size_t end, int flags)
551cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas{
552cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas	struct pnp_resource *pnp_res;
553cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas	struct resource *res;
554cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas
555aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	pnp_res = pnp_new_resource(dev);
556cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas	if (!pnp_res) {
55725d39c39d82d062f4be685146abd054a3bafdf12Bjorn Helgaas		dev_err(&dev->dev, "can't add resource for IO %#llx-%#llx\n",
55825d39c39d82d062f4be685146abd054a3bafdf12Bjorn Helgaas			(unsigned long long) start,
55925d39c39d82d062f4be685146abd054a3bafdf12Bjorn Helgaas			(unsigned long long) end);
560cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas		return NULL;
561cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas	}
562cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas
563cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas	res = &pnp_res->res;
564cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas	res->flags = IORESOURCE_IO | flags;
565cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas	res->start = start;
566cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas	res->end = end;
567cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas
568c1f3f2819667a238585c65bba96c8b16af39a442Bjorn Helgaas	dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
569cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas	return pnp_res;
570cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas}
571cc8c2e308194f0997c718c7c735550ff06754d20Bjorn Helgaas
572d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaasstruct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
573d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas					  resource_size_t start,
574d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas					  resource_size_t end, int flags)
575d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas{
576d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas	struct pnp_resource *pnp_res;
577d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas	struct resource *res;
578d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas
579aee3ad815dd291a7193ab01da0f1a30c84d00061Bjorn Helgaas	pnp_res = pnp_new_resource(dev);
580d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas	if (!pnp_res) {
58125d39c39d82d062f4be685146abd054a3bafdf12Bjorn Helgaas		dev_err(&dev->dev, "can't add resource for MEM %#llx-%#llx\n",
58225d39c39d82d062f4be685146abd054a3bafdf12Bjorn Helgaas			(unsigned long long) start,
58325d39c39d82d062f4be685146abd054a3bafdf12Bjorn Helgaas			(unsigned long long) end);
584d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas		return NULL;
585d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas	}
586d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas
587d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas	res = &pnp_res->res;
588d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas	res->flags = IORESOURCE_MEM | flags;
589d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas	res->start = start;
590d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas	res->end = end;
591d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas
592c1f3f2819667a238585c65bba96c8b16af39a442Bjorn Helgaas	dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
593d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas	return pnp_res;
594d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas}
595d6180f36617953990bf90d4c1ff85b77e9995cd1Bjorn Helgaas
5967e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaasstruct pnp_resource *pnp_add_bus_resource(struct pnp_dev *dev,
5977e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas					  resource_size_t start,
5987e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas					  resource_size_t end)
5997e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas{
6007e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas	struct pnp_resource *pnp_res;
6017e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas	struct resource *res;
6027e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas
6037e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas	pnp_res = pnp_new_resource(dev);
6047e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas	if (!pnp_res) {
6057e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas		dev_err(&dev->dev, "can't add resource for BUS %#llx-%#llx\n",
6067e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas			(unsigned long long) start,
6077e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas			(unsigned long long) end);
6087e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas		return NULL;
6097e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas	}
6107e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas
6117e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas	res = &pnp_res->res;
6127e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas	res->flags = IORESOURCE_BUS;
6137e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas	res->start = start;
6147e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas	res->end = end;
6157e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas
616c1f3f2819667a238585c65bba96c8b16af39a442Bjorn Helgaas	dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
6177e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas	return pnp_res;
6187e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas}
6197e0e9c042790d4ea44c6a00ddaad8b8bbcc3f17fBjorn Helgaas
6201f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas/*
6211f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas * Determine whether the specified resource is a possible configuration
6221f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas * for this device.
6231f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas */
6241f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaasint pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t start,
6251f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas			resource_size_t size)
62657fd51a8be26921b56747ddd09d1d9e01c11c9e0Bjorn Helgaas{
6271f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	struct pnp_option *option;
62857fd51a8be26921b56747ddd09d1d9e01c11c9e0Bjorn Helgaas	struct pnp_port *port;
62957fd51a8be26921b56747ddd09d1d9e01c11c9e0Bjorn Helgaas	struct pnp_mem *mem;
63057fd51a8be26921b56747ddd09d1d9e01c11c9e0Bjorn Helgaas	struct pnp_irq *irq;
63157fd51a8be26921b56747ddd09d1d9e01c11c9e0Bjorn Helgaas	struct pnp_dma *dma;
63257fd51a8be26921b56747ddd09d1d9e01c11c9e0Bjorn Helgaas
6331f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas	list_for_each_entry(option, &dev->options, list) {
6341f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas		if (option->type != type)
6351f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas			continue;
63657fd51a8be26921b56747ddd09d1d9e01c11c9e0Bjorn Helgaas
6371f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas		switch (option->type) {
63857fd51a8be26921b56747ddd09d1d9e01c11c9e0Bjorn Helgaas		case IORESOURCE_IO:
6391f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas			port = &option->u.port;
6401f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas			if (port->min == start && port->size == size)
6411f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas				return 1;
64257fd51a8be26921b56747ddd09d1d9e01c11c9e0Bjorn Helgaas			break;
64357fd51a8be26921b56747ddd09d1d9e01c11c9e0Bjorn Helgaas		case IORESOURCE_MEM:
6441f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas			mem = &option->u.mem;
6451f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas			if (mem->min == start && mem->size == size)
6461f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas				return 1;
64757fd51a8be26921b56747ddd09d1d9e01c11c9e0Bjorn Helgaas			break;
64857fd51a8be26921b56747ddd09d1d9e01c11c9e0Bjorn Helgaas		case IORESOURCE_IRQ:
6491f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas			irq = &option->u.irq;
6501f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas			if (start < PNP_IRQ_NR &&
6511f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas			    test_bit(start, irq->map.bits))
6521f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas				return 1;
65357fd51a8be26921b56747ddd09d1d9e01c11c9e0Bjorn Helgaas			break;
65457fd51a8be26921b56747ddd09d1d9e01c11c9e0Bjorn Helgaas		case IORESOURCE_DMA:
6551f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas			dma = &option->u.dma;
6561f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas			if (dma->map & (1 << start))
6571f32ca31e7409d37c1b25e5f81840fb184380cdfBjorn Helgaas				return 1;
65857fd51a8be26921b56747ddd09d1d9e01c11c9e0Bjorn Helgaas			break;
65957fd51a8be26921b56747ddd09d1d9e01c11c9e0Bjorn Helgaas		}
66057fd51a8be26921b56747ddd09d1d9e01c11c9e0Bjorn Helgaas	}
66157fd51a8be26921b56747ddd09d1d9e01c11c9e0Bjorn Helgaas
66257fd51a8be26921b56747ddd09d1d9e01c11c9e0Bjorn Helgaas	return 0;
66357fd51a8be26921b56747ddd09d1d9e01c11c9e0Bjorn Helgaas}
66457fd51a8be26921b56747ddd09d1d9e01c11c9e0Bjorn HelgaasEXPORT_SYMBOL(pnp_possible_config);
66557fd51a8be26921b56747ddd09d1d9e01c11c9e0Bjorn Helgaas
6661b8e69662e1a086878bf930a6042daf7f8a076ccBjorn Helgaas <bjorn.helgaas atint pnp_range_reserved(resource_size_t start, resource_size_t end)
6671b8e69662e1a086878bf930a6042daf7f8a076ccBjorn Helgaas <bjorn.helgaas at{
6681b8e69662e1a086878bf930a6042daf7f8a076ccBjorn Helgaas <bjorn.helgaas at	struct pnp_dev *dev;
6691b8e69662e1a086878bf930a6042daf7f8a076ccBjorn Helgaas <bjorn.helgaas at	struct pnp_resource *pnp_res;
6701b8e69662e1a086878bf930a6042daf7f8a076ccBjorn Helgaas <bjorn.helgaas at	resource_size_t *dev_start, *dev_end;
6711b8e69662e1a086878bf930a6042daf7f8a076ccBjorn Helgaas <bjorn.helgaas at
6721b8e69662e1a086878bf930a6042daf7f8a076ccBjorn Helgaas <bjorn.helgaas at	pnp_for_each_dev(dev) {
6731b8e69662e1a086878bf930a6042daf7f8a076ccBjorn Helgaas <bjorn.helgaas at		list_for_each_entry(pnp_res, &dev->resources, list) {
6741b8e69662e1a086878bf930a6042daf7f8a076ccBjorn Helgaas <bjorn.helgaas at			dev_start = &pnp_res->res.start;
6751b8e69662e1a086878bf930a6042daf7f8a076ccBjorn Helgaas <bjorn.helgaas at			dev_end   = &pnp_res->res.end;
6761b8e69662e1a086878bf930a6042daf7f8a076ccBjorn Helgaas <bjorn.helgaas at			if (ranged_conflict(&start, &end, dev_start, dev_end))
6771b8e69662e1a086878bf930a6042daf7f8a076ccBjorn Helgaas <bjorn.helgaas at				return 1;
6781b8e69662e1a086878bf930a6042daf7f8a076ccBjorn Helgaas <bjorn.helgaas at		}
6791b8e69662e1a086878bf930a6042daf7f8a076ccBjorn Helgaas <bjorn.helgaas at	}
6801b8e69662e1a086878bf930a6042daf7f8a076ccBjorn Helgaas <bjorn.helgaas at	return 0;
6811b8e69662e1a086878bf930a6042daf7f8a076ccBjorn Helgaas <bjorn.helgaas at}
6821b8e69662e1a086878bf930a6042daf7f8a076ccBjorn Helgaas <bjorn.helgaas atEXPORT_SYMBOL(pnp_range_reserved);
6831b8e69662e1a086878bf930a6042daf7f8a076ccBjorn Helgaas <bjorn.helgaas at
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* format is: pnp_reserve_irq=irq1[,irq2] .... */
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init pnp_setup_reserve_irq(char *str)
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 16; i++)
6909dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		if (get_option(&str, &pnp_reserve_irq[i]) != 2)
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 1;
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds__setup("pnp_reserve_irq=", pnp_setup_reserve_irq);
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* format is: pnp_reserve_dma=dma1[,dma2] .... */
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init pnp_setup_reserve_dma(char *str)
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 8; i++)
7039dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		if (get_option(&str, &pnp_reserve_dma[i]) != 2)
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 1;
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds__setup("pnp_reserve_dma=", pnp_setup_reserve_dma);
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* format is: pnp_reserve_io=io1,size1[,io2,size2] .... */
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init pnp_setup_reserve_io(char *str)
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 16; i++)
7169dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		if (get_option(&str, &pnp_reserve_io[i]) != 2)
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 1;
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds__setup("pnp_reserve_io=", pnp_setup_reserve_io);
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* format is: pnp_reserve_mem=mem1,size1[,mem2,size2] .... */
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init pnp_setup_reserve_mem(char *str)
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 16; i++)
7299dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas		if (get_option(&str, &pnp_reserve_mem[i]) != 2)
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 1;
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds__setup("pnp_reserve_mem=", pnp_setup_reserve_mem);
735