resource.c 17 KB

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