blob: d3b0a4e5369218bc73886cd0796b35d8a893b160 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * rsparser.c - parses and encodes pnpbios resource data streams
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 */
4
Linus Torvalds1da177e2005-04-16 15:20:36 -07005#include <linux/ctype.h>
6#include <linux/pnp.h>
7#include <linux/pnpbios.h>
Tim Schmielau4e57b682005-10-30 15:03:48 -08008#include <linux/string.h>
9#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010
11#ifdef CONFIG_PCI
12#include <linux/pci.h>
13#else
Bjorn Helgaas9dd78462007-07-26 10:41:20 -070014inline void pcibios_penalize_isa_irq(int irq, int active)
15{
16}
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -070017#endif /* CONFIG_PCI */
Linus Torvalds1da177e2005-04-16 15:20:36 -070018
Bjorn Helgaas772defc2008-04-28 16:33:52 -060019#include "../base.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include "pnpbios.h"
21
22/* standard resource tags */
23#define SMALL_TAG_PNPVERNO 0x01
24#define SMALL_TAG_LOGDEVID 0x02
25#define SMALL_TAG_COMPATDEVID 0x03
26#define SMALL_TAG_IRQ 0x04
27#define SMALL_TAG_DMA 0x05
28#define SMALL_TAG_STARTDEP 0x06
29#define SMALL_TAG_ENDDEP 0x07
30#define SMALL_TAG_PORT 0x08
31#define SMALL_TAG_FIXEDPORT 0x09
32#define SMALL_TAG_VENDOR 0x0e
33#define SMALL_TAG_END 0x0f
34#define LARGE_TAG 0x80
35#define LARGE_TAG_MEM 0x81
36#define LARGE_TAG_ANSISTR 0x82
37#define LARGE_TAG_UNICODESTR 0x83
38#define LARGE_TAG_VENDOR 0x84
39#define LARGE_TAG_MEM32 0x85
40#define LARGE_TAG_FIXEDMEM32 0x86
41
42/*
43 * Resource Data Stream Format:
44 *
45 * Allocated Resources (required)
46 * end tag ->
47 * Resource Configuration Options (optional)
48 * end tag ->
49 * Compitable Device IDs (optional)
50 * final end tag ->
51 */
52
53/*
54 * Allocated Resources
55 */
56
Bjorn Helgaas4ab55d82008-04-28 16:34:06 -060057static void pnpbios_parse_allocated_irqresource(struct pnp_dev *dev, int irq)
Linus Torvalds1da177e2005-04-16 15:20:36 -070058{
Bjorn Helgaas06cb58a2008-04-28 16:34:29 -060059 struct resource *res;
60 int i;
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -070061
Bjorn Helgaas06cb58a2008-04-28 16:34:29 -060062 for (i = 0; i < PNP_MAX_IRQ; i++) {
63 res = pnp_get_resource(dev, IORESOURCE_IRQ, i);
64 if (!pnp_resource_valid(res))
65 break;
66 }
67
Linus Torvalds1da177e2005-04-16 15:20:36 -070068 if (i < PNP_MAX_IRQ) {
Bjorn Helgaas06cb58a2008-04-28 16:34:29 -060069 res->flags = IORESOURCE_IRQ; // Also clears _UNSET flag
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 if (irq == -1) {
Bjorn Helgaas06cb58a2008-04-28 16:34:29 -060071 res->flags |= IORESOURCE_DISABLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 return;
73 }
Bjorn Helgaas06cb58a2008-04-28 16:34:29 -060074 res->start = res->end = (unsigned long)irq;
David Shaohua Lic9c3e452005-04-01 00:07:31 -050075 pcibios_penalize_isa_irq(irq, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 }
77}
78
Bjorn Helgaas4ab55d82008-04-28 16:34:06 -060079static void pnpbios_parse_allocated_dmaresource(struct pnp_dev *dev, int dma)
Linus Torvalds1da177e2005-04-16 15:20:36 -070080{
Bjorn Helgaas06cb58a2008-04-28 16:34:29 -060081 struct resource *res;
82 int i;
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -070083
Bjorn Helgaas06cb58a2008-04-28 16:34:29 -060084 for (i = 0; i < PNP_MAX_DMA; i++) {
85 res = pnp_get_resource(dev, IORESOURCE_DMA, i);
86 if (!pnp_resource_valid(res))
87 break;
88 }
89
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 if (i < PNP_MAX_DMA) {
Bjorn Helgaas06cb58a2008-04-28 16:34:29 -060091 res->flags = IORESOURCE_DMA; // Also clears _UNSET flag
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 if (dma == -1) {
Bjorn Helgaas06cb58a2008-04-28 16:34:29 -060093 res->flags |= IORESOURCE_DISABLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -070094 return;
95 }
Bjorn Helgaas06cb58a2008-04-28 16:34:29 -060096 res->start = res->end = (unsigned long)dma;
Linus Torvalds1da177e2005-04-16 15:20:36 -070097 }
98}
99
Bjorn Helgaas4ab55d82008-04-28 16:34:06 -0600100static void pnpbios_parse_allocated_ioresource(struct pnp_dev *dev,
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -0700101 int io, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102{
Bjorn Helgaas06cb58a2008-04-28 16:34:29 -0600103 struct resource *res;
104 int i;
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -0700105
Bjorn Helgaas06cb58a2008-04-28 16:34:29 -0600106 for (i = 0; i < PNP_MAX_PORT; i++) {
107 res = pnp_get_resource(dev, IORESOURCE_IO, i);
108 if (!pnp_resource_valid(res))
109 break;
110 }
111
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 if (i < PNP_MAX_PORT) {
Bjorn Helgaas06cb58a2008-04-28 16:34:29 -0600113 res->flags = IORESOURCE_IO; // Also clears _UNSET flag
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700114 if (len <= 0 || (io + len - 1) >= 0x10003) {
Bjorn Helgaas06cb58a2008-04-28 16:34:29 -0600115 res->flags |= IORESOURCE_DISABLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116 return;
117 }
Bjorn Helgaas06cb58a2008-04-28 16:34:29 -0600118 res->start = (unsigned long)io;
119 res->end = (unsigned long)(io + len - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 }
121}
122
Bjorn Helgaas4ab55d82008-04-28 16:34:06 -0600123static void pnpbios_parse_allocated_memresource(struct pnp_dev *dev,
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -0700124 int mem, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125{
Bjorn Helgaas06cb58a2008-04-28 16:34:29 -0600126 struct resource *res;
127 int i;
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -0700128
Bjorn Helgaas06cb58a2008-04-28 16:34:29 -0600129 for (i = 0; i < PNP_MAX_MEM; i++) {
130 res = pnp_get_resource(dev, IORESOURCE_MEM, i);
131 if (!pnp_resource_valid(res))
132 break;
133 }
134
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135 if (i < PNP_MAX_MEM) {
Bjorn Helgaas06cb58a2008-04-28 16:34:29 -0600136 res->flags = IORESOURCE_MEM; // Also clears _UNSET flag
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 if (len <= 0) {
Bjorn Helgaas06cb58a2008-04-28 16:34:29 -0600138 res->flags |= IORESOURCE_DISABLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 return;
140 }
Bjorn Helgaas06cb58a2008-04-28 16:34:29 -0600141 res->start = (unsigned long)mem;
142 res->end = (unsigned long)(mem + len - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143 }
144}
145
Bjorn Helgaas4ab55d82008-04-28 16:34:06 -0600146static unsigned char *pnpbios_parse_allocated_resource_data(struct pnp_dev *dev,
147 unsigned char *p,
148 unsigned char *end)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149{
150 unsigned int len, tag;
151 int io, size, mask, i;
152
153 if (!p)
154 return NULL;
155
Bjorn Helgaas72dcc882008-04-28 16:34:07 -0600156 dev_dbg(&dev->dev, "parse allocated resources\n");
157
Bjorn Helgaasf4490002008-04-28 16:34:09 -0600158 pnp_init_resources(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159
160 while ((char *)p < (char *)end) {
161
162 /* determine the type of tag */
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700163 if (p[0] & LARGE_TAG) { /* large tag */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 len = (p[2] << 8) | p[1];
165 tag = p[0];
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700166 } else { /* small tag */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 len = p[0] & 0x07;
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700168 tag = ((p[0] >> 3) & 0x0f);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 }
170
171 switch (tag) {
172
173 case LARGE_TAG_MEM:
174 if (len != 9)
175 goto len_err;
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700176 io = *(short *)&p[4];
177 size = *(short *)&p[10];
Bjorn Helgaas4ab55d82008-04-28 16:34:06 -0600178 pnpbios_parse_allocated_memresource(dev, io, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 break;
180
181 case LARGE_TAG_ANSISTR:
182 /* ignore this for now */
183 break;
184
185 case LARGE_TAG_VENDOR:
186 /* do nothing */
187 break;
188
189 case LARGE_TAG_MEM32:
190 if (len != 17)
191 goto len_err;
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700192 io = *(int *)&p[4];
193 size = *(int *)&p[16];
Bjorn Helgaas4ab55d82008-04-28 16:34:06 -0600194 pnpbios_parse_allocated_memresource(dev, io, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 break;
196
197 case LARGE_TAG_FIXEDMEM32:
198 if (len != 9)
199 goto len_err;
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700200 io = *(int *)&p[4];
201 size = *(int *)&p[8];
Bjorn Helgaas4ab55d82008-04-28 16:34:06 -0600202 pnpbios_parse_allocated_memresource(dev, io, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 break;
204
205 case SMALL_TAG_IRQ:
206 if (len < 2 || len > 3)
207 goto len_err;
208 io = -1;
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700209 mask = p[1] + p[2] * 256;
210 for (i = 0; i < 16; i++, mask = mask >> 1)
211 if (mask & 0x01)
212 io = i;
Bjorn Helgaas4ab55d82008-04-28 16:34:06 -0600213 pnpbios_parse_allocated_irqresource(dev, io);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 break;
215
216 case SMALL_TAG_DMA:
217 if (len != 2)
218 goto len_err;
219 io = -1;
220 mask = p[1];
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700221 for (i = 0; i < 8; i++, mask = mask >> 1)
222 if (mask & 0x01)
223 io = i;
Bjorn Helgaas4ab55d82008-04-28 16:34:06 -0600224 pnpbios_parse_allocated_dmaresource(dev, io);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 break;
226
227 case SMALL_TAG_PORT:
228 if (len != 7)
229 goto len_err;
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700230 io = p[2] + p[3] * 256;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 size = p[7];
Bjorn Helgaas4ab55d82008-04-28 16:34:06 -0600232 pnpbios_parse_allocated_ioresource(dev, io, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 break;
234
235 case SMALL_TAG_VENDOR:
236 /* do nothing */
237 break;
238
239 case SMALL_TAG_FIXEDPORT:
240 if (len != 3)
241 goto len_err;
242 io = p[1] + p[2] * 256;
243 size = p[3];
Bjorn Helgaas4ab55d82008-04-28 16:34:06 -0600244 pnpbios_parse_allocated_ioresource(dev, io, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 break;
246
247 case SMALL_TAG_END:
248 p = p + 2;
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700249 return (unsigned char *)p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 break;
251
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700252 default: /* an unkown tag */
Bjorn Helgaas1e0aa9a2007-08-15 10:32:08 -0600253len_err:
Bjorn Helgaasaf11cb22008-04-28 16:34:12 -0600254 dev_err(&dev->dev, "unknown tag %#x length %d\n",
255 tag, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 break;
257 }
258
259 /* continue to the next tag */
260 if (p[0] & LARGE_TAG)
261 p += len + 3;
262 else
263 p += len + 1;
264 }
265
Bjorn Helgaasaf11cb22008-04-28 16:34:12 -0600266 dev_err(&dev->dev, "no end tag in resource structure\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
268 return NULL;
269}
270
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271/*
272 * Resource Configuration Options
273 */
274
Bjorn Helgaasc1caf062008-04-28 16:34:04 -0600275static __init void pnpbios_parse_mem_option(struct pnp_dev *dev,
276 unsigned char *p, int size,
Thomas Renninger2bb9a6b2008-02-06 01:40:03 -0800277 struct pnp_option *option)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278{
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700279 struct pnp_mem *mem;
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -0700280
Robert P. J. Daycd861282006-12-13 00:34:52 -0800281 mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 if (!mem)
283 return;
284 mem->min = ((p[5] << 8) | p[4]) << 8;
285 mem->max = ((p[7] << 8) | p[6]) << 8;
286 mem->align = (p[9] << 8) | p[8];
287 mem->size = ((p[11] << 8) | p[10]) << 8;
288 mem->flags = p[3];
Bjorn Helgaasc1caf062008-04-28 16:34:04 -0600289 pnp_register_mem_resource(dev, option, mem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290}
291
Bjorn Helgaasc1caf062008-04-28 16:34:04 -0600292static __init void pnpbios_parse_mem32_option(struct pnp_dev *dev,
293 unsigned char *p, int size,
Thomas Renninger2bb9a6b2008-02-06 01:40:03 -0800294 struct pnp_option *option)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295{
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700296 struct pnp_mem *mem;
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -0700297
Robert P. J. Daycd861282006-12-13 00:34:52 -0800298 mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 if (!mem)
300 return;
301 mem->min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
302 mem->max = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
303 mem->align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12];
304 mem->size = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16];
305 mem->flags = p[3];
Bjorn Helgaasc1caf062008-04-28 16:34:04 -0600306 pnp_register_mem_resource(dev, option, mem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307}
308
Bjorn Helgaasc1caf062008-04-28 16:34:04 -0600309static __init void pnpbios_parse_fixed_mem32_option(struct pnp_dev *dev,
310 unsigned char *p, int size,
Thomas Renninger2bb9a6b2008-02-06 01:40:03 -0800311 struct pnp_option *option)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312{
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700313 struct pnp_mem *mem;
Bjorn Helgaas1e0aa9a2007-08-15 10:32:08 -0600314
Robert P. J. Daycd861282006-12-13 00:34:52 -0800315 mem = kzalloc(sizeof(struct pnp_mem), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 if (!mem)
317 return;
318 mem->min = mem->max = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4];
319 mem->size = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8];
320 mem->align = 0;
321 mem->flags = p[3];
Bjorn Helgaasc1caf062008-04-28 16:34:04 -0600322 pnp_register_mem_resource(dev, option, mem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323}
324
Bjorn Helgaasc1caf062008-04-28 16:34:04 -0600325static __init void pnpbios_parse_irq_option(struct pnp_dev *dev,
326 unsigned char *p, int size,
327 struct pnp_option *option)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328{
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700329 struct pnp_irq *irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 unsigned long bits;
331
Robert P. J. Daycd861282006-12-13 00:34:52 -0800332 irq = kzalloc(sizeof(struct pnp_irq), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 if (!irq)
334 return;
335 bits = (p[2] << 8) | p[1];
336 bitmap_copy(irq->map, &bits, 16);
337 if (size > 2)
338 irq->flags = p[3];
339 else
340 irq->flags = IORESOURCE_IRQ_HIGHEDGE;
Bjorn Helgaasc1caf062008-04-28 16:34:04 -0600341 pnp_register_irq_resource(dev, option, irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342}
343
Bjorn Helgaasc1caf062008-04-28 16:34:04 -0600344static __init void pnpbios_parse_dma_option(struct pnp_dev *dev,
345 unsigned char *p, int size,
346 struct pnp_option *option)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347{
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700348 struct pnp_dma *dma;
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -0700349
Robert P. J. Daycd861282006-12-13 00:34:52 -0800350 dma = kzalloc(sizeof(struct pnp_dma), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 if (!dma)
352 return;
353 dma->map = p[1];
354 dma->flags = p[2];
Bjorn Helgaasc1caf062008-04-28 16:34:04 -0600355 pnp_register_dma_resource(dev, option, dma);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356}
357
Bjorn Helgaasc1caf062008-04-28 16:34:04 -0600358static __init void pnpbios_parse_port_option(struct pnp_dev *dev,
359 unsigned char *p, int size,
Thomas Renninger2bb9a6b2008-02-06 01:40:03 -0800360 struct pnp_option *option)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361{
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700362 struct pnp_port *port;
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -0700363
Robert P. J. Daycd861282006-12-13 00:34:52 -0800364 port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 if (!port)
366 return;
367 port->min = (p[3] << 8) | p[2];
368 port->max = (p[5] << 8) | p[4];
369 port->align = p[6];
370 port->size = p[7];
371 port->flags = p[1] ? PNP_PORT_FLAG_16BITADDR : 0;
Bjorn Helgaasc1caf062008-04-28 16:34:04 -0600372 pnp_register_port_resource(dev, option, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373}
374
Bjorn Helgaasc1caf062008-04-28 16:34:04 -0600375static __init void pnpbios_parse_fixed_port_option(struct pnp_dev *dev,
376 unsigned char *p, int size,
Thomas Renninger2bb9a6b2008-02-06 01:40:03 -0800377 struct pnp_option *option)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378{
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700379 struct pnp_port *port;
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -0700380
Robert P. J. Daycd861282006-12-13 00:34:52 -0800381 port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 if (!port)
383 return;
384 port->min = port->max = (p[2] << 8) | p[1];
385 port->size = p[3];
386 port->align = 0;
387 port->flags = PNP_PORT_FLAG_FIXED;
Bjorn Helgaasc1caf062008-04-28 16:34:04 -0600388 pnp_register_port_resource(dev, option, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389}
390
Thomas Renninger2bb9a6b2008-02-06 01:40:03 -0800391static __init unsigned char *
392pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
393 struct pnp_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394{
395 unsigned int len, tag;
396 int priority = 0;
397 struct pnp_option *option, *option_independent;
398
399 if (!p)
400 return NULL;
401
Bjorn Helgaas72dcc882008-04-28 16:34:07 -0600402 dev_dbg(&dev->dev, "parse resource options\n");
403
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404 option_independent = option = pnp_register_independent_option(dev);
405 if (!option)
406 return NULL;
407
408 while ((char *)p < (char *)end) {
409
410 /* determine the type of tag */
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700411 if (p[0] & LARGE_TAG) { /* large tag */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 len = (p[2] << 8) | p[1];
413 tag = p[0];
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700414 } else { /* small tag */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 len = p[0] & 0x07;
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700416 tag = ((p[0] >> 3) & 0x0f);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 }
418
419 switch (tag) {
420
421 case LARGE_TAG_MEM:
422 if (len != 9)
423 goto len_err;
Bjorn Helgaasc1caf062008-04-28 16:34:04 -0600424 pnpbios_parse_mem_option(dev, p, len, option);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 break;
426
427 case LARGE_TAG_MEM32:
428 if (len != 17)
429 goto len_err;
Bjorn Helgaasc1caf062008-04-28 16:34:04 -0600430 pnpbios_parse_mem32_option(dev, p, len, option);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 break;
432
433 case LARGE_TAG_FIXEDMEM32:
434 if (len != 9)
435 goto len_err;
Bjorn Helgaasc1caf062008-04-28 16:34:04 -0600436 pnpbios_parse_fixed_mem32_option(dev, p, len, option);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 break;
438
439 case SMALL_TAG_IRQ:
440 if (len < 2 || len > 3)
441 goto len_err;
Bjorn Helgaasc1caf062008-04-28 16:34:04 -0600442 pnpbios_parse_irq_option(dev, p, len, option);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 break;
444
445 case SMALL_TAG_DMA:
446 if (len != 2)
447 goto len_err;
Bjorn Helgaasc1caf062008-04-28 16:34:04 -0600448 pnpbios_parse_dma_option(dev, p, len, option);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 break;
450
451 case SMALL_TAG_PORT:
452 if (len != 7)
453 goto len_err;
Bjorn Helgaasc1caf062008-04-28 16:34:04 -0600454 pnpbios_parse_port_option(dev, p, len, option);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 break;
456
457 case SMALL_TAG_VENDOR:
458 /* do nothing */
459 break;
460
461 case SMALL_TAG_FIXEDPORT:
462 if (len != 3)
463 goto len_err;
Bjorn Helgaasc1caf062008-04-28 16:34:04 -0600464 pnpbios_parse_fixed_port_option(dev, p, len, option);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 break;
466
467 case SMALL_TAG_STARTDEP:
468 if (len > 1)
469 goto len_err;
470 priority = 0x100 | PNP_RES_PRIORITY_ACCEPTABLE;
471 if (len > 0)
472 priority = 0x100 | p[1];
473 option = pnp_register_dependent_option(dev, priority);
474 if (!option)
475 return NULL;
476 break;
477
478 case SMALL_TAG_ENDDEP:
479 if (len != 0)
480 goto len_err;
481 if (option_independent == option)
Bjorn Helgaasaf11cb22008-04-28 16:34:12 -0600482 dev_warn(&dev->dev, "missing "
483 "SMALL_TAG_STARTDEP tag\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 option = option_independent;
Bjorn Helgaasc1caf062008-04-28 16:34:04 -0600485 dev_dbg(&dev->dev, "end dependent options\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 break;
487
488 case SMALL_TAG_END:
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700489 return p + 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700491 default: /* an unkown tag */
Bjorn Helgaas1e0aa9a2007-08-15 10:32:08 -0600492len_err:
Bjorn Helgaasaf11cb22008-04-28 16:34:12 -0600493 dev_err(&dev->dev, "unknown tag %#x length %d\n",
494 tag, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 break;
496 }
497
498 /* continue to the next tag */
499 if (p[0] & LARGE_TAG)
500 p += len + 3;
501 else
502 p += len + 1;
503 }
504
Bjorn Helgaasaf11cb22008-04-28 16:34:12 -0600505 dev_err(&dev->dev, "no end tag in resource structure\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
507 return NULL;
508}
509
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510/*
511 * Compatible Device IDs
512 */
513
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700514static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p,
515 unsigned char *end,
516 struct pnp_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517{
518 int len, tag;
Bjorn Helgaas25eb8462008-04-28 16:33:53 -0600519 u32 eisa_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 char id[8];
521 struct pnp_id *dev_id;
522
523 if (!p)
524 return NULL;
525
526 while ((char *)p < (char *)end) {
527
528 /* determine the type of tag */
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700529 if (p[0] & LARGE_TAG) { /* large tag */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 len = (p[2] << 8) | p[1];
531 tag = p[0];
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700532 } else { /* small tag */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 len = p[0] & 0x07;
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700534 tag = ((p[0] >> 3) & 0x0f);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 }
536
537 switch (tag) {
538
539 case LARGE_TAG_ANSISTR:
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700540 strncpy(dev->name, p + 3,
541 len >= PNP_NAME_LEN ? PNP_NAME_LEN - 2 : len);
542 dev->name[len >=
543 PNP_NAME_LEN ? PNP_NAME_LEN - 1 : len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 break;
545
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700546 case SMALL_TAG_COMPATDEVID: /* compatible ID */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 if (len != 4)
548 goto len_err;
Bjorn Helgaas25eb8462008-04-28 16:33:53 -0600549 eisa_id = p[1] | p[2] << 8 | p[3] << 16 | p[4] << 24;
550 pnp_eisa_id_to_string(eisa_id & PNP_EISA_ID_MASK, id);
Bjorn Helgaas772defc2008-04-28 16:33:52 -0600551 dev_id = pnp_add_id(dev, id);
552 if (!dev_id)
553 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 break;
555
556 case SMALL_TAG_END:
557 p = p + 2;
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700558 return (unsigned char *)p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 break;
560
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700561 default: /* an unkown tag */
Bjorn Helgaas1e0aa9a2007-08-15 10:32:08 -0600562len_err:
Bjorn Helgaasaf11cb22008-04-28 16:34:12 -0600563 dev_err(&dev->dev, "unknown tag %#x length %d\n",
564 tag, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 break;
566 }
567
568 /* continue to the next tag */
569 if (p[0] & LARGE_TAG)
570 p += len + 3;
571 else
572 p += len + 1;
573 }
574
Bjorn Helgaasaf11cb22008-04-28 16:34:12 -0600575 dev_err(&dev->dev, "no end tag in resource structure\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576
577 return NULL;
578}
579
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580/*
581 * Allocated Resource Encoding
582 */
583
Bjorn Helgaas72dcc882008-04-28 16:34:07 -0600584static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p,
585 struct resource *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586{
587 unsigned long base = res->start;
588 unsigned long len = res->end - res->start + 1;
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -0700589
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 p[4] = (base >> 8) & 0xff;
591 p[5] = ((base >> 8) >> 8) & 0xff;
592 p[6] = (base >> 8) & 0xff;
593 p[7] = ((base >> 8) >> 8) & 0xff;
594 p[10] = (len >> 8) & 0xff;
595 p[11] = ((len >> 8) >> 8) & 0xff;
Bjorn Helgaas72dcc882008-04-28 16:34:07 -0600596
597 dev_dbg(&dev->dev, " encode mem %#llx-%#llx\n",
598 (unsigned long long) res->start, (unsigned long long) res->end);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599}
600
Bjorn Helgaas72dcc882008-04-28 16:34:07 -0600601static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p,
602 struct resource *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603{
604 unsigned long base = res->start;
605 unsigned long len = res->end - res->start + 1;
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -0700606
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 p[4] = base & 0xff;
608 p[5] = (base >> 8) & 0xff;
609 p[6] = (base >> 16) & 0xff;
610 p[7] = (base >> 24) & 0xff;
611 p[8] = base & 0xff;
612 p[9] = (base >> 8) & 0xff;
613 p[10] = (base >> 16) & 0xff;
614 p[11] = (base >> 24) & 0xff;
615 p[16] = len & 0xff;
616 p[17] = (len >> 8) & 0xff;
617 p[18] = (len >> 16) & 0xff;
618 p[19] = (len >> 24) & 0xff;
Bjorn Helgaas72dcc882008-04-28 16:34:07 -0600619
620 dev_dbg(&dev->dev, " encode mem32 %#llx-%#llx\n",
621 (unsigned long long) res->start, (unsigned long long) res->end);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622}
623
Bjorn Helgaas72dcc882008-04-28 16:34:07 -0600624static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p,
625 struct resource *res)
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700626{
627 unsigned long base = res->start;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 unsigned long len = res->end - res->start + 1;
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -0700629
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 p[4] = base & 0xff;
631 p[5] = (base >> 8) & 0xff;
632 p[6] = (base >> 16) & 0xff;
633 p[7] = (base >> 24) & 0xff;
634 p[8] = len & 0xff;
635 p[9] = (len >> 8) & 0xff;
636 p[10] = (len >> 16) & 0xff;
637 p[11] = (len >> 24) & 0xff;
Bjorn Helgaas72dcc882008-04-28 16:34:07 -0600638
639 dev_dbg(&dev->dev, " encode fixed_mem32 %#llx-%#llx\n",
640 (unsigned long long) res->start, (unsigned long long) res->end);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641}
642
Bjorn Helgaas72dcc882008-04-28 16:34:07 -0600643static void pnpbios_encode_irq(struct pnp_dev *dev, unsigned char *p,
644 struct resource *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645{
646 unsigned long map = 0;
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -0700647
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 map = 1 << res->start;
649 p[1] = map & 0xff;
650 p[2] = (map >> 8) & 0xff;
Bjorn Helgaas72dcc882008-04-28 16:34:07 -0600651
652 dev_dbg(&dev->dev, " encode irq %d\n", res->start);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653}
654
Bjorn Helgaas72dcc882008-04-28 16:34:07 -0600655static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p,
656 struct resource *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657{
658 unsigned long map = 0;
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -0700659
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 map = 1 << res->start;
661 p[1] = map & 0xff;
Bjorn Helgaas72dcc882008-04-28 16:34:07 -0600662
663 dev_dbg(&dev->dev, " encode dma %d\n", res->start);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664}
665
Bjorn Helgaas72dcc882008-04-28 16:34:07 -0600666static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p,
667 struct resource *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668{
669 unsigned long base = res->start;
670 unsigned long len = res->end - res->start + 1;
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -0700671
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 p[2] = base & 0xff;
673 p[3] = (base >> 8) & 0xff;
674 p[4] = base & 0xff;
675 p[5] = (base >> 8) & 0xff;
676 p[7] = len & 0xff;
Bjorn Helgaas72dcc882008-04-28 16:34:07 -0600677
678 dev_dbg(&dev->dev, " encode io %#llx-%#llx\n",
679 (unsigned long long) res->start, (unsigned long long) res->end);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680}
681
Bjorn Helgaas72dcc882008-04-28 16:34:07 -0600682static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p,
683 struct resource *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684{
685 unsigned long base = res->start;
686 unsigned long len = res->end - res->start + 1;
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -0700687
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 p[1] = base & 0xff;
689 p[2] = (base >> 8) & 0xff;
690 p[3] = len & 0xff;
Bjorn Helgaas72dcc882008-04-28 16:34:07 -0600691
692 dev_dbg(&dev->dev, " encode fixed_io %#llx-%#llx\n",
693 (unsigned long long) res->start, (unsigned long long) res->end);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694}
695
Bjorn Helgaas4ab55d82008-04-28 16:34:06 -0600696static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev
697 *dev,
698 unsigned char *p,
699 unsigned char *end)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700{
701 unsigned int len, tag;
702 int port = 0, irq = 0, dma = 0, mem = 0;
703
704 if (!p)
705 return NULL;
706
707 while ((char *)p < (char *)end) {
708
709 /* determine the type of tag */
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700710 if (p[0] & LARGE_TAG) { /* large tag */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 len = (p[2] << 8) | p[1];
712 tag = p[0];
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700713 } else { /* small tag */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 len = p[0] & 0x07;
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700715 tag = ((p[0] >> 3) & 0x0f);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 }
717
718 switch (tag) {
719
720 case LARGE_TAG_MEM:
721 if (len != 9)
722 goto len_err;
Bjorn Helgaas7e2cf312008-04-28 16:34:24 -0600723 pnpbios_encode_mem(dev, p,
724 pnp_get_resource(dev, IORESOURCE_MEM, mem));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 mem++;
726 break;
727
728 case LARGE_TAG_MEM32:
729 if (len != 17)
730 goto len_err;
Bjorn Helgaas7e2cf312008-04-28 16:34:24 -0600731 pnpbios_encode_mem32(dev, p,
732 pnp_get_resource(dev, IORESOURCE_MEM, mem));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 mem++;
734 break;
735
736 case LARGE_TAG_FIXEDMEM32:
737 if (len != 9)
738 goto len_err;
Bjorn Helgaas7e2cf312008-04-28 16:34:24 -0600739 pnpbios_encode_fixed_mem32(dev, p,
740 pnp_get_resource(dev, IORESOURCE_MEM, mem));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 mem++;
742 break;
743
744 case SMALL_TAG_IRQ:
745 if (len < 2 || len > 3)
746 goto len_err;
Bjorn Helgaas7e2cf312008-04-28 16:34:24 -0600747 pnpbios_encode_irq(dev, p,
748 pnp_get_resource(dev, IORESOURCE_IRQ, irq));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 irq++;
750 break;
751
752 case SMALL_TAG_DMA:
753 if (len != 2)
754 goto len_err;
Bjorn Helgaas7e2cf312008-04-28 16:34:24 -0600755 pnpbios_encode_dma(dev, p,
756 pnp_get_resource(dev, IORESOURCE_DMA, dma));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 dma++;
758 break;
759
760 case SMALL_TAG_PORT:
761 if (len != 7)
762 goto len_err;
Bjorn Helgaas7e2cf312008-04-28 16:34:24 -0600763 pnpbios_encode_port(dev, p,
764 pnp_get_resource(dev, IORESOURCE_IO, port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 port++;
766 break;
767
768 case SMALL_TAG_VENDOR:
769 /* do nothing */
770 break;
771
772 case SMALL_TAG_FIXEDPORT:
773 if (len != 3)
774 goto len_err;
Bjorn Helgaas7e2cf312008-04-28 16:34:24 -0600775 pnpbios_encode_fixed_port(dev, p,
776 pnp_get_resource(dev, IORESOURCE_IO, port));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 port++;
778 break;
779
780 case SMALL_TAG_END:
781 p = p + 2;
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700782 return (unsigned char *)p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 break;
784
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700785 default: /* an unkown tag */
Bjorn Helgaas1e0aa9a2007-08-15 10:32:08 -0600786len_err:
Bjorn Helgaasaf11cb22008-04-28 16:34:12 -0600787 dev_err(&dev->dev, "unknown tag %#x length %d\n",
788 tag, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 break;
790 }
791
792 /* continue to the next tag */
793 if (p[0] & LARGE_TAG)
794 p += len + 3;
795 else
796 p += len + 1;
797 }
798
Bjorn Helgaasaf11cb22008-04-28 16:34:12 -0600799 dev_err(&dev->dev, "no end tag in resource structure\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800
801 return NULL;
802}
803
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804/*
805 * Core Parsing Functions
806 */
807
Thomas Renninger2bb9a6b2008-02-06 01:40:03 -0800808int __init pnpbios_parse_data_stream(struct pnp_dev *dev,
809 struct pnp_bios_node *node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810{
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700811 unsigned char *p = (char *)node->data;
812 unsigned char *end = (char *)(node->data + node->size);
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -0700813
Bjorn Helgaas4ab55d82008-04-28 16:34:06 -0600814 p = pnpbios_parse_allocated_resource_data(dev, p, end);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 if (!p)
816 return -EIO;
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700817 p = pnpbios_parse_resource_option_data(p, end, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 if (!p)
819 return -EIO;
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700820 p = pnpbios_parse_compatible_ids(p, end, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 if (!p)
822 return -EIO;
823 return 0;
824}
825
Bjorn Helgaas4ab55d82008-04-28 16:34:06 -0600826int pnpbios_read_resources_from_node(struct pnp_dev *dev,
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -0700827 struct pnp_bios_node *node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828{
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700829 unsigned char *p = (char *)node->data;
830 unsigned char *end = (char *)(node->data + node->size);
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -0700831
Bjorn Helgaas4ab55d82008-04-28 16:34:06 -0600832 p = pnpbios_parse_allocated_resource_data(dev, p, end);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 if (!p)
834 return -EIO;
835 return 0;
836}
837
Bjorn Helgaas4ab55d82008-04-28 16:34:06 -0600838int pnpbios_write_resources_to_node(struct pnp_dev *dev,
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -0700839 struct pnp_bios_node *node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840{
Bjorn Helgaas9dd78462007-07-26 10:41:20 -0700841 unsigned char *p = (char *)node->data;
842 unsigned char *end = (char *)(node->data + node->size);
Bjorn Helgaas07d4e9a2007-07-26 10:41:21 -0700843
Bjorn Helgaas4ab55d82008-04-28 16:34:06 -0600844 p = pnpbios_encode_allocated_resource_data(dev, p, end);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 if (!p)
846 return -EIO;
847 return 0;
848}