static unsigned long um_pci_cfgspace_read()

in drivers/virt-pci.c [171:232]


static unsigned long um_pci_cfgspace_read(void *priv, unsigned int offset,
					  int size)
{
	struct um_pci_device_reg *reg = priv;
	struct um_pci_device *dev = reg->dev;
	struct virtio_pcidev_msg hdr = {
		.op = VIRTIO_PCIDEV_OP_CFG_READ,
		.size = size,
		.addr = offset,
	};
	/* buf->data is maximum size - we may only use parts of it */
	struct um_pci_message_buffer *buf;
	u8 *data;
	unsigned long ret = ULONG_MAX;

	if (!dev)
		return ULONG_MAX;

	buf = get_cpu_var(um_pci_msg_bufs);
	data = buf->data;

	memset(buf->data, 0xff, sizeof(buf->data));

	switch (size) {
	case 1:
	case 2:
	case 4:
#ifdef CONFIG_64BIT
	case 8:
#endif
		break;
	default:
		WARN(1, "invalid config space read size %d\n", size);
		goto out;
	}

	if (um_pci_send_cmd(dev, &hdr, sizeof(hdr), NULL, 0, data, 8))
		goto out;

	switch (size) {
	case 1:
		ret = data[0];
		break;
	case 2:
		ret = le16_to_cpup((void *)data);
		break;
	case 4:
		ret = le32_to_cpup((void *)data);
		break;
#ifdef CONFIG_64BIT
	case 8:
		ret = le64_to_cpup((void *)data);
		break;
#endif
	default:
		break;
	}

out:
	put_cpu_var(um_pci_msg_bufs);
	return ret;
}