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