resource.c 17 KB

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