manager.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. /*
  2. * manager.c - Resource Management, Conflict Resolution, Activation and Disabling of Devices
  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/errno.h>
  8. #include <linux/module.h>
  9. #include <linux/init.h>
  10. #include <linux/kernel.h>
  11. #include <linux/pnp.h>
  12. #include <linux/slab.h>
  13. #include <linux/bitmap.h>
  14. #include "base.h"
  15. DECLARE_MUTEX(pnp_res_mutex);
  16. static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
  17. {
  18. resource_size_t *start, *end;
  19. unsigned long *flags;
  20. if (idx >= PNP_MAX_PORT) {
  21. dev_err(&dev->dev, "too many I/O port resources\n");
  22. /* pretend we were successful so at least the manager won't try again */
  23. return 1;
  24. }
  25. /* check if this resource has been manually set, if so skip */
  26. if (!(dev->res.port_resource[idx].flags & IORESOURCE_AUTO))
  27. return 1;
  28. start = &dev->res.port_resource[idx].start;
  29. end = &dev->res.port_resource[idx].end;
  30. flags = &dev->res.port_resource[idx].flags;
  31. /* set the initial values */
  32. *flags |= rule->flags | IORESOURCE_IO;
  33. *flags &= ~IORESOURCE_UNSET;
  34. if (!rule->size) {
  35. *flags |= IORESOURCE_DISABLED;
  36. return 1; /* skip disabled resource requests */
  37. }
  38. *start = rule->min;
  39. *end = *start + rule->size - 1;
  40. /* run through until pnp_check_port is happy */
  41. while (!pnp_check_port(dev, idx)) {
  42. *start += rule->align;
  43. *end = *start + rule->size - 1;
  44. if (*start > rule->max || !rule->align)
  45. return 0;
  46. }
  47. return 1;
  48. }
  49. static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
  50. {
  51. resource_size_t *start, *end;
  52. unsigned long *flags;
  53. if (idx >= PNP_MAX_MEM) {
  54. dev_err(&dev->dev, "too many memory resources\n");
  55. /* pretend we were successful so at least the manager won't try again */
  56. return 1;
  57. }
  58. /* check if this resource has been manually set, if so skip */
  59. if (!(dev->res.mem_resource[idx].flags & IORESOURCE_AUTO))
  60. return 1;
  61. start = &dev->res.mem_resource[idx].start;
  62. end = &dev->res.mem_resource[idx].end;
  63. flags = &dev->res.mem_resource[idx].flags;
  64. /* set the initial values */
  65. *flags |= rule->flags | IORESOURCE_MEM;
  66. *flags &= ~IORESOURCE_UNSET;
  67. /* convert pnp flags to standard Linux flags */
  68. if (!(rule->flags & IORESOURCE_MEM_WRITEABLE))
  69. *flags |= IORESOURCE_READONLY;
  70. if (rule->flags & IORESOURCE_MEM_CACHEABLE)
  71. *flags |= IORESOURCE_CACHEABLE;
  72. if (rule->flags & IORESOURCE_MEM_RANGELENGTH)
  73. *flags |= IORESOURCE_RANGELENGTH;
  74. if (rule->flags & IORESOURCE_MEM_SHADOWABLE)
  75. *flags |= IORESOURCE_SHADOWABLE;
  76. if (!rule->size) {
  77. *flags |= IORESOURCE_DISABLED;
  78. return 1; /* skip disabled resource requests */
  79. }
  80. *start = rule->min;
  81. *end = *start + rule->size - 1;
  82. /* run through until pnp_check_mem is happy */
  83. while (!pnp_check_mem(dev, idx)) {
  84. *start += rule->align;
  85. *end = *start + rule->size - 1;
  86. if (*start > rule->max || !rule->align)
  87. return 0;
  88. }
  89. return 1;
  90. }
  91. static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
  92. {
  93. resource_size_t *start, *end;
  94. unsigned long *flags;
  95. int i;
  96. /* IRQ priority: this table is good for i386 */
  97. static unsigned short xtab[16] = {
  98. 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
  99. };
  100. if (idx >= PNP_MAX_IRQ) {
  101. dev_err(&dev->dev, "too many IRQ resources\n");
  102. /* pretend we were successful so at least the manager won't try again */
  103. return 1;
  104. }
  105. /* check if this resource has been manually set, if so skip */
  106. if (!(dev->res.irq_resource[idx].flags & IORESOURCE_AUTO))
  107. return 1;
  108. start = &dev->res.irq_resource[idx].start;
  109. end = &dev->res.irq_resource[idx].end;
  110. flags = &dev->res.irq_resource[idx].flags;
  111. /* set the initial values */
  112. *flags |= rule->flags | IORESOURCE_IRQ;
  113. *flags &= ~IORESOURCE_UNSET;
  114. if (bitmap_empty(rule->map, PNP_IRQ_NR)) {
  115. *flags |= IORESOURCE_DISABLED;
  116. return 1; /* skip disabled resource requests */
  117. }
  118. /* TBD: need check for >16 IRQ */
  119. *start = find_next_bit(rule->map, PNP_IRQ_NR, 16);
  120. if (*start < PNP_IRQ_NR) {
  121. *end = *start;
  122. return 1;
  123. }
  124. for (i = 0; i < 16; i++) {
  125. if (test_bit(xtab[i], rule->map)) {
  126. *start = *end = xtab[i];
  127. if (pnp_check_irq(dev, idx))
  128. return 1;
  129. }
  130. }
  131. return 0;
  132. }
  133. static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
  134. {
  135. resource_size_t *start, *end;
  136. unsigned long *flags;
  137. int i;
  138. /* DMA priority: this table is good for i386 */
  139. static unsigned short xtab[8] = {
  140. 1, 3, 5, 6, 7, 0, 2, 4
  141. };
  142. if (idx >= PNP_MAX_DMA) {
  143. dev_err(&dev->dev, "too many DMA resources\n");
  144. return;
  145. }
  146. /* check if this resource has been manually set, if so skip */
  147. if (!(dev->res.dma_resource[idx].flags & IORESOURCE_AUTO))
  148. return;
  149. start = &dev->res.dma_resource[idx].start;
  150. end = &dev->res.dma_resource[idx].end;
  151. flags = &dev->res.dma_resource[idx].flags;
  152. /* set the initial values */
  153. *flags |= rule->flags | IORESOURCE_DMA;
  154. *flags &= ~IORESOURCE_UNSET;
  155. for (i = 0; i < 8; i++) {
  156. if (rule->map & (1 << xtab[i])) {
  157. *start = *end = xtab[i];
  158. if (pnp_check_dma(dev, idx))
  159. return;
  160. }
  161. }
  162. #ifdef MAX_DMA_CHANNELS
  163. *start = *end = MAX_DMA_CHANNELS;
  164. #endif
  165. *flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
  166. }
  167. /**
  168. * pnp_init_resources - Resets a resource table to default values.
  169. * @table: pointer to the desired resource table
  170. */
  171. void pnp_init_resource_table(struct pnp_resource_table *table)
  172. {
  173. int idx;
  174. for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
  175. table->irq_resource[idx].name = NULL;
  176. table->irq_resource[idx].start = -1;
  177. table->irq_resource[idx].end = -1;
  178. table->irq_resource[idx].flags =
  179. IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET;
  180. }
  181. for (idx = 0; idx < PNP_MAX_DMA; idx++) {
  182. table->dma_resource[idx].name = NULL;
  183. table->dma_resource[idx].start = -1;
  184. table->dma_resource[idx].end = -1;
  185. table->dma_resource[idx].flags =
  186. IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET;
  187. }
  188. for (idx = 0; idx < PNP_MAX_PORT; idx++) {
  189. table->port_resource[idx].name = NULL;
  190. table->port_resource[idx].start = 0;
  191. table->port_resource[idx].end = 0;
  192. table->port_resource[idx].flags =
  193. IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET;
  194. }
  195. for (idx = 0; idx < PNP_MAX_MEM; idx++) {
  196. table->mem_resource[idx].name = NULL;
  197. table->mem_resource[idx].start = 0;
  198. table->mem_resource[idx].end = 0;
  199. table->mem_resource[idx].flags =
  200. IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET;
  201. }
  202. }
  203. /**
  204. * pnp_clean_resources - clears resources that were not manually set
  205. * @res: the resources to clean
  206. */
  207. static void pnp_clean_resource_table(struct pnp_resource_table *res)
  208. {
  209. int idx;
  210. for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
  211. if (!(res->irq_resource[idx].flags & IORESOURCE_AUTO))
  212. continue;
  213. res->irq_resource[idx].start = -1;
  214. res->irq_resource[idx].end = -1;
  215. res->irq_resource[idx].flags =
  216. IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET;
  217. }
  218. for (idx = 0; idx < PNP_MAX_DMA; idx++) {
  219. if (!(res->dma_resource[idx].flags & IORESOURCE_AUTO))
  220. continue;
  221. res->dma_resource[idx].start = -1;
  222. res->dma_resource[idx].end = -1;
  223. res->dma_resource[idx].flags =
  224. IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET;
  225. }
  226. for (idx = 0; idx < PNP_MAX_PORT; idx++) {
  227. if (!(res->port_resource[idx].flags & IORESOURCE_AUTO))
  228. continue;
  229. res->port_resource[idx].start = 0;
  230. res->port_resource[idx].end = 0;
  231. res->port_resource[idx].flags =
  232. IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET;
  233. }
  234. for (idx = 0; idx < PNP_MAX_MEM; idx++) {
  235. if (!(res->mem_resource[idx].flags & IORESOURCE_AUTO))
  236. continue;
  237. res->mem_resource[idx].start = 0;
  238. res->mem_resource[idx].end = 0;
  239. res->mem_resource[idx].flags =
  240. IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET;
  241. }
  242. }
  243. /**
  244. * pnp_assign_resources - assigns resources to the device based on the specified dependent number
  245. * @dev: pointer to the desired device
  246. * @depnum: the dependent function number
  247. *
  248. * Only set depnum to 0 if the device does not have dependent options.
  249. */
  250. static int pnp_assign_resources(struct pnp_dev *dev, int depnum)
  251. {
  252. struct pnp_port *port;
  253. struct pnp_mem *mem;
  254. struct pnp_irq *irq;
  255. struct pnp_dma *dma;
  256. int nport = 0, nmem = 0, nirq = 0, ndma = 0;
  257. if (!pnp_can_configure(dev))
  258. return -ENODEV;
  259. down(&pnp_res_mutex);
  260. pnp_clean_resource_table(&dev->res); /* start with a fresh slate */
  261. if (dev->independent) {
  262. port = dev->independent->port;
  263. mem = dev->independent->mem;
  264. irq = dev->independent->irq;
  265. dma = dev->independent->dma;
  266. while (port) {
  267. if (!pnp_assign_port(dev, port, nport))
  268. goto fail;
  269. nport++;
  270. port = port->next;
  271. }
  272. while (mem) {
  273. if (!pnp_assign_mem(dev, mem, nmem))
  274. goto fail;
  275. nmem++;
  276. mem = mem->next;
  277. }
  278. while (irq) {
  279. if (!pnp_assign_irq(dev, irq, nirq))
  280. goto fail;
  281. nirq++;
  282. irq = irq->next;
  283. }
  284. while (dma) {
  285. pnp_assign_dma(dev, dma, ndma);
  286. ndma++;
  287. dma = dma->next;
  288. }
  289. }
  290. if (depnum) {
  291. struct pnp_option *dep;
  292. int i;
  293. for (i = 1, dep = dev->dependent; i < depnum;
  294. i++, dep = dep->next)
  295. if (!dep)
  296. goto fail;
  297. port = dep->port;
  298. mem = dep->mem;
  299. irq = dep->irq;
  300. dma = dep->dma;
  301. while (port) {
  302. if (!pnp_assign_port(dev, port, nport))
  303. goto fail;
  304. nport++;
  305. port = port->next;
  306. }
  307. while (mem) {
  308. if (!pnp_assign_mem(dev, mem, nmem))
  309. goto fail;
  310. nmem++;
  311. mem = mem->next;
  312. }
  313. while (irq) {
  314. if (!pnp_assign_irq(dev, irq, nirq))
  315. goto fail;
  316. nirq++;
  317. irq = irq->next;
  318. }
  319. while (dma) {
  320. pnp_assign_dma(dev, dma, ndma);
  321. ndma++;
  322. dma = dma->next;
  323. }
  324. } else if (dev->dependent)
  325. goto fail;
  326. up(&pnp_res_mutex);
  327. return 1;
  328. fail:
  329. pnp_clean_resource_table(&dev->res);
  330. up(&pnp_res_mutex);
  331. return 0;
  332. }
  333. /**
  334. * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table
  335. * @dev: pointer to the desired device
  336. * @res: pointer to the new resource config
  337. * @mode: 0 or PNP_CONFIG_FORCE
  338. *
  339. * This function can be used by drivers that want to manually set thier resources.
  340. */
  341. int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res,
  342. int mode)
  343. {
  344. int i;
  345. struct pnp_resource_table *bak;
  346. if (!pnp_can_configure(dev))
  347. return -ENODEV;
  348. bak = pnp_alloc(sizeof(struct pnp_resource_table));
  349. if (!bak)
  350. return -ENOMEM;
  351. *bak = dev->res;
  352. down(&pnp_res_mutex);
  353. dev->res = *res;
  354. if (!(mode & PNP_CONFIG_FORCE)) {
  355. for (i = 0; i < PNP_MAX_PORT; i++) {
  356. if (!pnp_check_port(dev, i))
  357. goto fail;
  358. }
  359. for (i = 0; i < PNP_MAX_MEM; i++) {
  360. if (!pnp_check_mem(dev, i))
  361. goto fail;
  362. }
  363. for (i = 0; i < PNP_MAX_IRQ; i++) {
  364. if (!pnp_check_irq(dev, i))
  365. goto fail;
  366. }
  367. for (i = 0; i < PNP_MAX_DMA; i++) {
  368. if (!pnp_check_dma(dev, i))
  369. goto fail;
  370. }
  371. }
  372. up(&pnp_res_mutex);
  373. kfree(bak);
  374. return 0;
  375. fail:
  376. dev->res = *bak;
  377. up(&pnp_res_mutex);
  378. kfree(bak);
  379. return -EINVAL;
  380. }
  381. /**
  382. * pnp_auto_config_dev - automatically assigns resources to a device
  383. * @dev: pointer to the desired device
  384. */
  385. int pnp_auto_config_dev(struct pnp_dev *dev)
  386. {
  387. struct pnp_option *dep;
  388. int i = 1;
  389. if (!pnp_can_configure(dev)) {
  390. dev_dbg(&dev->dev, "configuration not supported\n");
  391. return -ENODEV;
  392. }
  393. if (!dev->dependent) {
  394. if (pnp_assign_resources(dev, 0))
  395. return 0;
  396. } else {
  397. dep = dev->dependent;
  398. do {
  399. if (pnp_assign_resources(dev, i))
  400. return 0;
  401. dep = dep->next;
  402. i++;
  403. } while (dep);
  404. }
  405. dev_err(&dev->dev, "unable to assign resources\n");
  406. return -EBUSY;
  407. }
  408. /**
  409. * pnp_start_dev - low-level start of the PnP device
  410. * @dev: pointer to the desired device
  411. *
  412. * assumes that resources have already been allocated
  413. */
  414. int pnp_start_dev(struct pnp_dev *dev)
  415. {
  416. if (!pnp_can_write(dev)) {
  417. dev_dbg(&dev->dev, "activation not supported\n");
  418. return -EINVAL;
  419. }
  420. if (dev->protocol->set(dev, &dev->res) < 0) {
  421. dev_err(&dev->dev, "activation failed\n");
  422. return -EIO;
  423. }
  424. dev_info(&dev->dev, "activated\n");
  425. return 0;
  426. }
  427. /**
  428. * pnp_stop_dev - low-level disable of the PnP device
  429. * @dev: pointer to the desired device
  430. *
  431. * does not free resources
  432. */
  433. int pnp_stop_dev(struct pnp_dev *dev)
  434. {
  435. if (!pnp_can_disable(dev)) {
  436. dev_dbg(&dev->dev, "disabling not supported\n");
  437. return -EINVAL;
  438. }
  439. if (dev->protocol->disable(dev) < 0) {
  440. dev_err(&dev->dev, "disable failed\n");
  441. return -EIO;
  442. }
  443. dev_info(&dev->dev, "disabled\n");
  444. return 0;
  445. }
  446. /**
  447. * pnp_activate_dev - activates a PnP device for use
  448. * @dev: pointer to the desired device
  449. *
  450. * does not validate or set resources so be careful.
  451. */
  452. int pnp_activate_dev(struct pnp_dev *dev)
  453. {
  454. int error;
  455. if (dev->active)
  456. return 0; /* the device is already active */
  457. /* ensure resources are allocated */
  458. if (pnp_auto_config_dev(dev))
  459. return -EBUSY;
  460. error = pnp_start_dev(dev);
  461. if (error)
  462. return error;
  463. dev->active = 1;
  464. return 1;
  465. }
  466. /**
  467. * pnp_disable_dev - disables device
  468. * @dev: pointer to the desired device
  469. *
  470. * inform the correct pnp protocol so that resources can be used by other devices
  471. */
  472. int pnp_disable_dev(struct pnp_dev *dev)
  473. {
  474. int error;
  475. if (!dev->active)
  476. return 0; /* the device is already disabled */
  477. error = pnp_stop_dev(dev);
  478. if (error)
  479. return error;
  480. dev->active = 0;
  481. /* release the resources so that other devices can use them */
  482. down(&pnp_res_mutex);
  483. pnp_clean_resource_table(&dev->res);
  484. up(&pnp_res_mutex);
  485. return 1;
  486. }
  487. /**
  488. * pnp_resource_change - change one resource
  489. * @resource: pointer to resource to be changed
  490. * @start: start of region
  491. * @size: size of region
  492. */
  493. void pnp_resource_change(struct resource *resource, resource_size_t start,
  494. resource_size_t size)
  495. {
  496. resource->flags &= ~(IORESOURCE_AUTO | IORESOURCE_UNSET);
  497. resource->start = start;
  498. resource->end = start + size - 1;
  499. }
  500. EXPORT_SYMBOL(pnp_manual_config_dev);
  501. EXPORT_SYMBOL(pnp_start_dev);
  502. EXPORT_SYMBOL(pnp_stop_dev);
  503. EXPORT_SYMBOL(pnp_activate_dev);
  504. EXPORT_SYMBOL(pnp_disable_dev);
  505. EXPORT_SYMBOL(pnp_resource_change);
  506. EXPORT_SYMBOL(pnp_init_resource_table);