resource.c 17 KB

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