rsparser.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  1. /*
  2. * rsparser.c - parses and encodes pnpbios resource data streams
  3. */
  4. #include <linux/ctype.h>
  5. #include <linux/pnp.h>
  6. #include <linux/string.h>
  7. #include <linux/slab.h>
  8. #ifdef CONFIG_PCI
  9. #include <linux/pci.h>
  10. #else
  11. inline void pcibios_penalize_isa_irq(int irq, int active)
  12. {
  13. }
  14. #endif /* CONFIG_PCI */
  15. #include "../base.h"
  16. #include "pnpbios.h"
  17. /* standard resource tags */
  18. #define SMALL_TAG_PNPVERNO 0x01
  19. #define SMALL_TAG_LOGDEVID 0x02
  20. #define SMALL_TAG_COMPATDEVID 0x03
  21. #define SMALL_TAG_IRQ 0x04
  22. #define SMALL_TAG_DMA 0x05
  23. #define SMALL_TAG_STARTDEP 0x06
  24. #define SMALL_TAG_ENDDEP 0x07
  25. #define SMALL_TAG_PORT 0x08
  26. #define SMALL_TAG_FIXEDPORT 0x09
  27. #define SMALL_TAG_VENDOR 0x0e
  28. #define SMALL_TAG_END 0x0f
  29. #define LARGE_TAG 0x80
  30. #define LARGE_TAG_MEM 0x81
  31. #define LARGE_TAG_ANSISTR 0x82
  32. #define LARGE_TAG_UNICODESTR 0x83
  33. #define LARGE_TAG_VENDOR 0x84
  34. #define LARGE_TAG_MEM32 0x85
  35. #define LARGE_TAG_FIXEDMEM32 0x86
  36. /*
  37. * Resource Data Stream Format:
  38. *
  39. * Allocated Resources (required)
  40. * end tag ->
  41. * Resource Configuration Options (optional)
  42. * end tag ->
  43. * Compitable Device IDs (optional)
  44. * final end tag ->
  45. */
  46. /*
  47. * Allocated Resources
  48. */
  49. static void pnpbios_parse_allocated_ioresource(struct pnp_dev *dev,
  50. int start, int len)
  51. {
  52. int flags = 0;
  53. int end = start + len - 1;
  54. if (len <= 0 || end >= 0x10003)
  55. flags |= IORESOURCE_DISABLED;
  56. pnp_add_io_resource(dev, start, end, flags);
  57. }
  58. static void pnpbios_parse_allocated_memresource(struct pnp_dev *dev,
  59. int start, int len)
  60. {
  61. int flags = 0;
  62. int end = start + len - 1;
  63. if (len <= 0)
  64. flags |= IORESOURCE_DISABLED;
  65. pnp_add_mem_resource(dev, start, end, flags);
  66. }
  67. static unsigned char *pnpbios_parse_allocated_resource_data(struct pnp_dev *dev,
  68. unsigned char *p,
  69. unsigned char *end)
  70. {
  71. unsigned int len, tag;
  72. int io, size, mask, i, flags;
  73. if (!p)
  74. return NULL;
  75. dev_dbg(&dev->dev, "parse allocated resources\n");
  76. pnp_init_resources(dev);
  77. while ((char *)p < (char *)end) {
  78. /* determine the type of tag */
  79. if (p[0] & LARGE_TAG) { /* large tag */
  80. len = (p[2] << 8) | p[1];
  81. tag = p[0];
  82. } else { /* small tag */
  83. len = p[0] & 0x07;
  84. tag = ((p[0] >> 3) & 0x0f);
  85. }
  86. switch (tag) {
  87. case LARGE_TAG_MEM:
  88. if (len != 9)
  89. goto len_err;
  90. io = *(short *)&p[4];
  91. size = *(short *)&p[10];
  92. pnpbios_parse_allocated_memresource(dev, io, size);
  93. break;
  94. case LARGE_TAG_ANSISTR:
  95. /* ignore this for now */
  96. break;
  97. case LARGE_TAG_VENDOR:
  98. /* do nothing */
  99. break;
  100. case LARGE_TAG_MEM32:
  101. if (len != 17)
  102. goto len_err;
  103. io = *(int *)&p[4];
  104. size = *(int *)&p[16];
  105. pnpbios_parse_allocated_memresource(dev, io, size);
  106. break;
  107. case LARGE_TAG_FIXEDMEM32:
  108. if (len != 9)
  109. goto len_err;
  110. io = *(int *)&p[4];
  111. size = *(int *)&p[8];
  112. pnpbios_parse_allocated_memresource(dev, io, size);
  113. break;
  114. case SMALL_TAG_IRQ:
  115. if (len < 2 || len > 3)
  116. goto len_err;
  117. flags = 0;
  118. io = -1;
  119. mask = p[1] + p[2] * 256;
  120. for (i = 0; i < 16; i++, mask = mask >> 1)
  121. if (mask & 0x01)
  122. io = i;
  123. if (io != -1)
  124. pcibios_penalize_isa_irq(io, 1);
  125. else
  126. flags = IORESOURCE_DISABLED;
  127. pnp_add_irq_resource(dev, io, flags);
  128. break;
  129. case SMALL_TAG_DMA:
  130. if (len != 2)
  131. goto len_err;
  132. flags = 0;
  133. io = -1;
  134. mask = p[1];
  135. for (i = 0; i < 8; i++, mask = mask >> 1)
  136. if (mask & 0x01)
  137. io = i;
  138. if (io == -1)
  139. flags = IORESOURCE_DISABLED;
  140. pnp_add_dma_resource(dev, io, flags);
  141. break;
  142. case SMALL_TAG_PORT:
  143. if (len != 7)
  144. goto len_err;
  145. io = p[2] + p[3] * 256;
  146. size = p[7];
  147. pnpbios_parse_allocated_ioresource(dev, io, size);
  148. break;
  149. case SMALL_TAG_VENDOR:
  150. /* do nothing */
  151. break;
  152. case SMALL_TAG_FIXEDPORT:
  153. if (len != 3)
  154. goto len_err;
  155. io = p[1] + p[2] * 256;
  156. size = p[3];
  157. pnpbios_parse_allocated_ioresource(dev, io, size);
  158. break;
  159. case SMALL_TAG_END:
  160. p = p + 2;
  161. return (unsigned char *)p;
  162. break;
  163. default: /* an unkown tag */
  164. len_err:
  165. dev_err(&dev->dev, "unknown tag %#x length %d\n",
  166. tag, len);
  167. break;
  168. }
  169. /* continue to the next tag */
  170. if (p[0] & LARGE_TAG)
  171. p += len + 3;
  172. else
  173. p += len + 1;
  174. }
  175. dev_err(&dev->dev, "no end tag in resource structure\n");
  176. return NULL;
  177. }
  178. /*
  179. * Resource Configuration Options
  180. */
  181. static __init void pnpbios_parse_mem_option(struct pnp_dev *dev,
  182. unsigned char *p, int size,
  183. struct pnp_option *option)
  184. {
  185. resource_size_t min, max, align, len;
  186. unsigned char flags;
  187. min = ((p[5] << 8) | p[4]) << 8;
  188. max = ((p[7] << 8) | p[6]) << 8;
  189. align = (p[9] << 8) | p[8];
  190. len = ((p[11] << 8) | p[10]) << 8;
  191. flags = p[3];
  192. pnp_register_mem_resource(dev, option, min, max, align, len, flags);
  193. }
  194. static __init void pnpbios_parse_mem32_option(struct pnp_dev *dev,
  195. unsigned char *p, int size,
  196. struct pnp_option *option)
  197. {
  198. resource_size_t min, max, align, len;
  199. unsigned char flags;
  200. min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
  201. max = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
  202. align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12];
  203. len = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16];
  204. flags = p[3];
  205. pnp_register_mem_resource(dev, option, min, max, align, len, flags);
  206. }
  207. static __init void pnpbios_parse_fixed_mem32_option(struct pnp_dev *dev,
  208. unsigned char *p, int size,
  209. struct pnp_option *option)
  210. {
  211. resource_size_t base, len;
  212. unsigned char flags;
  213. base = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
  214. len = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
  215. flags = p[3];
  216. pnp_register_mem_resource(dev, option, base, base, 0, len, flags);
  217. }
  218. static __init void pnpbios_parse_irq_option(struct pnp_dev *dev,
  219. unsigned char *p, int size,
  220. struct pnp_option *option)
  221. {
  222. unsigned long bits;
  223. pnp_irq_mask_t map;
  224. unsigned char flags = IORESOURCE_IRQ_HIGHEDGE;
  225. bits = (p[2] << 8) | p[1];
  226. bitmap_zero(map.bits, PNP_IRQ_NR);
  227. bitmap_copy(map.bits, &bits, 16);
  228. if (size > 2)
  229. flags = p[3];
  230. pnp_register_irq_resource(dev, option, &map, flags);
  231. }
  232. static __init void pnpbios_parse_dma_option(struct pnp_dev *dev,
  233. unsigned char *p, int size,
  234. struct pnp_option *option)
  235. {
  236. pnp_register_dma_resource(dev, option, p[1], p[2]);
  237. }
  238. static __init void pnpbios_parse_port_option(struct pnp_dev *dev,
  239. unsigned char *p, int size,
  240. struct pnp_option *option)
  241. {
  242. resource_size_t min, max, align, len;
  243. unsigned char flags;
  244. min = (p[3] << 8) | p[2];
  245. max = (p[5] << 8) | p[4];
  246. align = p[6];
  247. len = p[7];
  248. flags = p[1] ? IORESOURCE_IO_16BIT_ADDR : 0;
  249. pnp_register_port_resource(dev, option, min, max, align, len, flags);
  250. }
  251. static __init void pnpbios_parse_fixed_port_option(struct pnp_dev *dev,
  252. unsigned char *p, int size,
  253. struct pnp_option *option)
  254. {
  255. resource_size_t base, len;
  256. base = (p[2] << 8) | p[1];
  257. len = p[3];
  258. pnp_register_port_resource(dev, option, base, base, 0, len,
  259. IORESOURCE_IO_FIXED);
  260. }
  261. static __init unsigned char *
  262. pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
  263. struct pnp_dev *dev)
  264. {
  265. unsigned int len, tag;
  266. int priority = 0;
  267. struct pnp_option *option, *option_independent;
  268. if (!p)
  269. return NULL;
  270. dev_dbg(&dev->dev, "parse resource options\n");
  271. option_independent = option = pnp_register_independent_option(dev);
  272. if (!option)
  273. return NULL;
  274. while ((char *)p < (char *)end) {
  275. /* determine the type of tag */
  276. if (p[0] & LARGE_TAG) { /* large tag */
  277. len = (p[2] << 8) | p[1];
  278. tag = p[0];
  279. } else { /* small tag */
  280. len = p[0] & 0x07;
  281. tag = ((p[0] >> 3) & 0x0f);
  282. }
  283. switch (tag) {
  284. case LARGE_TAG_MEM:
  285. if (len != 9)
  286. goto len_err;
  287. pnpbios_parse_mem_option(dev, p, len, option);
  288. break;
  289. case LARGE_TAG_MEM32:
  290. if (len != 17)
  291. goto len_err;
  292. pnpbios_parse_mem32_option(dev, p, len, option);
  293. break;
  294. case LARGE_TAG_FIXEDMEM32:
  295. if (len != 9)
  296. goto len_err;
  297. pnpbios_parse_fixed_mem32_option(dev, p, len, option);
  298. break;
  299. case SMALL_TAG_IRQ:
  300. if (len < 2 || len > 3)
  301. goto len_err;
  302. pnpbios_parse_irq_option(dev, p, len, option);
  303. break;
  304. case SMALL_TAG_DMA:
  305. if (len != 2)
  306. goto len_err;
  307. pnpbios_parse_dma_option(dev, p, len, option);
  308. break;
  309. case SMALL_TAG_PORT:
  310. if (len != 7)
  311. goto len_err;
  312. pnpbios_parse_port_option(dev, p, len, option);
  313. break;
  314. case SMALL_TAG_VENDOR:
  315. /* do nothing */
  316. break;
  317. case SMALL_TAG_FIXEDPORT:
  318. if (len != 3)
  319. goto len_err;
  320. pnpbios_parse_fixed_port_option(dev, p, len, option);
  321. break;
  322. case SMALL_TAG_STARTDEP:
  323. if (len > 1)
  324. goto len_err;
  325. priority = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE;
  326. if (len > 0)
  327. priority = 0x100 | p[1];
  328. option = pnp_register_dependent_option(dev, priority);
  329. if (!option)
  330. return NULL;
  331. break;
  332. case SMALL_TAG_ENDDEP:
  333. if (len != 0)
  334. goto len_err;
  335. if (option_independent == option)
  336. dev_warn(&dev->dev, "missing "
  337. "SMALL_TAG_STARTDEP tag\n");
  338. option = option_independent;
  339. dev_dbg(&dev->dev, "end dependent options\n");
  340. break;
  341. case SMALL_TAG_END:
  342. return p + 2;
  343. default: /* an unkown tag */
  344. len_err:
  345. dev_err(&dev->dev, "unknown tag %#x length %d\n",
  346. tag, len);
  347. break;
  348. }
  349. /* continue to the next tag */
  350. if (p[0] & LARGE_TAG)
  351. p += len + 3;
  352. else
  353. p += len + 1;
  354. }
  355. dev_err(&dev->dev, "no end tag in resource structure\n");
  356. return NULL;
  357. }
  358. /*
  359. * Compatible Device IDs
  360. */
  361. static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p,
  362. unsigned char *end,
  363. struct pnp_dev *dev)
  364. {
  365. int len, tag;
  366. u32 eisa_id;
  367. char id[8];
  368. struct pnp_id *dev_id;
  369. if (!p)
  370. return NULL;
  371. while ((char *)p < (char *)end) {
  372. /* determine the type of tag */
  373. if (p[0] & LARGE_TAG) { /* large tag */
  374. len = (p[2] << 8) | p[1];
  375. tag = p[0];
  376. } else { /* small tag */
  377. len = p[0] & 0x07;
  378. tag = ((p[0] >> 3) & 0x0f);
  379. }
  380. switch (tag) {
  381. case LARGE_TAG_ANSISTR:
  382. strncpy(dev->name, p + 3,
  383. len >= PNP_NAME_LEN ? PNP_NAME_LEN - 2 : len);
  384. dev->name[len >=
  385. PNP_NAME_LEN ? PNP_NAME_LEN - 1 : len] = '\0';
  386. break;
  387. case SMALL_TAG_COMPATDEVID: /* compatible ID */
  388. if (len != 4)
  389. goto len_err;
  390. eisa_id = p[1] | p[2] << 8 | p[3] << 16 | p[4] << 24;
  391. pnp_eisa_id_to_string(eisa_id & PNP_EISA_ID_MASK, id);
  392. dev_id = pnp_add_id(dev, id);
  393. if (!dev_id)
  394. return NULL;
  395. break;
  396. case SMALL_TAG_END:
  397. p = p + 2;
  398. return (unsigned char *)p;
  399. break;
  400. default: /* an unkown tag */
  401. len_err:
  402. dev_err(&dev->dev, "unknown tag %#x length %d\n",
  403. tag, len);
  404. break;
  405. }
  406. /* continue to the next tag */
  407. if (p[0] & LARGE_TAG)
  408. p += len + 3;
  409. else
  410. p += len + 1;
  411. }
  412. dev_err(&dev->dev, "no end tag in resource structure\n");
  413. return NULL;
  414. }
  415. /*
  416. * Allocated Resource Encoding
  417. */
  418. static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p,
  419. struct resource *res)
  420. {
  421. unsigned long base;
  422. unsigned long len;
  423. if (pnp_resource_enabled(res)) {
  424. base = res->start;
  425. len = res->end - res->start + 1;
  426. } else {
  427. base = 0;
  428. len = 0;
  429. }
  430. p[4] = (base >> 8) & 0xff;
  431. p[5] = ((base >> 8) >> 8) & 0xff;
  432. p[6] = (base >> 8) & 0xff;
  433. p[7] = ((base >> 8) >> 8) & 0xff;
  434. p[10] = (len >> 8) & 0xff;
  435. p[11] = ((len >> 8) >> 8) & 0xff;
  436. dev_dbg(&dev->dev, " encode mem %#lx-%#lx\n", base, base + len - 1);
  437. }
  438. static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p,
  439. struct resource *res)
  440. {
  441. unsigned long base;
  442. unsigned long len;
  443. if (pnp_resource_enabled(res)) {
  444. base = res->start;
  445. len = res->end - res->start + 1;
  446. } else {
  447. base = 0;
  448. len = 0;
  449. }
  450. p[4] = base & 0xff;
  451. p[5] = (base >> 8) & 0xff;
  452. p[6] = (base >> 16) & 0xff;
  453. p[7] = (base >> 24) & 0xff;
  454. p[8] = base & 0xff;
  455. p[9] = (base >> 8) & 0xff;
  456. p[10] = (base >> 16) & 0xff;
  457. p[11] = (base >> 24) & 0xff;
  458. p[16] = len & 0xff;
  459. p[17] = (len >> 8) & 0xff;
  460. p[18] = (len >> 16) & 0xff;
  461. p[19] = (len >> 24) & 0xff;
  462. dev_dbg(&dev->dev, " encode mem32 %#lx-%#lx\n", base, base + len - 1);
  463. }
  464. static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p,
  465. struct resource *res)
  466. {
  467. unsigned long base;
  468. unsigned long len;
  469. if (pnp_resource_enabled(res)) {
  470. base = res->start;
  471. len = res->end - res->start + 1;
  472. } else {
  473. base = 0;
  474. len = 0;
  475. }
  476. p[4] = base & 0xff;
  477. p[5] = (base >> 8) & 0xff;
  478. p[6] = (base >> 16) & 0xff;
  479. p[7] = (base >> 24) & 0xff;
  480. p[8] = len & 0xff;
  481. p[9] = (len >> 8) & 0xff;
  482. p[10] = (len >> 16) & 0xff;
  483. p[11] = (len >> 24) & 0xff;
  484. dev_dbg(&dev->dev, " encode fixed_mem32 %#lx-%#lx\n", base,
  485. base + len - 1);
  486. }
  487. static void pnpbios_encode_irq(struct pnp_dev *dev, unsigned char *p,
  488. struct resource *res)
  489. {
  490. unsigned long map;
  491. if (pnp_resource_enabled(res))
  492. map = 1 << res->start;
  493. else
  494. map = 0;
  495. p[1] = map & 0xff;
  496. p[2] = (map >> 8) & 0xff;
  497. dev_dbg(&dev->dev, " encode irq mask %#lx\n", map);
  498. }
  499. static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p,
  500. struct resource *res)
  501. {
  502. unsigned long map;
  503. if (pnp_resource_enabled(res))
  504. map = 1 << res->start;
  505. else
  506. map = 0;
  507. p[1] = map & 0xff;
  508. dev_dbg(&dev->dev, " encode dma mask %#lx\n", map);
  509. }
  510. static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p,
  511. struct resource *res)
  512. {
  513. unsigned long base;
  514. unsigned long len;
  515. if (pnp_resource_enabled(res)) {
  516. base = res->start;
  517. len = res->end - res->start + 1;
  518. } else {
  519. base = 0;
  520. len = 0;
  521. }
  522. p[2] = base & 0xff;
  523. p[3] = (base >> 8) & 0xff;
  524. p[4] = base & 0xff;
  525. p[5] = (base >> 8) & 0xff;
  526. p[7] = len & 0xff;
  527. dev_dbg(&dev->dev, " encode io %#lx-%#lx\n", base, base + len - 1);
  528. }
  529. static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p,
  530. struct resource *res)
  531. {
  532. unsigned long base = res->start;
  533. unsigned long len = res->end - res->start + 1;
  534. if (pnp_resource_enabled(res)) {
  535. base = res->start;
  536. len = res->end - res->start + 1;
  537. } else {
  538. base = 0;
  539. len = 0;
  540. }
  541. p[1] = base & 0xff;
  542. p[2] = (base >> 8) & 0xff;
  543. p[3] = len & 0xff;
  544. dev_dbg(&dev->dev, " encode fixed_io %#lx-%#lx\n", base,
  545. base + len - 1);
  546. }
  547. static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev
  548. *dev,
  549. unsigned char *p,
  550. unsigned char *end)
  551. {
  552. unsigned int len, tag;
  553. int port = 0, irq = 0, dma = 0, mem = 0;
  554. if (!p)
  555. return NULL;
  556. while ((char *)p < (char *)end) {
  557. /* determine the type of tag */
  558. if (p[0] & LARGE_TAG) { /* large tag */
  559. len = (p[2] << 8) | p[1];
  560. tag = p[0];
  561. } else { /* small tag */
  562. len = p[0] & 0x07;
  563. tag = ((p[0] >> 3) & 0x0f);
  564. }
  565. switch (tag) {
  566. case LARGE_TAG_MEM:
  567. if (len != 9)
  568. goto len_err;
  569. pnpbios_encode_mem(dev, p,
  570. pnp_get_resource(dev, IORESOURCE_MEM, mem));
  571. mem++;
  572. break;
  573. case LARGE_TAG_MEM32:
  574. if (len != 17)
  575. goto len_err;
  576. pnpbios_encode_mem32(dev, p,
  577. pnp_get_resource(dev, IORESOURCE_MEM, mem));
  578. mem++;
  579. break;
  580. case LARGE_TAG_FIXEDMEM32:
  581. if (len != 9)
  582. goto len_err;
  583. pnpbios_encode_fixed_mem32(dev, p,
  584. pnp_get_resource(dev, IORESOURCE_MEM, mem));
  585. mem++;
  586. break;
  587. case SMALL_TAG_IRQ:
  588. if (len < 2 || len > 3)
  589. goto len_err;
  590. pnpbios_encode_irq(dev, p,
  591. pnp_get_resource(dev, IORESOURCE_IRQ, irq));
  592. irq++;
  593. break;
  594. case SMALL_TAG_DMA:
  595. if (len != 2)
  596. goto len_err;
  597. pnpbios_encode_dma(dev, p,
  598. pnp_get_resource(dev, IORESOURCE_DMA, dma));
  599. dma++;
  600. break;
  601. case SMALL_TAG_PORT:
  602. if (len != 7)
  603. goto len_err;
  604. pnpbios_encode_port(dev, p,
  605. pnp_get_resource(dev, IORESOURCE_IO, port));
  606. port++;
  607. break;
  608. case SMALL_TAG_VENDOR:
  609. /* do nothing */
  610. break;
  611. case SMALL_TAG_FIXEDPORT:
  612. if (len != 3)
  613. goto len_err;
  614. pnpbios_encode_fixed_port(dev, p,
  615. pnp_get_resource(dev, IORESOURCE_IO, port));
  616. port++;
  617. break;
  618. case SMALL_TAG_END:
  619. p = p + 2;
  620. return (unsigned char *)p;
  621. break;
  622. default: /* an unkown tag */
  623. len_err:
  624. dev_err(&dev->dev, "unknown tag %#x length %d\n",
  625. tag, len);
  626. break;
  627. }
  628. /* continue to the next tag */
  629. if (p[0] & LARGE_TAG)
  630. p += len + 3;
  631. else
  632. p += len + 1;
  633. }
  634. dev_err(&dev->dev, "no end tag in resource structure\n");
  635. return NULL;
  636. }
  637. /*
  638. * Core Parsing Functions
  639. */
  640. int __init pnpbios_parse_data_stream(struct pnp_dev *dev,
  641. struct pnp_bios_node *node)
  642. {
  643. unsigned char *p = (char *)node->data;
  644. unsigned char *end = (char *)(node->data + node->size);
  645. p = pnpbios_parse_allocated_resource_data(dev, p, end);
  646. if (!p)
  647. return -EIO;
  648. p = pnpbios_parse_resource_option_data(p, end, dev);
  649. if (!p)
  650. return -EIO;
  651. p = pnpbios_parse_compatible_ids(p, end, dev);
  652. if (!p)
  653. return -EIO;
  654. return 0;
  655. }
  656. int pnpbios_read_resources_from_node(struct pnp_dev *dev,
  657. struct pnp_bios_node *node)
  658. {
  659. unsigned char *p = (char *)node->data;
  660. unsigned char *end = (char *)(node->data + node->size);
  661. p = pnpbios_parse_allocated_resource_data(dev, p, end);
  662. if (!p)
  663. return -EIO;
  664. return 0;
  665. }
  666. int pnpbios_write_resources_to_node(struct pnp_dev *dev,
  667. struct pnp_bios_node *node)
  668. {
  669. unsigned char *p = (char *)node->data;
  670. unsigned char *end = (char *)(node->data + node->size);
  671. p = pnpbios_encode_allocated_resource_data(dev, p, end);
  672. if (!p)
  673. return -EIO;
  674. return 0;
  675. }