xref: /OK3568_Linux_fs/kernel/drivers/pnp/resource.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * resource.c - Contains functions for registering and analyzing resource information
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz>
6*4882a593Smuzhiyun  * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
7*4882a593Smuzhiyun  * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
8*4882a593Smuzhiyun  *	Bjorn Helgaas <bjorn.helgaas@hp.com>
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <linux/module.h>
12*4882a593Smuzhiyun #include <linux/slab.h>
13*4882a593Smuzhiyun #include <linux/errno.h>
14*4882a593Smuzhiyun #include <linux/interrupt.h>
15*4882a593Smuzhiyun #include <linux/kernel.h>
16*4882a593Smuzhiyun #include <asm/io.h>
17*4882a593Smuzhiyun #include <asm/dma.h>
18*4882a593Smuzhiyun #include <asm/irq.h>
19*4882a593Smuzhiyun #include <linux/pci.h>
20*4882a593Smuzhiyun #include <linux/ioport.h>
21*4882a593Smuzhiyun #include <linux/init.h>
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #include <linux/pnp.h>
24*4882a593Smuzhiyun #include "base.h"
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun static int pnp_reserve_irq[16] = {[0 ... 15] = -1 };	/* reserve (don't use) some IRQ */
27*4882a593Smuzhiyun static int pnp_reserve_dma[8] = {[0 ... 7] = -1 };	/* reserve (don't use) some DMA */
28*4882a593Smuzhiyun static int pnp_reserve_io[16] = {[0 ... 15] = -1 };	/* reserve (don't use) some I/O region */
29*4882a593Smuzhiyun static int pnp_reserve_mem[16] = {[0 ... 15] = -1 };	/* reserve (don't use) some memory region */
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun /*
32*4882a593Smuzhiyun  * option registration
33*4882a593Smuzhiyun  */
34*4882a593Smuzhiyun 
pnp_build_option(struct pnp_dev * dev,unsigned long type,unsigned int option_flags)35*4882a593Smuzhiyun static struct pnp_option *pnp_build_option(struct pnp_dev *dev, unsigned long type,
36*4882a593Smuzhiyun 				    unsigned int option_flags)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	struct pnp_option *option;
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun 	option = kzalloc(sizeof(struct pnp_option), GFP_KERNEL);
41*4882a593Smuzhiyun 	if (!option)
42*4882a593Smuzhiyun 		return NULL;
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 	option->flags = option_flags;
45*4882a593Smuzhiyun 	option->type = type;
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun 	list_add_tail(&option->list, &dev->options);
48*4882a593Smuzhiyun 	return option;
49*4882a593Smuzhiyun }
50*4882a593Smuzhiyun 
pnp_register_irq_resource(struct pnp_dev * dev,unsigned int option_flags,pnp_irq_mask_t * map,unsigned char flags)51*4882a593Smuzhiyun int pnp_register_irq_resource(struct pnp_dev *dev, unsigned int option_flags,
52*4882a593Smuzhiyun 			      pnp_irq_mask_t *map, unsigned char flags)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun 	struct pnp_option *option;
55*4882a593Smuzhiyun 	struct pnp_irq *irq;
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	option = pnp_build_option(dev, IORESOURCE_IRQ, option_flags);
58*4882a593Smuzhiyun 	if (!option)
59*4882a593Smuzhiyun 		return -ENOMEM;
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun 	irq = &option->u.irq;
62*4882a593Smuzhiyun 	irq->map = *map;
63*4882a593Smuzhiyun 	irq->flags = flags;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun #ifdef CONFIG_PCI
66*4882a593Smuzhiyun 	{
67*4882a593Smuzhiyun 		int i;
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 		for (i = 0; i < 16; i++)
70*4882a593Smuzhiyun 			if (test_bit(i, irq->map.bits))
71*4882a593Smuzhiyun 				pcibios_penalize_isa_irq(i, 0);
72*4882a593Smuzhiyun 	}
73*4882a593Smuzhiyun #endif
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	dbg_pnp_show_option(dev, option);
76*4882a593Smuzhiyun 	return 0;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun 
pnp_register_dma_resource(struct pnp_dev * dev,unsigned int option_flags,unsigned char map,unsigned char flags)79*4882a593Smuzhiyun int pnp_register_dma_resource(struct pnp_dev *dev, unsigned int option_flags,
80*4882a593Smuzhiyun 			      unsigned char map, unsigned char flags)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun 	struct pnp_option *option;
83*4882a593Smuzhiyun 	struct pnp_dma *dma;
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	option = pnp_build_option(dev, IORESOURCE_DMA, option_flags);
86*4882a593Smuzhiyun 	if (!option)
87*4882a593Smuzhiyun 		return -ENOMEM;
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	dma = &option->u.dma;
90*4882a593Smuzhiyun 	dma->map = map;
91*4882a593Smuzhiyun 	dma->flags = flags;
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	dbg_pnp_show_option(dev, option);
94*4882a593Smuzhiyun 	return 0;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun 
pnp_register_port_resource(struct pnp_dev * dev,unsigned int option_flags,resource_size_t min,resource_size_t max,resource_size_t align,resource_size_t size,unsigned char flags)97*4882a593Smuzhiyun int pnp_register_port_resource(struct pnp_dev *dev, unsigned int option_flags,
98*4882a593Smuzhiyun 			       resource_size_t min, resource_size_t max,
99*4882a593Smuzhiyun 			       resource_size_t align, resource_size_t size,
100*4882a593Smuzhiyun 			       unsigned char flags)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun 	struct pnp_option *option;
103*4882a593Smuzhiyun 	struct pnp_port *port;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	option = pnp_build_option(dev, IORESOURCE_IO, option_flags);
106*4882a593Smuzhiyun 	if (!option)
107*4882a593Smuzhiyun 		return -ENOMEM;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	port = &option->u.port;
110*4882a593Smuzhiyun 	port->min = min;
111*4882a593Smuzhiyun 	port->max = max;
112*4882a593Smuzhiyun 	port->align = align;
113*4882a593Smuzhiyun 	port->size = size;
114*4882a593Smuzhiyun 	port->flags = flags;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	dbg_pnp_show_option(dev, option);
117*4882a593Smuzhiyun 	return 0;
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun 
pnp_register_mem_resource(struct pnp_dev * dev,unsigned int option_flags,resource_size_t min,resource_size_t max,resource_size_t align,resource_size_t size,unsigned char flags)120*4882a593Smuzhiyun int pnp_register_mem_resource(struct pnp_dev *dev, unsigned int option_flags,
121*4882a593Smuzhiyun 			      resource_size_t min, resource_size_t max,
122*4882a593Smuzhiyun 			      resource_size_t align, resource_size_t size,
123*4882a593Smuzhiyun 			      unsigned char flags)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun 	struct pnp_option *option;
126*4882a593Smuzhiyun 	struct pnp_mem *mem;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	option = pnp_build_option(dev, IORESOURCE_MEM, option_flags);
129*4882a593Smuzhiyun 	if (!option)
130*4882a593Smuzhiyun 		return -ENOMEM;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	mem = &option->u.mem;
133*4882a593Smuzhiyun 	mem->min = min;
134*4882a593Smuzhiyun 	mem->max = max;
135*4882a593Smuzhiyun 	mem->align = align;
136*4882a593Smuzhiyun 	mem->size = size;
137*4882a593Smuzhiyun 	mem->flags = flags;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	dbg_pnp_show_option(dev, option);
140*4882a593Smuzhiyun 	return 0;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun 
pnp_free_options(struct pnp_dev * dev)143*4882a593Smuzhiyun void pnp_free_options(struct pnp_dev *dev)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun 	struct pnp_option *option, *tmp;
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	list_for_each_entry_safe(option, tmp, &dev->options, list) {
148*4882a593Smuzhiyun 		list_del(&option->list);
149*4882a593Smuzhiyun 		kfree(option);
150*4882a593Smuzhiyun 	}
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun /*
154*4882a593Smuzhiyun  * resource validity checking
155*4882a593Smuzhiyun  */
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun #define length(start, end) (*(end) - *(start) + 1)
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun /* Two ranges conflict if one doesn't end before the other starts */
160*4882a593Smuzhiyun #define ranged_conflict(starta, enda, startb, endb) \
161*4882a593Smuzhiyun 	!((*(enda) < *(startb)) || (*(endb) < *(starta)))
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun #define cannot_compare(flags) \
164*4882a593Smuzhiyun ((flags) & IORESOURCE_DISABLED)
165*4882a593Smuzhiyun 
pnp_check_port(struct pnp_dev * dev,struct resource * res)166*4882a593Smuzhiyun int pnp_check_port(struct pnp_dev *dev, struct resource *res)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun 	int i;
169*4882a593Smuzhiyun 	struct pnp_dev *tdev;
170*4882a593Smuzhiyun 	struct resource *tres;
171*4882a593Smuzhiyun 	resource_size_t *port, *end, *tport, *tend;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	port = &res->start;
174*4882a593Smuzhiyun 	end = &res->end;
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	/* if the resource doesn't exist, don't complain about it */
177*4882a593Smuzhiyun 	if (cannot_compare(res->flags))
178*4882a593Smuzhiyun 		return 1;
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	/* check if the resource is already in use, skip if the
181*4882a593Smuzhiyun 	 * device is active because it itself may be in use */
182*4882a593Smuzhiyun 	if (!dev->active) {
183*4882a593Smuzhiyun 		if (!request_region(*port, length(port, end), "pnp"))
184*4882a593Smuzhiyun 			return 0;
185*4882a593Smuzhiyun 		release_region(*port, length(port, end));
186*4882a593Smuzhiyun 	}
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	/* check if the resource is reserved */
189*4882a593Smuzhiyun 	for (i = 0; i < 8; i++) {
190*4882a593Smuzhiyun 		int rport = pnp_reserve_io[i << 1];
191*4882a593Smuzhiyun 		int rend = pnp_reserve_io[(i << 1) + 1] + rport - 1;
192*4882a593Smuzhiyun 		if (ranged_conflict(port, end, &rport, &rend))
193*4882a593Smuzhiyun 			return 0;
194*4882a593Smuzhiyun 	}
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	/* check for internal conflicts */
197*4882a593Smuzhiyun 	for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
198*4882a593Smuzhiyun 		if (tres != res && tres->flags & IORESOURCE_IO) {
199*4882a593Smuzhiyun 			tport = &tres->start;
200*4882a593Smuzhiyun 			tend = &tres->end;
201*4882a593Smuzhiyun 			if (ranged_conflict(port, end, tport, tend))
202*4882a593Smuzhiyun 				return 0;
203*4882a593Smuzhiyun 		}
204*4882a593Smuzhiyun 	}
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	/* check for conflicts with other pnp devices */
207*4882a593Smuzhiyun 	pnp_for_each_dev(tdev) {
208*4882a593Smuzhiyun 		if (tdev == dev)
209*4882a593Smuzhiyun 			continue;
210*4882a593Smuzhiyun 		for (i = 0;
211*4882a593Smuzhiyun 		     (tres = pnp_get_resource(tdev, IORESOURCE_IO, i));
212*4882a593Smuzhiyun 		     i++) {
213*4882a593Smuzhiyun 			if (tres->flags & IORESOURCE_IO) {
214*4882a593Smuzhiyun 				if (cannot_compare(tres->flags))
215*4882a593Smuzhiyun 					continue;
216*4882a593Smuzhiyun 				if (tres->flags & IORESOURCE_WINDOW)
217*4882a593Smuzhiyun 					continue;
218*4882a593Smuzhiyun 				tport = &tres->start;
219*4882a593Smuzhiyun 				tend = &tres->end;
220*4882a593Smuzhiyun 				if (ranged_conflict(port, end, tport, tend))
221*4882a593Smuzhiyun 					return 0;
222*4882a593Smuzhiyun 			}
223*4882a593Smuzhiyun 		}
224*4882a593Smuzhiyun 	}
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	return 1;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun 
pnp_check_mem(struct pnp_dev * dev,struct resource * res)229*4882a593Smuzhiyun int pnp_check_mem(struct pnp_dev *dev, struct resource *res)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun 	int i;
232*4882a593Smuzhiyun 	struct pnp_dev *tdev;
233*4882a593Smuzhiyun 	struct resource *tres;
234*4882a593Smuzhiyun 	resource_size_t *addr, *end, *taddr, *tend;
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	addr = &res->start;
237*4882a593Smuzhiyun 	end = &res->end;
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	/* if the resource doesn't exist, don't complain about it */
240*4882a593Smuzhiyun 	if (cannot_compare(res->flags))
241*4882a593Smuzhiyun 		return 1;
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	/* check if the resource is already in use, skip if the
244*4882a593Smuzhiyun 	 * device is active because it itself may be in use */
245*4882a593Smuzhiyun 	if (!dev->active) {
246*4882a593Smuzhiyun 		if (!request_mem_region(*addr, length(addr, end), "pnp"))
247*4882a593Smuzhiyun 			return 0;
248*4882a593Smuzhiyun 		release_mem_region(*addr, length(addr, end));
249*4882a593Smuzhiyun 	}
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	/* check if the resource is reserved */
252*4882a593Smuzhiyun 	for (i = 0; i < 8; i++) {
253*4882a593Smuzhiyun 		int raddr = pnp_reserve_mem[i << 1];
254*4882a593Smuzhiyun 		int rend = pnp_reserve_mem[(i << 1) + 1] + raddr - 1;
255*4882a593Smuzhiyun 		if (ranged_conflict(addr, end, &raddr, &rend))
256*4882a593Smuzhiyun 			return 0;
257*4882a593Smuzhiyun 	}
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	/* check for internal conflicts */
260*4882a593Smuzhiyun 	for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
261*4882a593Smuzhiyun 		if (tres != res && tres->flags & IORESOURCE_MEM) {
262*4882a593Smuzhiyun 			taddr = &tres->start;
263*4882a593Smuzhiyun 			tend = &tres->end;
264*4882a593Smuzhiyun 			if (ranged_conflict(addr, end, taddr, tend))
265*4882a593Smuzhiyun 				return 0;
266*4882a593Smuzhiyun 		}
267*4882a593Smuzhiyun 	}
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 	/* check for conflicts with other pnp devices */
270*4882a593Smuzhiyun 	pnp_for_each_dev(tdev) {
271*4882a593Smuzhiyun 		if (tdev == dev)
272*4882a593Smuzhiyun 			continue;
273*4882a593Smuzhiyun 		for (i = 0;
274*4882a593Smuzhiyun 		     (tres = pnp_get_resource(tdev, IORESOURCE_MEM, i));
275*4882a593Smuzhiyun 		     i++) {
276*4882a593Smuzhiyun 			if (tres->flags & IORESOURCE_MEM) {
277*4882a593Smuzhiyun 				if (cannot_compare(tres->flags))
278*4882a593Smuzhiyun 					continue;
279*4882a593Smuzhiyun 				if (tres->flags & IORESOURCE_WINDOW)
280*4882a593Smuzhiyun 					continue;
281*4882a593Smuzhiyun 				taddr = &tres->start;
282*4882a593Smuzhiyun 				tend = &tres->end;
283*4882a593Smuzhiyun 				if (ranged_conflict(addr, end, taddr, tend))
284*4882a593Smuzhiyun 					return 0;
285*4882a593Smuzhiyun 			}
286*4882a593Smuzhiyun 		}
287*4882a593Smuzhiyun 	}
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	return 1;
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun 
pnp_test_handler(int irq,void * dev_id)292*4882a593Smuzhiyun static irqreturn_t pnp_test_handler(int irq, void *dev_id)
293*4882a593Smuzhiyun {
294*4882a593Smuzhiyun 	return IRQ_HANDLED;
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun #ifdef CONFIG_PCI
pci_dev_uses_irq(struct pnp_dev * pnp,struct pci_dev * pci,unsigned int irq)298*4882a593Smuzhiyun static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci,
299*4882a593Smuzhiyun 			    unsigned int irq)
300*4882a593Smuzhiyun {
301*4882a593Smuzhiyun 	u32 class;
302*4882a593Smuzhiyun 	u8 progif;
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	if (pci->irq == irq) {
305*4882a593Smuzhiyun 		pnp_dbg(&pnp->dev, "  device %s using irq %d\n",
306*4882a593Smuzhiyun 			pci_name(pci), irq);
307*4882a593Smuzhiyun 		return 1;
308*4882a593Smuzhiyun 	}
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	/*
311*4882a593Smuzhiyun 	 * See pci_setup_device() and ata_pci_sff_activate_host() for
312*4882a593Smuzhiyun 	 * similar IDE legacy detection.
313*4882a593Smuzhiyun 	 */
314*4882a593Smuzhiyun 	pci_read_config_dword(pci, PCI_CLASS_REVISION, &class);
315*4882a593Smuzhiyun 	class >>= 8;		/* discard revision ID */
316*4882a593Smuzhiyun 	progif = class & 0xff;
317*4882a593Smuzhiyun 	class >>= 8;
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	if (class == PCI_CLASS_STORAGE_IDE) {
320*4882a593Smuzhiyun 		/*
321*4882a593Smuzhiyun 		 * Unless both channels are native-PCI mode only,
322*4882a593Smuzhiyun 		 * treat the compatibility IRQs as busy.
323*4882a593Smuzhiyun 		 */
324*4882a593Smuzhiyun 		if ((progif & 0x5) != 0x5)
325*4882a593Smuzhiyun 			if (pci_get_legacy_ide_irq(pci, 0) == irq ||
326*4882a593Smuzhiyun 			    pci_get_legacy_ide_irq(pci, 1) == irq) {
327*4882a593Smuzhiyun 				pnp_dbg(&pnp->dev, "  legacy IDE device %s "
328*4882a593Smuzhiyun 					"using irq %d\n", pci_name(pci), irq);
329*4882a593Smuzhiyun 				return 1;
330*4882a593Smuzhiyun 			}
331*4882a593Smuzhiyun 	}
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	return 0;
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun #endif
336*4882a593Smuzhiyun 
pci_uses_irq(struct pnp_dev * pnp,unsigned int irq)337*4882a593Smuzhiyun static int pci_uses_irq(struct pnp_dev *pnp, unsigned int irq)
338*4882a593Smuzhiyun {
339*4882a593Smuzhiyun #ifdef CONFIG_PCI
340*4882a593Smuzhiyun 	struct pci_dev *pci = NULL;
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 	for_each_pci_dev(pci) {
343*4882a593Smuzhiyun 		if (pci_dev_uses_irq(pnp, pci, irq)) {
344*4882a593Smuzhiyun 			pci_dev_put(pci);
345*4882a593Smuzhiyun 			return 1;
346*4882a593Smuzhiyun 		}
347*4882a593Smuzhiyun 	}
348*4882a593Smuzhiyun #endif
349*4882a593Smuzhiyun 	return 0;
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun 
pnp_check_irq(struct pnp_dev * dev,struct resource * res)352*4882a593Smuzhiyun int pnp_check_irq(struct pnp_dev *dev, struct resource *res)
353*4882a593Smuzhiyun {
354*4882a593Smuzhiyun 	int i;
355*4882a593Smuzhiyun 	struct pnp_dev *tdev;
356*4882a593Smuzhiyun 	struct resource *tres;
357*4882a593Smuzhiyun 	resource_size_t *irq;
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	irq = &res->start;
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	/* if the resource doesn't exist, don't complain about it */
362*4882a593Smuzhiyun 	if (cannot_compare(res->flags))
363*4882a593Smuzhiyun 		return 1;
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	/* check if the resource is valid */
366*4882a593Smuzhiyun 	if (*irq > 15)
367*4882a593Smuzhiyun 		return 0;
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 	/* check if the resource is reserved */
370*4882a593Smuzhiyun 	for (i = 0; i < 16; i++) {
371*4882a593Smuzhiyun 		if (pnp_reserve_irq[i] == *irq)
372*4882a593Smuzhiyun 			return 0;
373*4882a593Smuzhiyun 	}
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	/* check for internal conflicts */
376*4882a593Smuzhiyun 	for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) {
377*4882a593Smuzhiyun 		if (tres != res && tres->flags & IORESOURCE_IRQ) {
378*4882a593Smuzhiyun 			if (tres->start == *irq)
379*4882a593Smuzhiyun 				return 0;
380*4882a593Smuzhiyun 		}
381*4882a593Smuzhiyun 	}
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 	/* check if the resource is being used by a pci device */
384*4882a593Smuzhiyun 	if (pci_uses_irq(dev, *irq))
385*4882a593Smuzhiyun 		return 0;
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	/* check if the resource is already in use, skip if the
388*4882a593Smuzhiyun 	 * device is active because it itself may be in use */
389*4882a593Smuzhiyun 	if (!dev->active) {
390*4882a593Smuzhiyun 		if (request_irq(*irq, pnp_test_handler,
391*4882a593Smuzhiyun 				IRQF_PROBE_SHARED, "pnp", NULL))
392*4882a593Smuzhiyun 			return 0;
393*4882a593Smuzhiyun 		free_irq(*irq, NULL);
394*4882a593Smuzhiyun 	}
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	/* check for conflicts with other pnp devices */
397*4882a593Smuzhiyun 	pnp_for_each_dev(tdev) {
398*4882a593Smuzhiyun 		if (tdev == dev)
399*4882a593Smuzhiyun 			continue;
400*4882a593Smuzhiyun 		for (i = 0;
401*4882a593Smuzhiyun 		     (tres = pnp_get_resource(tdev, IORESOURCE_IRQ, i));
402*4882a593Smuzhiyun 		     i++) {
403*4882a593Smuzhiyun 			if (tres->flags & IORESOURCE_IRQ) {
404*4882a593Smuzhiyun 				if (cannot_compare(tres->flags))
405*4882a593Smuzhiyun 					continue;
406*4882a593Smuzhiyun 				if (tres->start == *irq)
407*4882a593Smuzhiyun 					return 0;
408*4882a593Smuzhiyun 			}
409*4882a593Smuzhiyun 		}
410*4882a593Smuzhiyun 	}
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun 	return 1;
413*4882a593Smuzhiyun }
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun #ifdef CONFIG_ISA_DMA_API
pnp_check_dma(struct pnp_dev * dev,struct resource * res)416*4882a593Smuzhiyun int pnp_check_dma(struct pnp_dev *dev, struct resource *res)
417*4882a593Smuzhiyun {
418*4882a593Smuzhiyun 	int i;
419*4882a593Smuzhiyun 	struct pnp_dev *tdev;
420*4882a593Smuzhiyun 	struct resource *tres;
421*4882a593Smuzhiyun 	resource_size_t *dma;
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	dma = &res->start;
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	/* if the resource doesn't exist, don't complain about it */
426*4882a593Smuzhiyun 	if (cannot_compare(res->flags))
427*4882a593Smuzhiyun 		return 1;
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun 	/* check if the resource is valid */
430*4882a593Smuzhiyun 	if (*dma == 4 || *dma > 7)
431*4882a593Smuzhiyun 		return 0;
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	/* check if the resource is reserved */
434*4882a593Smuzhiyun 	for (i = 0; i < 8; i++) {
435*4882a593Smuzhiyun 		if (pnp_reserve_dma[i] == *dma)
436*4882a593Smuzhiyun 			return 0;
437*4882a593Smuzhiyun 	}
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 	/* check for internal conflicts */
440*4882a593Smuzhiyun 	for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) {
441*4882a593Smuzhiyun 		if (tres != res && tres->flags & IORESOURCE_DMA) {
442*4882a593Smuzhiyun 			if (tres->start == *dma)
443*4882a593Smuzhiyun 				return 0;
444*4882a593Smuzhiyun 		}
445*4882a593Smuzhiyun 	}
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	/* check if the resource is already in use, skip if the
448*4882a593Smuzhiyun 	 * device is active because it itself may be in use */
449*4882a593Smuzhiyun 	if (!dev->active) {
450*4882a593Smuzhiyun 		if (request_dma(*dma, "pnp"))
451*4882a593Smuzhiyun 			return 0;
452*4882a593Smuzhiyun 		free_dma(*dma);
453*4882a593Smuzhiyun 	}
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 	/* check for conflicts with other pnp devices */
456*4882a593Smuzhiyun 	pnp_for_each_dev(tdev) {
457*4882a593Smuzhiyun 		if (tdev == dev)
458*4882a593Smuzhiyun 			continue;
459*4882a593Smuzhiyun 		for (i = 0;
460*4882a593Smuzhiyun 		     (tres = pnp_get_resource(tdev, IORESOURCE_DMA, i));
461*4882a593Smuzhiyun 		     i++) {
462*4882a593Smuzhiyun 			if (tres->flags & IORESOURCE_DMA) {
463*4882a593Smuzhiyun 				if (cannot_compare(tres->flags))
464*4882a593Smuzhiyun 					continue;
465*4882a593Smuzhiyun 				if (tres->start == *dma)
466*4882a593Smuzhiyun 					return 0;
467*4882a593Smuzhiyun 			}
468*4882a593Smuzhiyun 		}
469*4882a593Smuzhiyun 	}
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun 	return 1;
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun #endif /* CONFIG_ISA_DMA_API */
474*4882a593Smuzhiyun 
pnp_resource_type(struct resource * res)475*4882a593Smuzhiyun unsigned long pnp_resource_type(struct resource *res)
476*4882a593Smuzhiyun {
477*4882a593Smuzhiyun 	return res->flags & (IORESOURCE_IO  | IORESOURCE_MEM |
478*4882a593Smuzhiyun 			     IORESOURCE_IRQ | IORESOURCE_DMA |
479*4882a593Smuzhiyun 			     IORESOURCE_BUS);
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun 
pnp_get_resource(struct pnp_dev * dev,unsigned long type,unsigned int num)482*4882a593Smuzhiyun struct resource *pnp_get_resource(struct pnp_dev *dev,
483*4882a593Smuzhiyun 				  unsigned long type, unsigned int num)
484*4882a593Smuzhiyun {
485*4882a593Smuzhiyun 	struct pnp_resource *pnp_res;
486*4882a593Smuzhiyun 	struct resource *res;
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 	list_for_each_entry(pnp_res, &dev->resources, list) {
489*4882a593Smuzhiyun 		res = &pnp_res->res;
490*4882a593Smuzhiyun 		if (pnp_resource_type(res) == type && num-- == 0)
491*4882a593Smuzhiyun 			return res;
492*4882a593Smuzhiyun 	}
493*4882a593Smuzhiyun 	return NULL;
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun EXPORT_SYMBOL(pnp_get_resource);
496*4882a593Smuzhiyun 
pnp_new_resource(struct pnp_dev * dev)497*4882a593Smuzhiyun static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev)
498*4882a593Smuzhiyun {
499*4882a593Smuzhiyun 	struct pnp_resource *pnp_res;
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun 	pnp_res = kzalloc(sizeof(struct pnp_resource), GFP_KERNEL);
502*4882a593Smuzhiyun 	if (!pnp_res)
503*4882a593Smuzhiyun 		return NULL;
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	list_add_tail(&pnp_res->list, &dev->resources);
506*4882a593Smuzhiyun 	return pnp_res;
507*4882a593Smuzhiyun }
508*4882a593Smuzhiyun 
pnp_add_resource(struct pnp_dev * dev,struct resource * res)509*4882a593Smuzhiyun struct pnp_resource *pnp_add_resource(struct pnp_dev *dev,
510*4882a593Smuzhiyun 				      struct resource *res)
511*4882a593Smuzhiyun {
512*4882a593Smuzhiyun 	struct pnp_resource *pnp_res;
513*4882a593Smuzhiyun 
514*4882a593Smuzhiyun 	pnp_res = pnp_new_resource(dev);
515*4882a593Smuzhiyun 	if (!pnp_res) {
516*4882a593Smuzhiyun 		dev_err(&dev->dev, "can't add resource %pR\n", res);
517*4882a593Smuzhiyun 		return NULL;
518*4882a593Smuzhiyun 	}
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun 	pnp_res->res = *res;
521*4882a593Smuzhiyun 	pnp_res->res.name = dev->name;
522*4882a593Smuzhiyun 	dev_dbg(&dev->dev, "%pR\n", res);
523*4882a593Smuzhiyun 	return pnp_res;
524*4882a593Smuzhiyun }
525*4882a593Smuzhiyun 
pnp_add_irq_resource(struct pnp_dev * dev,int irq,int flags)526*4882a593Smuzhiyun struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
527*4882a593Smuzhiyun 					  int flags)
528*4882a593Smuzhiyun {
529*4882a593Smuzhiyun 	struct pnp_resource *pnp_res;
530*4882a593Smuzhiyun 	struct resource *res;
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 	pnp_res = pnp_new_resource(dev);
533*4882a593Smuzhiyun 	if (!pnp_res) {
534*4882a593Smuzhiyun 		dev_err(&dev->dev, "can't add resource for IRQ %d\n", irq);
535*4882a593Smuzhiyun 		return NULL;
536*4882a593Smuzhiyun 	}
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun 	res = &pnp_res->res;
539*4882a593Smuzhiyun 	res->flags = IORESOURCE_IRQ | flags;
540*4882a593Smuzhiyun 	res->start = irq;
541*4882a593Smuzhiyun 	res->end = irq;
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun 	dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
544*4882a593Smuzhiyun 	return pnp_res;
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun 
pnp_add_dma_resource(struct pnp_dev * dev,int dma,int flags)547*4882a593Smuzhiyun struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
548*4882a593Smuzhiyun 					  int flags)
549*4882a593Smuzhiyun {
550*4882a593Smuzhiyun 	struct pnp_resource *pnp_res;
551*4882a593Smuzhiyun 	struct resource *res;
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 	pnp_res = pnp_new_resource(dev);
554*4882a593Smuzhiyun 	if (!pnp_res) {
555*4882a593Smuzhiyun 		dev_err(&dev->dev, "can't add resource for DMA %d\n", dma);
556*4882a593Smuzhiyun 		return NULL;
557*4882a593Smuzhiyun 	}
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun 	res = &pnp_res->res;
560*4882a593Smuzhiyun 	res->flags = IORESOURCE_DMA | flags;
561*4882a593Smuzhiyun 	res->start = dma;
562*4882a593Smuzhiyun 	res->end = dma;
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 	dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
565*4882a593Smuzhiyun 	return pnp_res;
566*4882a593Smuzhiyun }
567*4882a593Smuzhiyun 
pnp_add_io_resource(struct pnp_dev * dev,resource_size_t start,resource_size_t end,int flags)568*4882a593Smuzhiyun struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
569*4882a593Smuzhiyun 					 resource_size_t start,
570*4882a593Smuzhiyun 					 resource_size_t end, int flags)
571*4882a593Smuzhiyun {
572*4882a593Smuzhiyun 	struct pnp_resource *pnp_res;
573*4882a593Smuzhiyun 	struct resource *res;
574*4882a593Smuzhiyun 
575*4882a593Smuzhiyun 	pnp_res = pnp_new_resource(dev);
576*4882a593Smuzhiyun 	if (!pnp_res) {
577*4882a593Smuzhiyun 		dev_err(&dev->dev, "can't add resource for IO %#llx-%#llx\n",
578*4882a593Smuzhiyun 			(unsigned long long) start,
579*4882a593Smuzhiyun 			(unsigned long long) end);
580*4882a593Smuzhiyun 		return NULL;
581*4882a593Smuzhiyun 	}
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun 	res = &pnp_res->res;
584*4882a593Smuzhiyun 	res->flags = IORESOURCE_IO | flags;
585*4882a593Smuzhiyun 	res->start = start;
586*4882a593Smuzhiyun 	res->end = end;
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun 	dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
589*4882a593Smuzhiyun 	return pnp_res;
590*4882a593Smuzhiyun }
591*4882a593Smuzhiyun 
pnp_add_mem_resource(struct pnp_dev * dev,resource_size_t start,resource_size_t end,int flags)592*4882a593Smuzhiyun struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
593*4882a593Smuzhiyun 					  resource_size_t start,
594*4882a593Smuzhiyun 					  resource_size_t end, int flags)
595*4882a593Smuzhiyun {
596*4882a593Smuzhiyun 	struct pnp_resource *pnp_res;
597*4882a593Smuzhiyun 	struct resource *res;
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun 	pnp_res = pnp_new_resource(dev);
600*4882a593Smuzhiyun 	if (!pnp_res) {
601*4882a593Smuzhiyun 		dev_err(&dev->dev, "can't add resource for MEM %#llx-%#llx\n",
602*4882a593Smuzhiyun 			(unsigned long long) start,
603*4882a593Smuzhiyun 			(unsigned long long) end);
604*4882a593Smuzhiyun 		return NULL;
605*4882a593Smuzhiyun 	}
606*4882a593Smuzhiyun 
607*4882a593Smuzhiyun 	res = &pnp_res->res;
608*4882a593Smuzhiyun 	res->flags = IORESOURCE_MEM | flags;
609*4882a593Smuzhiyun 	res->start = start;
610*4882a593Smuzhiyun 	res->end = end;
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun 	dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
613*4882a593Smuzhiyun 	return pnp_res;
614*4882a593Smuzhiyun }
615*4882a593Smuzhiyun 
pnp_add_bus_resource(struct pnp_dev * dev,resource_size_t start,resource_size_t end)616*4882a593Smuzhiyun struct pnp_resource *pnp_add_bus_resource(struct pnp_dev *dev,
617*4882a593Smuzhiyun 					  resource_size_t start,
618*4882a593Smuzhiyun 					  resource_size_t end)
619*4882a593Smuzhiyun {
620*4882a593Smuzhiyun 	struct pnp_resource *pnp_res;
621*4882a593Smuzhiyun 	struct resource *res;
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 	pnp_res = pnp_new_resource(dev);
624*4882a593Smuzhiyun 	if (!pnp_res) {
625*4882a593Smuzhiyun 		dev_err(&dev->dev, "can't add resource for BUS %#llx-%#llx\n",
626*4882a593Smuzhiyun 			(unsigned long long) start,
627*4882a593Smuzhiyun 			(unsigned long long) end);
628*4882a593Smuzhiyun 		return NULL;
629*4882a593Smuzhiyun 	}
630*4882a593Smuzhiyun 
631*4882a593Smuzhiyun 	res = &pnp_res->res;
632*4882a593Smuzhiyun 	res->flags = IORESOURCE_BUS;
633*4882a593Smuzhiyun 	res->start = start;
634*4882a593Smuzhiyun 	res->end = end;
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun 	dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
637*4882a593Smuzhiyun 	return pnp_res;
638*4882a593Smuzhiyun }
639*4882a593Smuzhiyun 
640*4882a593Smuzhiyun /*
641*4882a593Smuzhiyun  * Determine whether the specified resource is a possible configuration
642*4882a593Smuzhiyun  * for this device.
643*4882a593Smuzhiyun  */
pnp_possible_config(struct pnp_dev * dev,int type,resource_size_t start,resource_size_t size)644*4882a593Smuzhiyun int pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t start,
645*4882a593Smuzhiyun 			resource_size_t size)
646*4882a593Smuzhiyun {
647*4882a593Smuzhiyun 	struct pnp_option *option;
648*4882a593Smuzhiyun 	struct pnp_port *port;
649*4882a593Smuzhiyun 	struct pnp_mem *mem;
650*4882a593Smuzhiyun 	struct pnp_irq *irq;
651*4882a593Smuzhiyun 	struct pnp_dma *dma;
652*4882a593Smuzhiyun 
653*4882a593Smuzhiyun 	list_for_each_entry(option, &dev->options, list) {
654*4882a593Smuzhiyun 		if (option->type != type)
655*4882a593Smuzhiyun 			continue;
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun 		switch (option->type) {
658*4882a593Smuzhiyun 		case IORESOURCE_IO:
659*4882a593Smuzhiyun 			port = &option->u.port;
660*4882a593Smuzhiyun 			if (port->min == start && port->size == size)
661*4882a593Smuzhiyun 				return 1;
662*4882a593Smuzhiyun 			break;
663*4882a593Smuzhiyun 		case IORESOURCE_MEM:
664*4882a593Smuzhiyun 			mem = &option->u.mem;
665*4882a593Smuzhiyun 			if (mem->min == start && mem->size == size)
666*4882a593Smuzhiyun 				return 1;
667*4882a593Smuzhiyun 			break;
668*4882a593Smuzhiyun 		case IORESOURCE_IRQ:
669*4882a593Smuzhiyun 			irq = &option->u.irq;
670*4882a593Smuzhiyun 			if (start < PNP_IRQ_NR &&
671*4882a593Smuzhiyun 			    test_bit(start, irq->map.bits))
672*4882a593Smuzhiyun 				return 1;
673*4882a593Smuzhiyun 			break;
674*4882a593Smuzhiyun 		case IORESOURCE_DMA:
675*4882a593Smuzhiyun 			dma = &option->u.dma;
676*4882a593Smuzhiyun 			if (dma->map & (1 << start))
677*4882a593Smuzhiyun 				return 1;
678*4882a593Smuzhiyun 			break;
679*4882a593Smuzhiyun 		}
680*4882a593Smuzhiyun 	}
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	return 0;
683*4882a593Smuzhiyun }
684*4882a593Smuzhiyun EXPORT_SYMBOL(pnp_possible_config);
685*4882a593Smuzhiyun 
pnp_range_reserved(resource_size_t start,resource_size_t end)686*4882a593Smuzhiyun int pnp_range_reserved(resource_size_t start, resource_size_t end)
687*4882a593Smuzhiyun {
688*4882a593Smuzhiyun 	struct pnp_dev *dev;
689*4882a593Smuzhiyun 	struct pnp_resource *pnp_res;
690*4882a593Smuzhiyun 	resource_size_t *dev_start, *dev_end;
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun 	pnp_for_each_dev(dev) {
693*4882a593Smuzhiyun 		list_for_each_entry(pnp_res, &dev->resources, list) {
694*4882a593Smuzhiyun 			dev_start = &pnp_res->res.start;
695*4882a593Smuzhiyun 			dev_end   = &pnp_res->res.end;
696*4882a593Smuzhiyun 			if (ranged_conflict(&start, &end, dev_start, dev_end))
697*4882a593Smuzhiyun 				return 1;
698*4882a593Smuzhiyun 		}
699*4882a593Smuzhiyun 	}
700*4882a593Smuzhiyun 	return 0;
701*4882a593Smuzhiyun }
702*4882a593Smuzhiyun EXPORT_SYMBOL(pnp_range_reserved);
703*4882a593Smuzhiyun 
704*4882a593Smuzhiyun /* format is: pnp_reserve_irq=irq1[,irq2] .... */
pnp_setup_reserve_irq(char * str)705*4882a593Smuzhiyun static int __init pnp_setup_reserve_irq(char *str)
706*4882a593Smuzhiyun {
707*4882a593Smuzhiyun 	int i;
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun 	for (i = 0; i < 16; i++)
710*4882a593Smuzhiyun 		if (get_option(&str, &pnp_reserve_irq[i]) != 2)
711*4882a593Smuzhiyun 			break;
712*4882a593Smuzhiyun 	return 1;
713*4882a593Smuzhiyun }
714*4882a593Smuzhiyun 
715*4882a593Smuzhiyun __setup("pnp_reserve_irq=", pnp_setup_reserve_irq);
716*4882a593Smuzhiyun 
717*4882a593Smuzhiyun /* format is: pnp_reserve_dma=dma1[,dma2] .... */
pnp_setup_reserve_dma(char * str)718*4882a593Smuzhiyun static int __init pnp_setup_reserve_dma(char *str)
719*4882a593Smuzhiyun {
720*4882a593Smuzhiyun 	int i;
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun 	for (i = 0; i < 8; i++)
723*4882a593Smuzhiyun 		if (get_option(&str, &pnp_reserve_dma[i]) != 2)
724*4882a593Smuzhiyun 			break;
725*4882a593Smuzhiyun 	return 1;
726*4882a593Smuzhiyun }
727*4882a593Smuzhiyun 
728*4882a593Smuzhiyun __setup("pnp_reserve_dma=", pnp_setup_reserve_dma);
729*4882a593Smuzhiyun 
730*4882a593Smuzhiyun /* format is: pnp_reserve_io=io1,size1[,io2,size2] .... */
pnp_setup_reserve_io(char * str)731*4882a593Smuzhiyun static int __init pnp_setup_reserve_io(char *str)
732*4882a593Smuzhiyun {
733*4882a593Smuzhiyun 	int i;
734*4882a593Smuzhiyun 
735*4882a593Smuzhiyun 	for (i = 0; i < 16; i++)
736*4882a593Smuzhiyun 		if (get_option(&str, &pnp_reserve_io[i]) != 2)
737*4882a593Smuzhiyun 			break;
738*4882a593Smuzhiyun 	return 1;
739*4882a593Smuzhiyun }
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun __setup("pnp_reserve_io=", pnp_setup_reserve_io);
742*4882a593Smuzhiyun 
743*4882a593Smuzhiyun /* format is: pnp_reserve_mem=mem1,size1[,mem2,size2] .... */
pnp_setup_reserve_mem(char * str)744*4882a593Smuzhiyun static int __init pnp_setup_reserve_mem(char *str)
745*4882a593Smuzhiyun {
746*4882a593Smuzhiyun 	int i;
747*4882a593Smuzhiyun 
748*4882a593Smuzhiyun 	for (i = 0; i < 16; i++)
749*4882a593Smuzhiyun 		if (get_option(&str, &pnp_reserve_mem[i]) != 2)
750*4882a593Smuzhiyun 			break;
751*4882a593Smuzhiyun 	return 1;
752*4882a593Smuzhiyun }
753*4882a593Smuzhiyun 
754*4882a593Smuzhiyun __setup("pnp_reserve_mem=", pnp_setup_reserve_mem);
755