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