Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * resource.c - Contains functions for registering and analyzing resource information
0004  *
0005  * based on isapnp.c resource management (c) Jaroslav Kysela <perex@perex.cz>
0006  * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
0007  * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
0008  *  Bjorn Helgaas <bjorn.helgaas@hp.com>
0009  */
0010 
0011 #include <linux/module.h>
0012 #include <linux/slab.h>
0013 #include <linux/errno.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/kernel.h>
0016 #include <asm/io.h>
0017 #include <asm/dma.h>
0018 #include <asm/irq.h>
0019 #include <linux/pci.h>
0020 #include <linux/libata.h>
0021 #include <linux/ioport.h>
0022 #include <linux/init.h>
0023 
0024 #include <linux/pnp.h>
0025 #include "base.h"
0026 
0027 static int pnp_reserve_irq[16] = {[0 ... 15] = -1 };    /* reserve (don't use) some IRQ */
0028 static int pnp_reserve_dma[8] = {[0 ... 7] = -1 };  /* reserve (don't use) some DMA */
0029 static int pnp_reserve_io[16] = {[0 ... 15] = -1 }; /* reserve (don't use) some I/O region */
0030 static int pnp_reserve_mem[16] = {[0 ... 15] = -1 };    /* reserve (don't use) some memory region */
0031 
0032 /*
0033  * option registration
0034  */
0035 
0036 static struct pnp_option *pnp_build_option(struct pnp_dev *dev, unsigned long type,
0037                     unsigned int option_flags)
0038 {
0039     struct pnp_option *option;
0040 
0041     option = kzalloc(sizeof(struct pnp_option), GFP_KERNEL);
0042     if (!option)
0043         return NULL;
0044 
0045     option->flags = option_flags;
0046     option->type = type;
0047 
0048     list_add_tail(&option->list, &dev->options);
0049     return option;
0050 }
0051 
0052 int pnp_register_irq_resource(struct pnp_dev *dev, unsigned int option_flags,
0053                   pnp_irq_mask_t *map, unsigned char flags)
0054 {
0055     struct pnp_option *option;
0056     struct pnp_irq *irq;
0057 
0058     option = pnp_build_option(dev, IORESOURCE_IRQ, option_flags);
0059     if (!option)
0060         return -ENOMEM;
0061 
0062     irq = &option->u.irq;
0063     irq->map = *map;
0064     irq->flags = flags;
0065 
0066 #ifdef CONFIG_PCI
0067     {
0068         int i;
0069 
0070         for (i = 0; i < 16; i++)
0071             if (test_bit(i, irq->map.bits))
0072                 pcibios_penalize_isa_irq(i, 0);
0073     }
0074 #endif
0075 
0076     dbg_pnp_show_option(dev, option);
0077     return 0;
0078 }
0079 
0080 int pnp_register_dma_resource(struct pnp_dev *dev, unsigned int option_flags,
0081                   unsigned char map, unsigned char flags)
0082 {
0083     struct pnp_option *option;
0084     struct pnp_dma *dma;
0085 
0086     option = pnp_build_option(dev, IORESOURCE_DMA, option_flags);
0087     if (!option)
0088         return -ENOMEM;
0089 
0090     dma = &option->u.dma;
0091     dma->map = map;
0092     dma->flags = flags;
0093 
0094     dbg_pnp_show_option(dev, option);
0095     return 0;
0096 }
0097 
0098 int pnp_register_port_resource(struct pnp_dev *dev, unsigned int option_flags,
0099                    resource_size_t min, resource_size_t max,
0100                    resource_size_t align, resource_size_t size,
0101                    unsigned char flags)
0102 {
0103     struct pnp_option *option;
0104     struct pnp_port *port;
0105 
0106     option = pnp_build_option(dev, IORESOURCE_IO, option_flags);
0107     if (!option)
0108         return -ENOMEM;
0109 
0110     port = &option->u.port;
0111     port->min = min;
0112     port->max = max;
0113     port->align = align;
0114     port->size = size;
0115     port->flags = flags;
0116 
0117     dbg_pnp_show_option(dev, option);
0118     return 0;
0119 }
0120 
0121 int pnp_register_mem_resource(struct pnp_dev *dev, unsigned int option_flags,
0122                   resource_size_t min, resource_size_t max,
0123                   resource_size_t align, resource_size_t size,
0124                   unsigned char flags)
0125 {
0126     struct pnp_option *option;
0127     struct pnp_mem *mem;
0128 
0129     option = pnp_build_option(dev, IORESOURCE_MEM, option_flags);
0130     if (!option)
0131         return -ENOMEM;
0132 
0133     mem = &option->u.mem;
0134     mem->min = min;
0135     mem->max = max;
0136     mem->align = align;
0137     mem->size = size;
0138     mem->flags = flags;
0139 
0140     dbg_pnp_show_option(dev, option);
0141     return 0;
0142 }
0143 
0144 void pnp_free_options(struct pnp_dev *dev)
0145 {
0146     struct pnp_option *option, *tmp;
0147 
0148     list_for_each_entry_safe(option, tmp, &dev->options, list) {
0149         list_del(&option->list);
0150         kfree(option);
0151     }
0152 }
0153 
0154 /*
0155  * resource validity checking
0156  */
0157 
0158 #define length(start, end) (*(end) - *(start) + 1)
0159 
0160 /* Two ranges conflict if one doesn't end before the other starts */
0161 #define ranged_conflict(starta, enda, startb, endb) \
0162     !((*(enda) < *(startb)) || (*(endb) < *(starta)))
0163 
0164 #define cannot_compare(flags) \
0165 ((flags) & IORESOURCE_DISABLED)
0166 
0167 int pnp_check_port(struct pnp_dev *dev, struct resource *res)
0168 {
0169     int i;
0170     struct pnp_dev *tdev;
0171     struct resource *tres;
0172     resource_size_t *port, *end, *tport, *tend;
0173 
0174     port = &res->start;
0175     end = &res->end;
0176 
0177     /* if the resource doesn't exist, don't complain about it */
0178     if (cannot_compare(res->flags))
0179         return 1;
0180 
0181     /* check if the resource is already in use, skip if the
0182      * device is active because it itself may be in use */
0183     if (!dev->active) {
0184         if (!request_region(*port, length(port, end), "pnp"))
0185             return 0;
0186         release_region(*port, length(port, end));
0187     }
0188 
0189     /* check if the resource is reserved */
0190     for (i = 0; i < 8; i++) {
0191         int rport = pnp_reserve_io[i << 1];
0192         int rend = pnp_reserve_io[(i << 1) + 1] + rport - 1;
0193         if (ranged_conflict(port, end, &rport, &rend))
0194             return 0;
0195     }
0196 
0197     /* check for internal conflicts */
0198     for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
0199         if (tres != res && tres->flags & IORESOURCE_IO) {
0200             tport = &tres->start;
0201             tend = &tres->end;
0202             if (ranged_conflict(port, end, tport, tend))
0203                 return 0;
0204         }
0205     }
0206 
0207     /* check for conflicts with other pnp devices */
0208     pnp_for_each_dev(tdev) {
0209         if (tdev == dev)
0210             continue;
0211         for (i = 0;
0212              (tres = pnp_get_resource(tdev, IORESOURCE_IO, i));
0213              i++) {
0214             if (tres->flags & IORESOURCE_IO) {
0215                 if (cannot_compare(tres->flags))
0216                     continue;
0217                 if (tres->flags & IORESOURCE_WINDOW)
0218                     continue;
0219                 tport = &tres->start;
0220                 tend = &tres->end;
0221                 if (ranged_conflict(port, end, tport, tend))
0222                     return 0;
0223             }
0224         }
0225     }
0226 
0227     return 1;
0228 }
0229 
0230 int pnp_check_mem(struct pnp_dev *dev, struct resource *res)
0231 {
0232     int i;
0233     struct pnp_dev *tdev;
0234     struct resource *tres;
0235     resource_size_t *addr, *end, *taddr, *tend;
0236 
0237     addr = &res->start;
0238     end = &res->end;
0239 
0240     /* if the resource doesn't exist, don't complain about it */
0241     if (cannot_compare(res->flags))
0242         return 1;
0243 
0244     /* check if the resource is already in use, skip if the
0245      * device is active because it itself may be in use */
0246     if (!dev->active) {
0247         if (!request_mem_region(*addr, length(addr, end), "pnp"))
0248             return 0;
0249         release_mem_region(*addr, length(addr, end));
0250     }
0251 
0252     /* check if the resource is reserved */
0253     for (i = 0; i < 8; i++) {
0254         int raddr = pnp_reserve_mem[i << 1];
0255         int rend = pnp_reserve_mem[(i << 1) + 1] + raddr - 1;
0256         if (ranged_conflict(addr, end, &raddr, &rend))
0257             return 0;
0258     }
0259 
0260     /* check for internal conflicts */
0261     for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
0262         if (tres != res && tres->flags & IORESOURCE_MEM) {
0263             taddr = &tres->start;
0264             tend = &tres->end;
0265             if (ranged_conflict(addr, end, taddr, tend))
0266                 return 0;
0267         }
0268     }
0269 
0270     /* check for conflicts with other pnp devices */
0271     pnp_for_each_dev(tdev) {
0272         if (tdev == dev)
0273             continue;
0274         for (i = 0;
0275              (tres = pnp_get_resource(tdev, IORESOURCE_MEM, i));
0276              i++) {
0277             if (tres->flags & IORESOURCE_MEM) {
0278                 if (cannot_compare(tres->flags))
0279                     continue;
0280                 if (tres->flags & IORESOURCE_WINDOW)
0281                     continue;
0282                 taddr = &tres->start;
0283                 tend = &tres->end;
0284                 if (ranged_conflict(addr, end, taddr, tend))
0285                     return 0;
0286             }
0287         }
0288     }
0289 
0290     return 1;
0291 }
0292 
0293 static irqreturn_t pnp_test_handler(int irq, void *dev_id)
0294 {
0295     return IRQ_HANDLED;
0296 }
0297 
0298 #ifdef CONFIG_PCI
0299 static int pci_dev_uses_irq(struct pnp_dev *pnp, struct pci_dev *pci,
0300                 unsigned int irq)
0301 {
0302     u32 class;
0303     u8 progif;
0304 
0305     if (pci->irq == irq) {
0306         pnp_dbg(&pnp->dev, "  device %s using irq %d\n",
0307             pci_name(pci), irq);
0308         return 1;
0309     }
0310 
0311     /*
0312      * See pci_setup_device() and ata_pci_sff_activate_host() for
0313      * similar IDE legacy detection.
0314      */
0315     pci_read_config_dword(pci, PCI_CLASS_REVISION, &class);
0316     class >>= 8;        /* discard revision ID */
0317     progif = class & 0xff;
0318     class >>= 8;
0319 
0320     if (class == PCI_CLASS_STORAGE_IDE) {
0321         /*
0322          * Unless both channels are native-PCI mode only,
0323          * treat the compatibility IRQs as busy.
0324          */
0325         if ((progif & 0x5) != 0x5)
0326             if (ATA_PRIMARY_IRQ(pci) == irq ||
0327                 ATA_SECONDARY_IRQ(pci) == irq) {
0328                 pnp_dbg(&pnp->dev, "  legacy IDE device %s "
0329                     "using irq %d\n", pci_name(pci), irq);
0330                 return 1;
0331             }
0332     }
0333 
0334     return 0;
0335 }
0336 #endif
0337 
0338 static int pci_uses_irq(struct pnp_dev *pnp, unsigned int irq)
0339 {
0340 #ifdef CONFIG_PCI
0341     struct pci_dev *pci = NULL;
0342 
0343     for_each_pci_dev(pci) {
0344         if (pci_dev_uses_irq(pnp, pci, irq)) {
0345             pci_dev_put(pci);
0346             return 1;
0347         }
0348     }
0349 #endif
0350     return 0;
0351 }
0352 
0353 int pnp_check_irq(struct pnp_dev *dev, struct resource *res)
0354 {
0355     int i;
0356     struct pnp_dev *tdev;
0357     struct resource *tres;
0358     resource_size_t *irq;
0359 
0360     irq = &res->start;
0361 
0362     /* if the resource doesn't exist, don't complain about it */
0363     if (cannot_compare(res->flags))
0364         return 1;
0365 
0366     /* check if the resource is valid */
0367     if (*irq > 15)
0368         return 0;
0369 
0370     /* check if the resource is reserved */
0371     for (i = 0; i < 16; i++) {
0372         if (pnp_reserve_irq[i] == *irq)
0373             return 0;
0374     }
0375 
0376     /* check for internal conflicts */
0377     for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) {
0378         if (tres != res && tres->flags & IORESOURCE_IRQ) {
0379             if (tres->start == *irq)
0380                 return 0;
0381         }
0382     }
0383 
0384     /* check if the resource is being used by a pci device */
0385     if (pci_uses_irq(dev, *irq))
0386         return 0;
0387 
0388     /* check if the resource is already in use, skip if the
0389      * device is active because it itself may be in use */
0390     if (!dev->active) {
0391         if (request_irq(*irq, pnp_test_handler,
0392                 IRQF_PROBE_SHARED, "pnp", NULL))
0393             return 0;
0394         free_irq(*irq, NULL);
0395     }
0396 
0397     /* check for conflicts with other pnp devices */
0398     pnp_for_each_dev(tdev) {
0399         if (tdev == dev)
0400             continue;
0401         for (i = 0;
0402              (tres = pnp_get_resource(tdev, IORESOURCE_IRQ, i));
0403              i++) {
0404             if (tres->flags & IORESOURCE_IRQ) {
0405                 if (cannot_compare(tres->flags))
0406                     continue;
0407                 if (tres->start == *irq)
0408                     return 0;
0409             }
0410         }
0411     }
0412 
0413     return 1;
0414 }
0415 
0416 #ifdef CONFIG_ISA_DMA_API
0417 int pnp_check_dma(struct pnp_dev *dev, struct resource *res)
0418 {
0419     int i;
0420     struct pnp_dev *tdev;
0421     struct resource *tres;
0422     resource_size_t *dma;
0423 
0424     dma = &res->start;
0425 
0426     /* if the resource doesn't exist, don't complain about it */
0427     if (cannot_compare(res->flags))
0428         return 1;
0429 
0430     /* check if the resource is valid */
0431     if (*dma == 4 || *dma > 7)
0432         return 0;
0433 
0434     /* check if the resource is reserved */
0435     for (i = 0; i < 8; i++) {
0436         if (pnp_reserve_dma[i] == *dma)
0437             return 0;
0438     }
0439 
0440     /* check for internal conflicts */
0441     for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) {
0442         if (tres != res && tres->flags & IORESOURCE_DMA) {
0443             if (tres->start == *dma)
0444                 return 0;
0445         }
0446     }
0447 
0448     /* check if the resource is already in use, skip if the
0449      * device is active because it itself may be in use */
0450     if (!dev->active) {
0451         if (request_dma(*dma, "pnp"))
0452             return 0;
0453         free_dma(*dma);
0454     }
0455 
0456     /* check for conflicts with other pnp devices */
0457     pnp_for_each_dev(tdev) {
0458         if (tdev == dev)
0459             continue;
0460         for (i = 0;
0461              (tres = pnp_get_resource(tdev, IORESOURCE_DMA, i));
0462              i++) {
0463             if (tres->flags & IORESOURCE_DMA) {
0464                 if (cannot_compare(tres->flags))
0465                     continue;
0466                 if (tres->start == *dma)
0467                     return 0;
0468             }
0469         }
0470     }
0471 
0472     return 1;
0473 }
0474 #endif /* CONFIG_ISA_DMA_API */
0475 
0476 unsigned long pnp_resource_type(struct resource *res)
0477 {
0478     return res->flags & (IORESOURCE_IO  | IORESOURCE_MEM |
0479                  IORESOURCE_IRQ | IORESOURCE_DMA |
0480                  IORESOURCE_BUS);
0481 }
0482 
0483 struct resource *pnp_get_resource(struct pnp_dev *dev,
0484                   unsigned long type, unsigned int num)
0485 {
0486     struct pnp_resource *pnp_res;
0487     struct resource *res;
0488 
0489     list_for_each_entry(pnp_res, &dev->resources, list) {
0490         res = &pnp_res->res;
0491         if (pnp_resource_type(res) == type && num-- == 0)
0492             return res;
0493     }
0494     return NULL;
0495 }
0496 EXPORT_SYMBOL(pnp_get_resource);
0497 
0498 static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev)
0499 {
0500     struct pnp_resource *pnp_res;
0501 
0502     pnp_res = kzalloc(sizeof(struct pnp_resource), GFP_KERNEL);
0503     if (!pnp_res)
0504         return NULL;
0505 
0506     list_add_tail(&pnp_res->list, &dev->resources);
0507     return pnp_res;
0508 }
0509 
0510 struct pnp_resource *pnp_add_resource(struct pnp_dev *dev,
0511                       struct resource *res)
0512 {
0513     struct pnp_resource *pnp_res;
0514 
0515     pnp_res = pnp_new_resource(dev);
0516     if (!pnp_res) {
0517         dev_err(&dev->dev, "can't add resource %pR\n", res);
0518         return NULL;
0519     }
0520 
0521     pnp_res->res = *res;
0522     pnp_res->res.name = dev->name;
0523     dev_dbg(&dev->dev, "%pR\n", res);
0524     return pnp_res;
0525 }
0526 
0527 struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
0528                       int flags)
0529 {
0530     struct pnp_resource *pnp_res;
0531     struct resource *res;
0532 
0533     pnp_res = pnp_new_resource(dev);
0534     if (!pnp_res) {
0535         dev_err(&dev->dev, "can't add resource for IRQ %d\n", irq);
0536         return NULL;
0537     }
0538 
0539     res = &pnp_res->res;
0540     res->flags = IORESOURCE_IRQ | flags;
0541     res->start = irq;
0542     res->end = irq;
0543 
0544     dev_dbg(&dev->dev, "%pR\n", res);
0545     return pnp_res;
0546 }
0547 
0548 struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
0549                       int flags)
0550 {
0551     struct pnp_resource *pnp_res;
0552     struct resource *res;
0553 
0554     pnp_res = pnp_new_resource(dev);
0555     if (!pnp_res) {
0556         dev_err(&dev->dev, "can't add resource for DMA %d\n", dma);
0557         return NULL;
0558     }
0559 
0560     res = &pnp_res->res;
0561     res->flags = IORESOURCE_DMA | flags;
0562     res->start = dma;
0563     res->end = dma;
0564 
0565     dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
0566     return pnp_res;
0567 }
0568 
0569 struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
0570                      resource_size_t start,
0571                      resource_size_t end, int flags)
0572 {
0573     struct pnp_resource *pnp_res;
0574     struct resource *res;
0575 
0576     pnp_res = pnp_new_resource(dev);
0577     if (!pnp_res) {
0578         dev_err(&dev->dev, "can't add resource for IO %#llx-%#llx\n",
0579             (unsigned long long) start,
0580             (unsigned long long) end);
0581         return NULL;
0582     }
0583 
0584     res = &pnp_res->res;
0585     res->flags = IORESOURCE_IO | flags;
0586     res->start = start;
0587     res->end = end;
0588 
0589     dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
0590     return pnp_res;
0591 }
0592 
0593 struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
0594                       resource_size_t start,
0595                       resource_size_t end, int flags)
0596 {
0597     struct pnp_resource *pnp_res;
0598     struct resource *res;
0599 
0600     pnp_res = pnp_new_resource(dev);
0601     if (!pnp_res) {
0602         dev_err(&dev->dev, "can't add resource for MEM %#llx-%#llx\n",
0603             (unsigned long long) start,
0604             (unsigned long long) end);
0605         return NULL;
0606     }
0607 
0608     res = &pnp_res->res;
0609     res->flags = IORESOURCE_MEM | flags;
0610     res->start = start;
0611     res->end = end;
0612 
0613     dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
0614     return pnp_res;
0615 }
0616 
0617 struct pnp_resource *pnp_add_bus_resource(struct pnp_dev *dev,
0618                       resource_size_t start,
0619                       resource_size_t end)
0620 {
0621     struct pnp_resource *pnp_res;
0622     struct resource *res;
0623 
0624     pnp_res = pnp_new_resource(dev);
0625     if (!pnp_res) {
0626         dev_err(&dev->dev, "can't add resource for BUS %#llx-%#llx\n",
0627             (unsigned long long) start,
0628             (unsigned long long) end);
0629         return NULL;
0630     }
0631 
0632     res = &pnp_res->res;
0633     res->flags = IORESOURCE_BUS;
0634     res->start = start;
0635     res->end = end;
0636 
0637     dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
0638     return pnp_res;
0639 }
0640 
0641 /*
0642  * Determine whether the specified resource is a possible configuration
0643  * for this device.
0644  */
0645 int pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t start,
0646             resource_size_t size)
0647 {
0648     struct pnp_option *option;
0649     struct pnp_port *port;
0650     struct pnp_mem *mem;
0651     struct pnp_irq *irq;
0652     struct pnp_dma *dma;
0653 
0654     list_for_each_entry(option, &dev->options, list) {
0655         if (option->type != type)
0656             continue;
0657 
0658         switch (option->type) {
0659         case IORESOURCE_IO:
0660             port = &option->u.port;
0661             if (port->min == start && port->size == size)
0662                 return 1;
0663             break;
0664         case IORESOURCE_MEM:
0665             mem = &option->u.mem;
0666             if (mem->min == start && mem->size == size)
0667                 return 1;
0668             break;
0669         case IORESOURCE_IRQ:
0670             irq = &option->u.irq;
0671             if (start < PNP_IRQ_NR &&
0672                 test_bit(start, irq->map.bits))
0673                 return 1;
0674             break;
0675         case IORESOURCE_DMA:
0676             dma = &option->u.dma;
0677             if (dma->map & (1 << start))
0678                 return 1;
0679             break;
0680         }
0681     }
0682 
0683     return 0;
0684 }
0685 EXPORT_SYMBOL(pnp_possible_config);
0686 
0687 int pnp_range_reserved(resource_size_t start, resource_size_t end)
0688 {
0689     struct pnp_dev *dev;
0690     struct pnp_resource *pnp_res;
0691     resource_size_t *dev_start, *dev_end;
0692 
0693     pnp_for_each_dev(dev) {
0694         list_for_each_entry(pnp_res, &dev->resources, list) {
0695             dev_start = &pnp_res->res.start;
0696             dev_end   = &pnp_res->res.end;
0697             if (ranged_conflict(&start, &end, dev_start, dev_end))
0698                 return 1;
0699         }
0700     }
0701     return 0;
0702 }
0703 EXPORT_SYMBOL(pnp_range_reserved);
0704 
0705 /* format is: pnp_reserve_irq=irq1[,irq2] .... */
0706 static int __init pnp_setup_reserve_irq(char *str)
0707 {
0708     int i;
0709 
0710     for (i = 0; i < 16; i++)
0711         if (get_option(&str, &pnp_reserve_irq[i]) != 2)
0712             break;
0713     return 1;
0714 }
0715 
0716 __setup("pnp_reserve_irq=", pnp_setup_reserve_irq);
0717 
0718 /* format is: pnp_reserve_dma=dma1[,dma2] .... */
0719 static int __init pnp_setup_reserve_dma(char *str)
0720 {
0721     int i;
0722 
0723     for (i = 0; i < 8; i++)
0724         if (get_option(&str, &pnp_reserve_dma[i]) != 2)
0725             break;
0726     return 1;
0727 }
0728 
0729 __setup("pnp_reserve_dma=", pnp_setup_reserve_dma);
0730 
0731 /* format is: pnp_reserve_io=io1,size1[,io2,size2] .... */
0732 static int __init pnp_setup_reserve_io(char *str)
0733 {
0734     int i;
0735 
0736     for (i = 0; i < 16; i++)
0737         if (get_option(&str, &pnp_reserve_io[i]) != 2)
0738             break;
0739     return 1;
0740 }
0741 
0742 __setup("pnp_reserve_io=", pnp_setup_reserve_io);
0743 
0744 /* format is: pnp_reserve_mem=mem1,size1[,mem2,size2] .... */
0745 static int __init pnp_setup_reserve_mem(char *str)
0746 {
0747     int i;
0748 
0749     for (i = 0; i < 16; i++)
0750         if (get_option(&str, &pnp_reserve_mem[i]) != 2)
0751             break;
0752     return 1;
0753 }
0754 
0755 __setup("pnp_reserve_mem=", pnp_setup_reserve_mem);