in isapnp/core.c [563:694]
static int __init isapnp_create_device(struct pnp_card *card,
unsigned short size)
{
int number = 0, skip = 0, priority, compat = 0;
unsigned char type, tmp[17];
unsigned int option_flags;
struct pnp_dev *dev;
u32 eisa_id;
char id[8];
if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
return 1;
option_flags = 0;
pnp_add_card_device(card, dev);
while (1) {
if (isapnp_read_tag(&type, &size) < 0)
return 1;
if (skip && type != _STAG_LOGDEVID && type != _STAG_END)
goto __skip;
switch (type) {
case _STAG_LOGDEVID:
if (size >= 5 && size <= 6) {
if ((dev =
isapnp_parse_device(card, size,
number++)) == NULL)
return 1;
size = 0;
skip = 0;
option_flags = 0;
pnp_add_card_device(card, dev);
} else {
skip = 1;
}
compat = 0;
break;
case _STAG_COMPATDEVID:
if (size == 4 && compat < DEVICE_COUNT_COMPATIBLE) {
isapnp_peek(tmp, 4);
eisa_id = tmp[0] | tmp[1] << 8 |
tmp[2] << 16 | tmp[3] << 24;
pnp_eisa_id_to_string(eisa_id, id);
pnp_add_id(dev, id);
compat++;
size = 0;
}
break;
case _STAG_IRQ:
if (size < 2 || size > 3)
goto __skip;
isapnp_parse_irq_resource(dev, option_flags, size);
size = 0;
break;
case _STAG_DMA:
if (size != 2)
goto __skip;
isapnp_parse_dma_resource(dev, option_flags, size);
size = 0;
break;
case _STAG_STARTDEP:
if (size > 1)
goto __skip;
priority = PNP_RES_PRIORITY_ACCEPTABLE;
if (size > 0) {
isapnp_peek(tmp, size);
priority = tmp[0];
size = 0;
}
option_flags = pnp_new_dependent_set(dev, priority);
break;
case _STAG_ENDDEP:
if (size != 0)
goto __skip;
option_flags = 0;
break;
case _STAG_IOPORT:
if (size != 7)
goto __skip;
isapnp_parse_port_resource(dev, option_flags, size);
size = 0;
break;
case _STAG_FIXEDIO:
if (size != 3)
goto __skip;
isapnp_parse_fixed_port_resource(dev, option_flags,
size);
size = 0;
break;
case _STAG_VENDOR:
break;
case _LTAG_MEMRANGE:
if (size != 9)
goto __skip;
isapnp_parse_mem_resource(dev, option_flags, size);
size = 0;
break;
case _LTAG_ANSISTR:
isapnp_parse_name(dev->name, sizeof(dev->name), &size);
break;
case _LTAG_UNICODESTR:
/* silently ignore */
/* who use unicode for hardware identification? */
break;
case _LTAG_VENDOR:
break;
case _LTAG_MEM32RANGE:
if (size != 17)
goto __skip;
isapnp_parse_mem32_resource(dev, option_flags, size);
size = 0;
break;
case _LTAG_FIXEDMEM32RANGE:
if (size != 9)
goto __skip;
isapnp_parse_fixed_mem32_resource(dev, option_flags,
size);
size = 0;
break;
case _STAG_END:
if (size > 0)
isapnp_skip_bytes(size);
return 1;
default:
dev_err(&dev->dev, "unknown tag %#x (card %i), "
"ignored\n", type, card->number);
}
__skip:
if (size > 0)
isapnp_skip_bytes(size);
}
return 0;
}