--- /dev/null
+#include "kvm/blk-virtio.h"
+
+#include "kvm/ioport.h"
+#include "kvm/pci.h"
+
+#define PCI_VENDOR_ID_REDHAT_QUMRANET 0x1af4
+#define PCI_DEVICE_ID_VIRTIO_BLK 0x1001
+#define PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET 0x1af4
+#define PCI_SUBSYSTEM_ID_VIRTIO_BLK 0x0002
+
+static struct pci_device_header virtio_device = {
+ .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
+ .device_id = PCI_DEVICE_ID_VIRTIO_BLK,
+ .header_type = PCI_HEADER_TYPE_NORMAL,
+ .revision_id = 0,
+ .class = 0x010000,
+ .subsys_vendor_id = PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET,
+ .subsys_id = PCI_SUBSYSTEM_ID_VIRTIO_BLK,
+ .bar[0] = IOPORT_VIRTIO | PCI_BASE_ADDRESS_SPACE_IO,
+};
+
+static bool virtio_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
+{
+ return true;
+}
+
+static bool virtio_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
+{
+ return true;
+}
+
+static struct ioport_operations virtio_io_ops = {
+ .io_in = virtio_in,
+ .io_out = virtio_out,
+};
+
+void blk_virtio__init(void)
+{
+ pci__register(&virtio_device, 1);
+
+ ioport__register(IOPORT_VIRTIO, &virtio_io_ops);
+}
#include "kvm/ioport.h"
#include "kvm/util.h"
+#include <assert.h>
#include <stdint.h>
-static struct pci_config_address pci_config_address;
+#define PCI_MAX_DEVICES 256
+
+static struct pci_device_header *pci_devices[PCI_MAX_DEVICES];
+
+static struct pci_config_address pci_config_address;
static void *pci_config_address_ptr(uint16_t port)
{
return true;
}
-#define PCI_VENDOR_ID_REDHAT_QUMRANET 0x1af4
-#define PCI_DEVICE_ID_VIRTIO_BLK 0x1001
-#define PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET 0x1af4
-#define PCI_SUBSYSTEM_ID_VIRTIO_BLK 0x0002
-
-static struct pci_device_header virtio_device = {
- .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
- .device_id = PCI_DEVICE_ID_VIRTIO_BLK,
- .header_type = PCI_HEADER_TYPE_NORMAL,
- .revision_id = 0,
- .class = 0x010000,
- .subsys_vendor_id = PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET,
- .subsys_id = PCI_SUBSYSTEM_ID_VIRTIO_BLK,
- .bar[0] = IOPORT_VIRTIO | PCI_BASE_ADDRESS_SPACE_IO,
-};
-
-static bool pci_device_matches(uint8_t bus_number, uint8_t device_number, uint8_t function_number)
+static bool pci_device_exists(uint8_t bus_number, uint8_t device_number, uint8_t function_number)
{
+ struct pci_device_header *dev;
+
if (pci_config_address.bus_number != bus_number)
return false;
- if (pci_config_address.device_number != device_number)
+ if (pci_config_address.function_number != function_number)
return false;
- return pci_config_address.function_number == function_number;
+ if (device_number >= PCI_MAX_DEVICES)
+ return false;
+
+ dev = pci_devices[device_number];
+
+ return dev != NULL;
}
static bool pci_config_data_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
{
unsigned long start;
+ uint8_t dev_num;
/*
* If someone accesses PCI configuration space offsets that are not
*/
start = port - PCI_CONFIG_DATA;
- if (pci_device_matches(0, 1, 0)) {
+ dev_num = pci_config_address.device_number;
+
+ if (pci_device_exists(0, dev_num, 0)) {
unsigned long offset;
offset = start + (pci_config_address.register_number << 2);
if (offset < sizeof(struct pci_device_header)) {
- void *p = &virtio_device;
+ void *p = pci_devices[dev_num];
+
memcpy(data, p + offset, size);
} else
memset(data, 0x00, size);
.io_out = pci_config_data_out,
};
-static bool virtio_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
+void pci__register(struct pci_device_header *dev, uint8_t dev_num)
{
- return true;
-}
+ assert(dev_num < PCI_MAX_DEVICES);
-static bool virtio_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
-{
- return true;
+ pci_devices[dev_num] = dev;
}
-static struct ioport_operations virtio_io_ops = {
- .io_in = virtio_in,
- .io_out = virtio_out,
-};
-
void pci__init(void)
{
- ioport__register(IOPORT_VIRTIO, &virtio_io_ops);
-
ioport__register(PCI_CONFIG_DATA + 0, &pci_config_data_ops);
ioport__register(PCI_CONFIG_DATA + 1, &pci_config_data_ops);
ioport__register(PCI_CONFIG_DATA + 2, &pci_config_data_ops);