/* * Resource Data Stream Format: * * Allocated Resources (required) * end tag -> * Resource Configuration Options (optional) * end tag -> * Compitable Device IDs (optional) * final end tag ->
*/
/* * Allocated Resources
*/
staticvoid pnpbios_parse_allocated_ioresource(struct pnp_dev *dev, int start, int len)
{ int flags = 0; int end = start + len - 1;
if (len <= 0 || end >= 0x10003)
flags |= IORESOURCE_DISABLED;
pnp_add_io_resource(dev, start, end, flags);
}
staticvoid pnpbios_parse_allocated_memresource(struct pnp_dev *dev, int start, int len)
{ int flags = 0; int end = start + len - 1;
if (len <= 0)
flags |= IORESOURCE_DISABLED;
pnp_add_mem_resource(dev, start, end, flags);
}
staticunsignedchar *pnpbios_parse_allocated_resource_data(struct pnp_dev *dev, unsignedchar *p, unsignedchar *end)
{ unsignedint len, tag; int io, size, mask, i, flags;
/* determine the type of tag */ if (p[0] & LARGE_TAG) { /* large tag */
len = (p[2] << 8) | p[1];
tag = p[0];
} else { /* small tag */
len = p[0] & 0x07;
tag = ((p[0] >> 3) & 0x0f);
}
switch (tag) {
case LARGE_TAG_MEM: if (len != 9) goto len_err;
io = *(short *)&p[4];
size = *(short *)&p[10];
pnpbios_parse_allocated_memresource(dev, io, size); break;
case LARGE_TAG_ANSISTR: /* ignore this for now */ break;
case LARGE_TAG_VENDOR: /* do nothing */ break;
case LARGE_TAG_MEM32: if (len != 17) goto len_err;
io = *(int *)&p[4];
size = *(int *)&p[16];
pnpbios_parse_allocated_memresource(dev, io, size); break;
case LARGE_TAG_FIXEDMEM32: if (len != 9) goto len_err;
io = *(int *)&p[4];
size = *(int *)&p[8];
pnpbios_parse_allocated_memresource(dev, io, size); break;
case SMALL_TAG_IRQ: if (len < 2 || len > 3) goto len_err;
flags = 0;
io = -1;
mask = p[1] + p[2] * 256; for (i = 0; i < 16; i++, mask = mask >> 1) if (mask & 0x01)
io = i; if (io != -1)
pcibios_penalize_isa_irq(io, 1); else
flags = IORESOURCE_DISABLED;
pnp_add_irq_resource(dev, io, flags); break;
case SMALL_TAG_DMA: if (len != 2) goto len_err;
flags = 0;
io = -1;
mask = p[1]; for (i = 0; i < 8; i++, mask = mask >> 1) if (mask & 0x01)
io = i; if (io == -1)
flags = IORESOURCE_DISABLED;
pnp_add_dma_resource(dev, io, flags); break;
/* determine the type of tag */ if (p[0] & LARGE_TAG) { /* large tag */
len = (p[2] << 8) | p[1];
tag = p[0];
} else { /* small tag */
len = p[0] & 0x07;
tag = ((p[0] >> 3) & 0x0f);
}
switch (tag) {
case LARGE_TAG_MEM: if (len != 9) goto len_err;
pnpbios_parse_mem_option(dev, p, len, option_flags); break;
case LARGE_TAG_MEM32: if (len != 17) goto len_err;
pnpbios_parse_mem32_option(dev, p, len, option_flags); break;
case LARGE_TAG_FIXEDMEM32: if (len != 9) goto len_err;
pnpbios_parse_fixed_mem32_option(dev, p, len,
option_flags); break;
case SMALL_TAG_IRQ: if (len < 2 || len > 3) goto len_err;
pnpbios_parse_irq_option(dev, p, len, option_flags); break;
case SMALL_TAG_DMA: if (len != 2) goto len_err;
pnpbios_parse_dma_option(dev, p, len, option_flags); break;
case SMALL_TAG_PORT: if (len != 7) goto len_err;
pnpbios_parse_port_option(dev, p, len, option_flags); break;
case SMALL_TAG_VENDOR: /* do nothing */ break;
case SMALL_TAG_FIXEDPORT: if (len != 3) goto len_err;
pnpbios_parse_fixed_port_option(dev, p, len,
option_flags); break;
case SMALL_TAG_STARTDEP: if (len > 1) goto len_err;
priority = PNP_RES_PRIORITY_ACCEPTABLE; if (len > 0)
priority = p[1];
option_flags = pnp_new_dependent_set(dev, priority); break;
case SMALL_TAG_ENDDEP: if (len != 0) goto len_err;
option_flags = 0; break;
case SMALL_TAG_END: return p + 2;
default: /* an unknown tag */
len_err:
dev_err(&dev->dev, "unknown tag %#x length %d\n",
tag, len); break;
}
/* continue to the next tag */ if (p[0] & LARGE_TAG)
p += len + 3; else
p += len + 1;
}
dev_err(&dev->dev, "no end tag in resource structure\n");
/* determine the type of tag */ if (p[0] & LARGE_TAG) { /* large tag */
len = (p[2] << 8) | p[1];
tag = p[0];
} else { /* small tag */
len = p[0] & 0x07;
tag = ((p[0] >> 3) & 0x0f);
}
switch (tag) {
case LARGE_TAG_ANSISTR:
memcpy(dev->name, p + 3,
len >= PNP_NAME_LEN ? PNP_NAME_LEN - 2 : len);
dev->name[len >=
PNP_NAME_LEN ? PNP_NAME_LEN - 1 : len] = '\0'; break;
case SMALL_TAG_COMPATDEVID: /* compatible ID */ if (len != 4) goto len_err;
eisa_id = p[1] | p[2] << 8 | p[3] << 16 | p[4] << 24;
pnp_eisa_id_to_string(eisa_id & PNP_EISA_ID_MASK, id);
dev_id = pnp_add_id(dev, id); if (!dev_id) return NULL; break;
case SMALL_TAG_END:
p = p + 2; return (unsignedchar *)p; break;
default: /* an unknown tag */
len_err:
dev_err(&dev->dev, "unknown tag %#x length %d\n",
tag, len); break;
}
/* continue to the next tag */ if (p[0] & LARGE_TAG)
p += len + 3; else
p += len + 1;
}
dev_err(&dev->dev, "no end tag in resource structure\n");
if (pnp_resource_enabled(res)) {
base = res->start;
len = resource_size(res);
} else {
base = 0;
len = 0;
}
p[2] = base & 0xff;
p[3] = (base >> 8) & 0xff;
p[4] = base & 0xff;
p[5] = (base >> 8) & 0xff;
p[7] = len & 0xff;
pnp_dbg(&dev->dev, " encode io %#lx-%#lx\n", base, base + len - 1);
}
staticvoid pnpbios_encode_fixed_port(struct pnp_dev *dev, unsignedchar *p, struct resource *res)
{ unsignedlong base = res->start; unsignedlong len = resource_size(res);
if (pnp_resource_enabled(res)) {
base = res->start;
len = resource_size(res);
} else {
base = 0;
len = 0;
}
p[1] = base & 0xff;
p[2] = (base >> 8) & 0xff;
p[3] = len & 0xff;
pnp_dbg(&dev->dev, " encode fixed_io %#lx-%#lx\n", base,
base + len - 1);
}
staticunsignedchar *pnpbios_encode_allocated_resource_data(struct pnp_dev
*dev, unsignedchar *p, unsignedchar *end)
{ unsignedint len, tag; int port = 0, irq = 0, dma = 0, mem = 0;
if (!p) return NULL;
while ((char *)p < (char *)end) {
/* determine the type of tag */ if (p[0] & LARGE_TAG) { /* large tag */
len = (p[2] << 8) | p[1];
tag = p[0];
} else { /* small tag */
len = p[0] & 0x07;
tag = ((p[0] >> 3) & 0x0f);
}
switch (tag) {
case LARGE_TAG_MEM: if (len != 9) goto len_err;
pnpbios_encode_mem(dev, p,
pnp_get_resource(dev, IORESOURCE_MEM, mem));
mem++; break;
case LARGE_TAG_MEM32: if (len != 17) goto len_err;
pnpbios_encode_mem32(dev, p,
pnp_get_resource(dev, IORESOURCE_MEM, mem));
mem++; break;
case LARGE_TAG_FIXEDMEM32: if (len != 9) goto len_err;
pnpbios_encode_fixed_mem32(dev, p,
pnp_get_resource(dev, IORESOURCE_MEM, mem));
mem++; break;
case SMALL_TAG_IRQ: if (len < 2 || len > 3) goto len_err;
pnpbios_encode_irq(dev, p,
pnp_get_resource(dev, IORESOURCE_IRQ, irq));
irq++; break;
case SMALL_TAG_DMA: if (len != 2) goto len_err;
pnpbios_encode_dma(dev, p,
pnp_get_resource(dev, IORESOURCE_DMA, dma));
dma++; break;
case SMALL_TAG_PORT: if (len != 7) goto len_err;
pnpbios_encode_port(dev, p,
pnp_get_resource(dev, IORESOURCE_IO, port));
port++; break;
case SMALL_TAG_VENDOR: /* do nothing */ break;
case SMALL_TAG_FIXEDPORT: if (len != 3) goto len_err;
pnpbios_encode_fixed_port(dev, p,
pnp_get_resource(dev, IORESOURCE_IO, port));
port++; break;
case SMALL_TAG_END:
p = p + 2; return (unsignedchar *)p; break;
default: /* an unknown tag */
len_err:
dev_err(&dev->dev, "unknown tag %#x length %d\n",
tag, len); break;
}
/* continue to the next tag */ if (p[0] & LARGE_TAG)
p += len + 3; else
p += len + 1;
}
dev_err(&dev->dev, "no end tag in resource structure\n");
p = pnpbios_parse_allocated_resource_data(dev, p, end); if (!p) return -EIO;
p = pnpbios_parse_resource_option_data(p, end, dev); if (!p) return -EIO;
p = pnpbios_parse_compatible_ids(p, end, dev); if (!p) return -EIO; return 0;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.