static int __init isapnp_create_device()

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;
}